Title: [227068] trunk
Revision
227068
Author
wenson_hs...@apple.com
Date
2018-01-17 09:07:43 -0800 (Wed, 17 Jan 2018)

Log Message

Add injected bundle SPI to replace subresource URLs when dropping or pasting rich content
https://bugs.webkit.org/show_bug.cgi?id=181637
<rdar://problem/36508471>

Reviewed by Tim Horton.

Source/WebCore:

Before carrying out blob URL conversion for pasted or dropped rich content, let the editor client replace
subresource URLs in WebKit2 by calling out to new injected bundle SPI. See comments below for more detail.

Tests:  WKAttachmentTests.InjectedBundleReplaceURLsWhenPastingAttributedString
        WKAttachmentTests.InjectedBundleReplaceURLWhenPastingImage

* editing/Editor.cpp:
(WebCore::Editor::clientReplacementURLForResource):
* editing/Editor.h:

Add a new helper to call out to the editor client for a URL string to replace a given ArchiveResource. In
WebKit2, this calls out to the injected bundle's new `replacementURLForResource` SPI hook.

* editing/cocoa/WebContentReaderCocoa.mm:
(WebCore::shouldReplaceSubresourceURL):
(WebCore::replaceRichContentWithAttachments):
(WebCore::replaceSubresourceURLsWithURLsFromClient):

Add a new static helper to replace subresource URLs in the given DocumentFragment with URLs supplied by the
editor client. Additionally builds a list of ArchiveResources that have not been replaced, for use at call sites
so that we don't unnecessarily create more Blobs for ArchiveResources that have already been replaced.

(WebCore::createFragmentAndAddResources):
(WebCore::sanitizeMarkupWithArchive):

Tweak web content reading codepaths to first replace subresource URLs with editor-client-supplied URLs.

(WebCore::WebContentReader::readImage):
(WebCore::shouldConvertToBlob): Deleted.

Rename this helper to shouldReplaceSubresourceURL, blob URL replacement is no longer the only scenario in which
we replace resource URLs, but in both cases, we still want to ignore `http:`-family and `data:` URLs.

* loader/EmptyClients.cpp:
* page/EditorClient.h:

Source/WebKit:

Add new injected bundle SPI, replacementURLForResource, which clients may use to provide a replacement URL to
represent an archive resource, given the resource's data and MIME type.

* WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h:
(API::InjectedBundle::EditorClient::replacementURLForResource):
* WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h:
* WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h:

Add replacementURLForResource, and also bump the current injected bundle editor client version to 2.

* WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
(-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
* WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp:
(WebKit::InjectedBundlePageEditorClient::replacementURLForResource):
* WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h:
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::replacementURLForResource):
* WebProcess/WebCoreSupport/WebEditorClient.h:

Source/WebKitLegacy/mac:

Add a stub implementation of replacementURLForResource. See WebCore and WebKit ChangeLogs for more detail.

* WebCoreSupport/WebEditorClient.h:
* WebCoreSupport/WebEditorClient.mm:
(WebEditorClient::replacementURLForResource):

Source/WebKitLegacy/win:

Add a stub implementation of replacementURLForResource. See WebCore and WebKit ChangeLogs for more detail.

* WebCoreSupport/WebEditorClient.cpp:
(WebEditorClient::replacementURLForResource):
* WebCoreSupport/WebEditorClient.h:

Tools:

Add 2 new API tests to exercise injected bundle SPI for supplying replacement URLs when pasting an image, and an
attributed string containing multiple NSTextAttachments. See WebKit and WebCore ChangeLogs for more detail.

* TestWebKitAPI/Tests/WebKitCocoa/BundleEditingDelegatePlugIn.mm:
(-[BundleEditingDelegatePlugIn webProcessPlugIn:didCreateBrowserContextController:]):
(-[BundleEditingDelegatePlugIn _webProcessPlugInBrowserContextController:replacementURLForResource:mimeType:]):

Implement the new Objective-C bundle SPI to look up the incoming MIME type in the dictionary supplied via the
"MIMETypeToReplacementURLMap" bundle initialization parameter, and return it.

* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(webViewForTestingAttachments):
(-[TestWKWebView tagsInBody]):
(-[TestWKWebView expectElementTagsInOrder:]):
(-[TestWKWebView expectElementTag:toComeBefore:]):

Add a test helper to check that the given list of element tags appears in the document body. Also, reimplement
the existing -expectElementTag:toComeBefore: as a special case of -expectElementTagsInOrder:.

(TestWebKitAPI::TEST):
* WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
(WTR::InjectedBundlePage::InjectedBundlePage):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (227067 => 227068)


--- trunk/Source/WebCore/ChangeLog	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebCore/ChangeLog	2018-01-17 17:07:43 UTC (rev 227068)
@@ -1,3 +1,47 @@
+2018-01-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Add injected bundle SPI to replace subresource URLs when dropping or pasting rich content
+        https://bugs.webkit.org/show_bug.cgi?id=181637
+        <rdar://problem/36508471>
+
+        Reviewed by Tim Horton.
+
+        Before carrying out blob URL conversion for pasted or dropped rich content, let the editor client replace
+        subresource URLs in WebKit2 by calling out to new injected bundle SPI. See comments below for more detail.
+
+        Tests:  WKAttachmentTests.InjectedBundleReplaceURLsWhenPastingAttributedString
+                WKAttachmentTests.InjectedBundleReplaceURLWhenPastingImage
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::clientReplacementURLForResource):
+        * editing/Editor.h:
+
+        Add a new helper to call out to the editor client for a URL string to replace a given ArchiveResource. In
+        WebKit2, this calls out to the injected bundle's new `replacementURLForResource` SPI hook.
+
+        * editing/cocoa/WebContentReaderCocoa.mm:
+        (WebCore::shouldReplaceSubresourceURL):
+        (WebCore::replaceRichContentWithAttachments):
+        (WebCore::replaceSubresourceURLsWithURLsFromClient):
+
+        Add a new static helper to replace subresource URLs in the given DocumentFragment with URLs supplied by the
+        editor client. Additionally builds a list of ArchiveResources that have not been replaced, for use at call sites
+        so that we don't unnecessarily create more Blobs for ArchiveResources that have already been replaced.
+
+        (WebCore::createFragmentAndAddResources):
+        (WebCore::sanitizeMarkupWithArchive):
+
+        Tweak web content reading codepaths to first replace subresource URLs with editor-client-supplied URLs.
+
+        (WebCore::WebContentReader::readImage):
+        (WebCore::shouldConvertToBlob): Deleted.
+
+        Rename this helper to shouldReplaceSubresourceURL, blob URL replacement is no longer the only scenario in which
+        we replace resource URLs, but in both cases, we still want to ignore `http:`-family and `data:` URLs.
+
+        * loader/EmptyClients.cpp:
+        * page/EditorClient.h:
+
 2018-01-17  Yacine Bandou  <yacine.bandou_...@softathome.com>
         [EME][GStreamer] Add the full-sample encryption support in the GStreamer ClearKey decryptor
         https://bugs.webkit.org/show_bug.cgi?id=180080

Modified: trunk/Source/WebCore/editing/Editor.cpp (227067 => 227068)


--- trunk/Source/WebCore/editing/Editor.cpp	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebCore/editing/Editor.cpp	2018-01-17 17:07:43 UTC (rev 227068)
@@ -3961,4 +3961,12 @@
     return font;
 }
 
+String Editor::clientReplacementURLForResource(Ref<SharedBuffer>&& resourceData, const String& mimeType)
+{
+    if (auto* editorClient = client())
+        return editorClient->replacementURLForResource(WTFMove(resourceData), mimeType);
+
+    return { };
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/editing/Editor.h (227067 => 227068)


--- trunk/Source/WebCore/editing/Editor.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebCore/editing/Editor.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -484,6 +484,8 @@
     WEBCORE_EXPORT void replaceSelectionWithAttributedString(NSAttributedString *, MailBlockquoteHandling = MailBlockquoteHandling::RespectBlockquote);
 #endif
 
+    String clientReplacementURLForResource(Ref<SharedBuffer>&& resourceData, const String& mimeType);
+
 #if !PLATFORM(WIN)
     WEBCORE_EXPORT void writeSelectionToPasteboard(Pasteboard&);
     WEBCORE_EXPORT void writeImageToPasteboard(Pasteboard&, Element& imageElement, const URL&, const String& title);

Modified: trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm (227067 => 227068)


--- trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-01-17 17:07:43 UTC (rev 227068)
@@ -175,7 +175,7 @@
 };
 
 
-static bool shouldConvertToBlob(const URL& url)
+static bool shouldReplaceSubresourceURL(const URL& url)
 {
     return !(url.protocolIsInHTTPFamily() || url.protocolIsData());
 }
@@ -223,7 +223,7 @@
     HashMap<AtomicString, Ref<Blob>> urlToBlobMap;
     for (const Ref<ArchiveResource>& subresource : subresources) {
         auto& url = ""
-        if (shouldConvertToBlob(url))
+        if (shouldReplaceSubresourceURL(url))
             urlToBlobMap.set(url.string(), Blob::create(subresource->data(), subresource->mimeType()));
     }
 
@@ -286,7 +286,31 @@
 #endif
 }
 
+static void replaceSubresourceURLsWithURLsFromClient(DocumentFragment& fragment, const Vector<Ref<ArchiveResource>>& subresources, Vector<Ref<ArchiveResource>>& outUnreplacedResources)
+{
+    ASSERT(fragment.document().frame());
+    auto& frame = *fragment.document().frame();
+    HashMap<AtomicString, AtomicString> subresourceURLToClientURLMap;
+    for (auto& subresource : subresources) {
+        auto& originalURL = subresource->url();
+        if (!shouldReplaceSubresourceURL(originalURL)) {
+            outUnreplacedResources.append(subresource.copyRef());
+            continue;
+        }
 
+        auto replacementURL = frame.editor().clientReplacementURLForResource(subresource->data(), subresource->mimeType());
+        if (replacementURL.isEmpty()) {
+            outUnreplacedResources.append(subresource.copyRef());
+            continue;
+        }
+
+        subresourceURLToClientURLMap.set(originalURL.string(), replacementURL);
+    }
+
+    if (!subresourceURLToClientURLMap.isEmpty())
+        replaceSubresourceURLs(fragment, WTFMove(subresourceURLToClientURLMap));
+}
+
 RefPtr<DocumentFragment> createFragmentAndAddResources(Frame& frame, NSAttributedString *string)
 {
     if (!frame.page() || !frame.document())
@@ -309,13 +333,16 @@
         return WTFMove(fragmentAndResources.fragment);
     }
 
+    Vector<Ref<ArchiveResource>> unreplacedResources;
+    replaceSubresourceURLsWithURLsFromClient(*fragmentAndResources.fragment, fragmentAndResources.resources, unreplacedResources);
+
     if (shouldReplaceRichContentWithAttachments()) {
-        replaceRichContentWithAttachments(*fragmentAndResources.fragment, fragmentAndResources.resources);
+        replaceRichContentWithAttachments(*fragmentAndResources.fragment, unreplacedResources);
         return WTFMove(fragmentAndResources.fragment);
     }
 
     HashMap<AtomicString, AtomicString> blobURLMap;
-    for (const Ref<ArchiveResource>& subresource : fragmentAndResources.resources) {
+    for (const Ref<ArchiveResource>& subresource : unreplacedResources) {
         auto blob = Blob::create(subresource->data(), subresource->mimeType());
         String blobURL = DOMURL::createObjectURL(document, blob);
         blobURLMap.set(subresource->url().string(), blobURL);
@@ -366,15 +393,18 @@
     ASSERT(stagingDocument);
     auto fragment = createFragmentFromMarkup(*stagingDocument, markupAndArchive.markup, markupAndArchive.mainResource->url(), DisallowScriptingAndPluginContent);
 
+    Vector<Ref<ArchiveResource>> unreplacedResources;
+    replaceSubresourceURLsWithURLsFromClient(fragment, markupAndArchive.archive->subresources(), unreplacedResources);
+
     if (shouldReplaceRichContentWithAttachments()) {
-        replaceRichContentWithAttachments(fragment, markupAndArchive.archive->subresources());
+        replaceRichContentWithAttachments(fragment, unreplacedResources);
         return markupForFragmentInDocument(WTFMove(fragment), *stagingDocument);
     }
 
     HashMap<AtomicString, AtomicString> blobURLMap;
-    for (const Ref<ArchiveResource>& subresource : markupAndArchive.archive->subresources()) {
+    for (const Ref<ArchiveResource>& subresource : unreplacedResources) {
         auto& subresourceURL = subresource->url();
-        if (!shouldConvertToBlob(subresourceURL))
+        if (!shouldReplaceSubresourceURL(subresourceURL))
             continue;
         auto blob = Blob::create(subresource->data(), subresource->mimeType());
         String blobURL = DOMURL::createObjectURL(destinationDocument, blob);
@@ -392,7 +422,7 @@
             continue;
 
         auto subframeURL = subframeMainResource->url();
-        if (!shouldConvertToBlob(subframeURL))
+        if (!shouldReplaceSubresourceURL(subframeURL))
             continue;
 
         MarkupAndArchive subframeContent = { String::fromUTF8(subframeMainResource->data().data(), subframeMainResource->data().size()),
@@ -581,10 +611,16 @@
 
 bool WebContentReader::readImage(Ref<SharedBuffer>&& buffer, const String& type)
 {
-    auto blob = Blob::create(buffer.get(), type);
     ASSERT(frame.document());
     auto& document = *frame.document();
 
+    auto replacementURL = frame.editor().clientReplacementURLForResource(buffer.copyRef(), type);
+    if (!replacementURL.isEmpty()) {
+        addFragment(createFragmentForImageAndURL(document, replacementURL));
+        return true;
+    }
+
+    auto blob = Blob::create(buffer.get(), type);
     if (shouldReplaceRichContentWithAttachments())
         addFragment(createFragmentForImageAttachment(document, WTFMove(blob)));
     else

Modified: trunk/Source/WebCore/loader/EmptyClients.cpp (227067 => 227068)


--- trunk/Source/WebCore/loader/EmptyClients.cpp	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebCore/loader/EmptyClients.cpp	2018-01-17 17:07:43 UTC (rev 227068)
@@ -176,6 +176,7 @@
     void willWriteSelectionToPasteboard(Range*) final { }
     void didWriteSelectionToPasteboard() final { }
     void getClientPasteboardDataForRange(Range*, Vector<String>&, Vector<RefPtr<SharedBuffer>>&) final { }
+    String replacementURLForResource(Ref<SharedBuffer>&&, const String&) final { return { }; }
     void requestCandidatesForSelection(const VisibleSelection&) final { }
     void handleAcceptedCandidateWithSoftSpaces(TextCheckingResult) final { }
 

Modified: trunk/Source/WebCore/page/EditorClient.h (227067 => 227068)


--- trunk/Source/WebCore/page/EditorClient.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebCore/page/EditorClient.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -86,6 +86,7 @@
     virtual void willWriteSelectionToPasteboard(Range*) = 0;
     virtual void didWriteSelectionToPasteboard() = 0;
     virtual void getClientPasteboardDataForRange(Range*, Vector<String>& pasteboardTypes, Vector<RefPtr<SharedBuffer>>& pasteboardData) = 0;
+    virtual String replacementURLForResource(Ref<SharedBuffer>&& resourceData, const String& mimeType) = 0;
     virtual void requestCandidatesForSelection(const VisibleSelection&) { }
     virtual void handleAcceptedCandidateWithSoftSpaces(TextCheckingResult) { }
 

Modified: trunk/Source/WebKit/ChangeLog (227067 => 227068)


--- trunk/Source/WebKit/ChangeLog	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/ChangeLog	2018-01-17 17:07:43 UTC (rev 227068)
@@ -1,3 +1,30 @@
+2018-01-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Add injected bundle SPI to replace subresource URLs when dropping or pasting rich content
+        https://bugs.webkit.org/show_bug.cgi?id=181637
+        <rdar://problem/36508471>
+
+        Reviewed by Tim Horton.
+
+        Add new injected bundle SPI, replacementURLForResource, which clients may use to provide a replacement URL to
+        represent an archive resource, given the resource's data and MIME type.
+
+        * WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h:
+        (API::InjectedBundle::EditorClient::replacementURLForResource):
+        * WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h:
+        * WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h:
+
+        Add replacementURLForResource, and also bump the current injected bundle editor client version to 2.
+
+        * WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm:
+        (-[WKWebProcessPlugInBrowserContextController _setEditingDelegate:]):
+        * WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp:
+        (WebKit::InjectedBundlePageEditorClient::replacementURLForResource):
+        * WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h:
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::replacementURLForResource):
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+
 2018-01-17  Zan Dobersek  <zdober...@igalia.com>
 
         [Cairo] Don't mirror global alpha and image interpolation quality state values in PlatformContextCairo

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/APIInjectedBundleEditorClient.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -28,6 +28,7 @@
 #include <WebCore/EditorInsertAction.h>
 #include <WebCore/TextAffinity.h>
 #include <wtf/Forward.h>
+#include <wtf/text/WTFString.h>
 
 namespace WebCore {
 class CSSStyleDeclaration;
@@ -64,6 +65,7 @@
     virtual void getPasteboardDataForRange(WebKit::WebPage&, WebCore::Range*, Vector<WTF::String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) { }
     virtual void didWriteToPasteboard(WebKit::WebPage&) { }
     virtual bool performTwoStepDrop(WebKit::WebPage&, WebCore::DocumentFragment&, WebCore::Range&, bool) { return false; }
+    virtual WTF::String replacementURLForResource(WebKit::WebPage&, Ref<WebCore::SharedBuffer>&&, const WTF::String&) { return { }; }
 };
 
 } // namespace InjectedBundle

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/Cocoa/WKWebProcessPlugInEditingDelegate.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -61,6 +61,7 @@
 - (NSDictionary<NSString *, NSData *> *)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller pasteboardDataForRange:(WKWebProcessPlugInRangeHandle *)range;
 - (void)_webProcessPlugInBrowserContextControllerDidWriteToPasteboard:(WKWebProcessPlugInBrowserContextController *)controller;
 - (BOOL)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller performTwoStepDrop:(WKWebProcessPlugInNodeHandle *)fragment atDestination:(WKWebProcessPlugInRangeHandle *)destination isMove:(BOOL)isMove WK_API_AVAILABLE(macosx(10.13), ios(11.0));
+- (NSString *)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller replacementURLForResource:(NSData *)resourceData mimeType:(NSString *)mimeType WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @end
 

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/c/WKBundlePageEditorClient.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -62,6 +62,7 @@
 typedef void (*WKBundlePageEditingNotification)(WKBundlePageRef page, WKStringRef notificationName, const void* clientInfo);
 typedef void (*WKBundlePageWillWriteToPasteboard)(WKBundlePageRef page, WKBundleRangeHandleRef range,  const void* clientInfo);
 typedef void (*WKBundlePageGetPasteboardDataForRange)(WKBundlePageRef page, WKBundleRangeHandleRef range, WKArrayRef* pasteboardTypes, WKArrayRef* pasteboardData, const void* clientInfo);
+typedef WKStringRef (*WKBundlePageReplacementURLForResource)(WKBundlePageRef, WKDataRef resourceData, WKStringRef mimeType, const void* clientInfo);
 typedef void (*WKBundlePageDidWriteToPasteboard)(WKBundlePageRef page, const void* clientInfo);
 typedef bool (*WKBundlePagePerformTwoStepDrop)(WKBundlePageRef page, WKBundleNodeHandleRef fragment, WKBundleRangeHandleRef destination, bool isMove, const void* clientInfo);
 
@@ -110,4 +111,30 @@
     WKBundlePagePerformTwoStepDrop                                      performTwoStepDrop;
 } WKBundlePageEditorClientV1;
 
+typedef struct WKBundlePageEditorClientV2 {
+    WKBundlePageEditorClientBase                                        base;
+
+    // Version 0.
+    WKBundlePageShouldBeginEditingCallback                              shouldBeginEditing;
+    WKBundlePageShouldEndEditingCallback                                shouldEndEditing;
+    WKBundlePageShouldInsertNodeCallback                                shouldInsertNode;
+    WKBundlePageShouldInsertTextCallback                                shouldInsertText;
+    WKBundlePageShouldDeleteRangeCallback                               shouldDeleteRange;
+    WKBundlePageShouldChangeSelectedRange                               shouldChangeSelectedRange;
+    WKBundlePageShouldApplyStyle                                        shouldApplyStyle;
+    WKBundlePageEditingNotification                                     didBeginEditing;
+    WKBundlePageEditingNotification                                     didEndEditing;
+    WKBundlePageEditingNotification                                     didChange;
+    WKBundlePageEditingNotification                                     didChangeSelection;
+
+    // Version 1.
+    WKBundlePageWillWriteToPasteboard                                   willWriteToPasteboard;
+    WKBundlePageGetPasteboardDataForRange                               getPasteboardDataForRange;
+    WKBundlePageDidWriteToPasteboard                                    didWriteToPasteboard;
+    WKBundlePagePerformTwoStepDrop                                      performTwoStepDrop;
+
+    // Version 2.
+    WKBundlePageReplacementURLForResource                               replacementURLForResource;
+} WKBundlePageEditorClientV2;
+
 #endif // WKBundlePageEditorClient_h

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/API/mac/WKWebProcessPlugInBrowserContextController.mm	2018-01-17 17:07:43 UTC (rev 227068)
@@ -678,6 +678,16 @@
             return [m_controller->_editingDelegate.get() _webProcessPlugInBrowserContextController:m_controller performTwoStepDrop:wrapper(*nodeHandle) atDestination:wrapper(*rangeHandle) isMove:isMove];
         }
 
+        WTF::String replacementURLForResource(WebKit::WebPage&, Ref<WebCore::SharedBuffer>&& resourceData, const WTF::String& mimeType)
+        {
+            if (!m_delegateMethods.replacementURLForResource)
+                return { };
+
+            NSString *type = (NSString *)mimeType;
+            auto data = ""
+            return [m_controller->_editingDelegate.get() _webProcessPlugInBrowserContextController:m_controller replacementURLForResource:data.get() mimeType:type];
+        }
+
         WKWebProcessPlugInBrowserContextController *m_controller;
         const struct DelegateMethods {
             DelegateMethods(RetainPtr<id <WKWebProcessPlugInEditingDelegate>> delegate)
@@ -688,6 +698,7 @@
                 , getPasteboardDataForRange([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextController:pasteboardDataForRange:)])
                 , didWriteToPasteboard([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextControllerDidWriteToPasteboard:)])
                 , performTwoStepDrop([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextController:performTwoStepDrop:atDestination:isMove:)])
+                , replacementURLForResource([delegate respondsToSelector:@selector(_webProcessPlugInBrowserContextController:replacementURLForResource:mimeType:)])
             {
             }
 
@@ -698,6 +709,7 @@
             bool getPasteboardDataForRange;
             bool didWriteToPasteboard;
             bool performTwoStepDrop;
+            bool replacementURLForResource;
         } m_delegateMethods;
     };
 

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.cpp	2018-01-17 17:07:43 UTC (rev 227068)
@@ -33,6 +33,8 @@
 #include "InjectedBundleRangeHandle.h"
 #include "WKAPICast.h"
 #include "WKBundleAPICast.h"
+#include "WKData.h"
+#include "WKRetainPtr.h"
 #include "WKString.h"
 #include "WebPage.h"
 #include <WebCore/DocumentFragment.h>
@@ -189,4 +191,14 @@
         m_client.didWriteToPasteboard(toAPI(&page), m_client.base.clientInfo);
 }
 
+String InjectedBundlePageEditorClient::replacementURLForResource(WebPage& page, Ref<SharedBuffer>&& resourceData, const String& mimeType)
+{
+    if (!m_client.replacementURLForResource)
+        return { };
+
+    auto data = "" unsigned char*>(resourceData->data()), resourceData->size()));
+    auto type = adoptWK(toCopiedAPI(mimeType));
+    return toWTFString(m_client.replacementURLForResource(toAPI(&page), data.get(), type.get(), m_client.base.clientInfo));
+}
+
 } // namespace WebKit

Modified: trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/InjectedBundle/InjectedBundlePageEditorClient.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -31,7 +31,7 @@
 
 namespace API {
 template<> struct ClientTraits<WKBundlePageEditorClientBase> {
-    typedef std::tuple<WKBundlePageEditorClientV0, WKBundlePageEditorClientV1> Versions;
+    typedef std::tuple<WKBundlePageEditorClientV0, WKBundlePageEditorClientV1, WKBundlePageEditorClientV2> Versions;
 };
 }
 
@@ -67,6 +67,7 @@
     void getPasteboardDataForRange(WebPage&, WebCore::Range*, Vector<String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) final;
     void didWriteToPasteboard(WebPage&) final;
     bool performTwoStepDrop(WebPage&, WebCore::DocumentFragment&, WebCore::Range& destination, bool isMove) final;
+    String replacementURLForResource(WebPage&, Ref<WebCore::SharedBuffer>&& resourceData, const String&) final;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp	2018-01-17 17:07:43 UTC (rev 227068)
@@ -263,6 +263,11 @@
     return m_page->injectedBundleEditorClient().performTwoStepDrop(*m_page, fragment, destination, isMove);
 }
 
+String WebEditorClient::replacementURLForResource(Ref<WebCore::SharedBuffer>&& resourceData, const String& mimeType)
+{
+    return m_page->injectedBundleEditorClient().replacementURLForResource(*m_page, WTFMove(resourceData), mimeType);
+}
+
 void WebEditorClient::registerUndoStep(UndoStep& step)
 {
     // FIXME: Add assertion that the command being reapplied is the same command that is

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h (227067 => 227068)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -76,6 +76,7 @@
     void willWriteSelectionToPasteboard(WebCore::Range*) final;
     void didWriteSelectionToPasteboard() final;
     void getClientPasteboardDataForRange(WebCore::Range*, Vector<String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) final;
+    String replacementURLForResource(Ref<WebCore::SharedBuffer>&& resourceData, const String& mimeType) final;
     
     void registerUndoStep(WebCore::UndoStep&) final;
     void registerRedoStep(WebCore::UndoStep&) final;

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (227067 => 227068)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2018-01-17 17:07:43 UTC (rev 227068)
@@ -1,3 +1,17 @@
+2018-01-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Add injected bundle SPI to replace subresource URLs when dropping or pasting rich content
+        https://bugs.webkit.org/show_bug.cgi?id=181637
+        <rdar://problem/36508471>
+
+        Reviewed by Tim Horton.
+
+        Add a stub implementation of replacementURLForResource. See WebCore and WebKit ChangeLogs for more detail.
+
+        * WebCoreSupport/WebEditorClient.h:
+        * WebCoreSupport/WebEditorClient.mm:
+        (WebEditorClient::replacementURLForResource):
+
 2018-01-11  Keith Miller  <keith_mil...@apple.com>
 
         Rename ENABLE_ASYNC_ITERATION to ENABLE_JS_ASYNC_ITERATION

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h (227067 => 227068)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -78,6 +78,7 @@
     void willWriteSelectionToPasteboard(WebCore::Range*) final;
     void didWriteSelectionToPasteboard() final;
     void getClientPasteboardDataForRange(WebCore::Range*, Vector<String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) final;
+    String replacementURLForResource(Ref<WebCore::SharedBuffer>&& resourceData, const String& mimeType) final;
 
     void setInsertionPasteboard(const String&) final;
 

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm (227067 => 227068)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.mm	2018-01-17 17:07:43 UTC (rev 227068)
@@ -419,6 +419,12 @@
     // Not implemented WebKit, only WebKit2.
 }
 
+String WebEditorClient::replacementURLForResource(Ref<SharedBuffer>&&, const String&)
+{
+    // Not implemented in WebKitLegacy.
+    return { };
+}
+
 #if (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300)
 
 // FIXME: Remove both this stub and the real version of this function below once we don't need the real version on any supported platform.

Modified: trunk/Source/WebKitLegacy/win/ChangeLog (227067 => 227068)


--- trunk/Source/WebKitLegacy/win/ChangeLog	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKitLegacy/win/ChangeLog	2018-01-17 17:07:43 UTC (rev 227068)
@@ -1,3 +1,17 @@
+2018-01-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Add injected bundle SPI to replace subresource URLs when dropping or pasting rich content
+        https://bugs.webkit.org/show_bug.cgi?id=181637
+        <rdar://problem/36508471>
+
+        Reviewed by Tim Horton.
+
+        Add a stub implementation of replacementURLForResource. See WebCore and WebKit ChangeLogs for more detail.
+
+        * WebCoreSupport/WebEditorClient.cpp:
+        (WebEditorClient::replacementURLForResource):
+        * WebCoreSupport/WebEditorClient.h:
+
 2017-12-28  Yusuke Suzuki  <utatane....@gmail.com>
 
         Remove std::chrono completely

Modified: trunk/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.cpp (227067 => 227068)


--- trunk/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.cpp	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.cpp	2018-01-17 17:07:43 UTC (rev 227068)
@@ -269,6 +269,12 @@
     notImplemented();
 }
 
+String WebEditorClient::replacementURLForResource(Ref<WebCore::SharedBuffer>&&, const String&)
+{
+    notImplemented();
+    return { };
+}
+
 bool WebEditorClient::shouldDeleteRange(Range* range)
 {
     COMPtr<IWebEditingDelegate> ed;

Modified: trunk/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.h (227067 => 227068)


--- trunk/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.h	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Source/WebKitLegacy/win/WebCoreSupport/WebEditorClient.h	2018-01-17 17:07:43 UTC (rev 227068)
@@ -54,6 +54,7 @@
     void willWriteSelectionToPasteboard(WebCore::Range*) final;
     void didWriteSelectionToPasteboard() final;
     void getClientPasteboardDataForRange(WebCore::Range*, Vector<String>& pasteboardTypes, Vector<RefPtr<WebCore::SharedBuffer>>& pasteboardData) final;
+    String replacementURLForResource(Ref<WebCore::SharedBuffer>&&, const String&) final;
 
     void didEndUserTriggeredSelectionChanges() final { }
     void respondToChangedContents() final;

Modified: trunk/Tools/ChangeLog (227067 => 227068)


--- trunk/Tools/ChangeLog	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Tools/ChangeLog	2018-01-17 17:07:43 UTC (rev 227068)
@@ -1,3 +1,34 @@
+2018-01-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Add injected bundle SPI to replace subresource URLs when dropping or pasting rich content
+        https://bugs.webkit.org/show_bug.cgi?id=181637
+        <rdar://problem/36508471>
+
+        Reviewed by Tim Horton.
+
+        Add 2 new API tests to exercise injected bundle SPI for supplying replacement URLs when pasting an image, and an
+        attributed string containing multiple NSTextAttachments. See WebKit and WebCore ChangeLogs for more detail.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/BundleEditingDelegatePlugIn.mm:
+        (-[BundleEditingDelegatePlugIn webProcessPlugIn:didCreateBrowserContextController:]):
+        (-[BundleEditingDelegatePlugIn _webProcessPlugInBrowserContextController:replacementURLForResource:mimeType:]):
+
+        Implement the new Objective-C bundle SPI to look up the incoming MIME type in the dictionary supplied via the
+        "MIMETypeToReplacementURLMap" bundle initialization parameter, and return it.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+        (webViewForTestingAttachments):
+        (-[TestWKWebView tagsInBody]):
+        (-[TestWKWebView expectElementTagsInOrder:]):
+        (-[TestWKWebView expectElementTag:toComeBefore:]):
+
+        Add a test helper to check that the given list of element tags appears in the document body. Also, reimplement
+        the existing -expectElementTag:toComeBefore: as a special case of -expectElementTagsInOrder:.
+
+        (TestWebKitAPI::TEST):
+        * WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp:
+        (WTR::InjectedBundlePage::InjectedBundlePage):
+
 2018-01-17  Carlos Garcia Campos  <cgar...@igalia.com>
 
         WebDriver: add support for test expectations

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/BundleEditingDelegatePlugIn.mm (227067 => 227068)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/BundleEditingDelegatePlugIn.mm	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/BundleEditingDelegatePlugIn.mm	2018-01-17 17:07:43 UTC (rev 227068)
@@ -47,6 +47,7 @@
     RetainPtr<id <BundleEditingDelegateProtocol>> _remoteObject;
     BOOL _editingDelegateShouldInsertText;
     BOOL _shouldOverridePerformTwoStepDrop;
+    RetainPtr<NSDictionary<NSString *, NSString *>> _mimeTypeToReplacementURLMap;
 }
 
 - (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
@@ -63,6 +64,7 @@
         _editingDelegateShouldInsertText = YES;
 
     _shouldOverridePerformTwoStepDrop = [[plugInController.parameters valueForKey:@"BundleOverridePerformTwoStepDrop"] boolValue];
+    _mimeTypeToReplacementURLMap = [plugInController.parameters valueForKey:@"MIMETypeToReplacementURLMap"];
 
     _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(BundleEditingDelegateProtocol)];
     _remoteObject = [browserContextController._remoteObjectRegistry remoteObjectProxyWithInterface:interface];
@@ -98,6 +100,12 @@
     return _shouldOverridePerformTwoStepDrop;
 }
 
+- (NSString *)_webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller replacementURLForResource:(NSData *)resourceData mimeType:(NSString *)mimeType
+{
+    assert(!!resourceData);
+    return [_mimeTypeToReplacementURLMap objectForKey:mimeType];
+}
+
 @end
 
 #endif // WK_API_ENABLED

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (227067 => 227068)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2018-01-17 17:07:43 UTC (rev 227068)
@@ -28,6 +28,7 @@
 #import "DataInteractionSimulator.h"
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
+#import "WKWebViewConfigurationExtras.h"
 #import <WebKit/WKPreferencesRefPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/WebKit.h>
@@ -144,18 +145,23 @@
 @interface TestWKWebView (AttachmentTesting)
 @end
 
-static RetainPtr<TestWKWebView> webViewForTestingAttachments(CGSize webViewSize)
+static RetainPtr<TestWKWebView> webViewForTestingAttachments(CGSize webViewSize, WKWebViewConfiguration *configuration)
 {
-    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    [configuration _setAttachmentElementEnabled:YES];
+    configuration._attachmentElementEnabled = YES;
     WKPreferencesSetCustomPasteboardDataEnabled((WKPreferencesRef)[configuration preferences], YES);
 
-    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, webViewSize.width, webViewSize.height) configuration:configuration.get()]);
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, webViewSize.width, webViewSize.height) configuration:configuration]);
     [webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width, initial-scale=1'><script>focus = () => document.body.focus()</script><body _onload_=focus() contenteditable></body>"];
 
     return webView;
 }
 
+static RetainPtr<TestWKWebView> webViewForTestingAttachments(CGSize webViewSize)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    return webViewForTestingAttachments(webViewSize, configuration.get());
+}
+
 static RetainPtr<TestWKWebView> webViewForTestingAttachments()
 {
     return webViewForTestingAttachments(CGSizeMake(500, 500));
@@ -207,22 +213,31 @@
 
 @implementation TestWKWebView (AttachmentTesting)
 
-- (void)expectElementTag:(NSString *)tagName toComeBefore:(NSString *)otherTagName
+- (NSArray<NSString *> *)tagsInBody
 {
-    NSArray *tagsInBody = [self objectByEvaluatingJavaScript:@"Array.from(document.body.getElementsByTagName('*')).map(e => e.tagName)"];
-    BOOL success = [tagsInBody containsObject:tagName] && [tagsInBody containsObject:otherTagName];
-    if (success) {
-        NSUInteger index = [tagsInBody indexOfObject:tagName];
-        NSUInteger otherIndex = [tagsInBody indexOfObjectWithOptions:NSEnumerationReverse passingTest:[&] (NSString *tag, NSUInteger, BOOL *) {
-            return [tag isEqualToString:otherTagName];
-        }];
-        success = index < otherIndex;
+    return [self objectByEvaluatingJavaScript:@"Array.from(document.body.getElementsByTagName('*')).map(e => e.tagName)"];
+}
+
+- (void)expectElementTagsInOrder:(NSArray<NSString *> *)tagNames
+{
+    auto remainingTags = adoptNS([tagNames mutableCopy]);
+    NSArray<NSString *> *tagsInBody = self.tagsInBody;
+    for (NSString *tag in tagsInBody.reverseObjectEnumerator) {
+        if ([tag isEqualToString:[remainingTags lastObject]])
+            [remainingTags removeLastObject];
+        if (![remainingTags count])
+            break;
     }
-    EXPECT_TRUE(success);
-    if (!success)
-        NSLog(@"Expected %@ to come before %@ in tags: %@", tagName, otherTagName, tagsInBody);
+    EXPECT_EQ([remainingTags count], 0U);
+    if ([remainingTags count])
+        NSLog(@"Expected to find ordered tags: %@ in: %@", tagNames, tagsInBody);
 }
 
+- (void)expectElementTag:(NSString *)tagName toComeBefore:(NSString *)otherTagName
+{
+    [self expectElementTagsInOrder:@[tagName, otherTagName]];
+}
+
 - (BOOL)_synchronouslyExecuteEditCommand:(NSString *)command argument:(NSString *)argument
 {
     __block bool done = false;
@@ -1096,6 +1111,38 @@
     [pastedAttachment expectRequestedDataToBe:originalData.get()];
 }
 
+TEST(WKAttachmentTests, InjectedBundleReplaceURLsWhenPastingAttributedString)
+{
+    platformCopyRichTextWithMultipleAttachments();
+
+    auto configuration = retainPtr([WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"]);
+    [[configuration processPool] _setObject:@{ @"image/png" : @"cid:foo-bar" } forBundleParameter:@"MIMETypeToReplacementURLMap"];
+    auto webView = webViewForTestingAttachments(CGSizeMake(500, 500), configuration.get());
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil];
+        EXPECT_EQ(2U, observer.observer().inserted.count);
+    }
+    [webView expectElementTagsInOrder:@[ @"IMG", @"ATTACHMENT", @"ATTACHMENT" ]];
+    EXPECT_WK_STREQ("cid:foo-bar", [webView valueOfAttribute:@"src" forQuerySelector:@"img"]);
+}
+
+TEST(WKAttachmentTests, InjectedBundleReplaceURLWhenPastingImage)
+{
+    platformCopyPNG();
+
+    NSString *replacementURL = @"cid:foo-bar";
+    auto configuration = retainPtr([WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"BundleEditingDelegatePlugIn"]);
+    [[configuration processPool] _setObject:@{ @"image/tiff" : replacementURL, @"image/png" : replacementURL } forBundleParameter:@"MIMETypeToReplacementURLMap"];
+    auto webView = webViewForTestingAttachments(CGSizeMake(500, 500), configuration.get());
+    {
+        ObserveAttachmentUpdatesForScope observer(webView.get());
+        [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil];
+        EXPECT_EQ(0U, observer.observer().inserted.count);
+    }
+    EXPECT_WK_STREQ("cid:foo-bar", [webView valueOfAttribute:@"src" forQuerySelector:@"img"]);
+}
+
 #pragma mark - Platform-specific tests
 
 #if PLATFORM(MAC)

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp (227067 => 227068)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp	2018-01-17 17:00:07 UTC (rev 227067)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp	2018-01-17 17:07:43 UTC (rev 227068)
@@ -358,8 +358,8 @@
     };
     WKBundlePageSetUIClient(m_page, &uiClient.base);
 
-    WKBundlePageEditorClientV1 editorClient = {
-        { 1, this },
+    WKBundlePageEditorClientV2 editorClient = {
+        { 2, this },
         shouldBeginEditing,
         shouldEndEditing,
         shouldInsertNode,
@@ -375,6 +375,7 @@
         0, /* getPasteboardDataForRange */
         0, /* didWriteToPasteboard */
         0, /* performTwoStepDrop */
+        0, /* replacementURLForResource */
     };
     WKBundlePageSetEditorClient(m_page, &editorClient.base);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to