Title: [222839] trunk
Revision
222839
Author
[email protected]
Date
2017-10-04 04:06:15 -0700 (Wed, 04 Oct 2017)

Log Message

Use blob URL when pasting RTFD instead of overriding DocumentLoader
https://bugs.webkit.org/show_bug.cgi?id=177801
<rdar://problem/34542270>

Reviewed by Wenson Hsieh.

Source/WebCore:

Before this patch, pasting RTFD resulted in images and other subresources in RTFD are being placed
into the document using WebKit fake URL, and DocumentLoader was overridden to return the appropriate
data upon resource requests. This is bad because there is no mechanism for websites to access its content.

Like r222119 and r208451, this patch fixes thie problem by using a blob URL instead of a WebKit fake URL.
This patch also adds a Blob::create variant which takes a SharedBuffer.

API Tests: PasteRTFD

* editing/WebCorePasteboardFileReader.cpp:
(WebCore::WebCorePasteboardFileReader::readBuffer):
* editing/cocoa/WebContentReaderCocoa.mm:
(WebCore::DeferredLoadingScope): Extracted out of createFragmentAndAddResources for clarity.
(WebCore::DeferredLoadingScope::DeferredLoadingScope):
(WebCore::DeferredLoadingScope::~DeferredLoadingScope):
(WebCore::createFragmentAndAddResources): Instead of adding resources to document loader, replace each
URL in the document by a blob URL.
(WebCore::WebContentReader::readImage):
* editing/markup.cpp:
(WebCore::replaceSubresourceURLs): Added. A helper to replace each URL in the document fragment by a blob
URL created for each subresource. This won't work for iframes or srcset but that's okay for now since DOM
constructed from RTFD doesn't use either.
* editing/markup.h:
* fileapi/Blob.cpp:
(WebCore::Blob::Blob): Added a variant which takes a SharedBuffer.
* fileapi/Blob.h:
(WebCore::Blob::create): Ditto.

Source/WebKit:

Fixed the assertion failure when RTFD content is empty.

* UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
(WebKit::WebPasteboardProxy::getPasteboardBufferForType):

Tools:

Added a regression test for an assertion failure when pasting an empty RTFD as well as a test for pasting
RTFD with an image, which should result in an image element with a blob URL.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm:
* TestWebKitAPI/Tests/WebKitCocoa/PasteRTFD.mm:
* TestWebKitAPI/Tests/WebKitCocoa/paste-rtfd.html:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (222838 => 222839)


--- trunk/Source/WebCore/ChangeLog	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/ChangeLog	2017-10-04 11:06:15 UTC (rev 222839)
@@ -1,3 +1,39 @@
+2017-10-04  Ryosuke Niwa  <[email protected]>
+
+        Use blob URL when pasting RTFD instead of overriding DocumentLoader
+        https://bugs.webkit.org/show_bug.cgi?id=177801
+        <rdar://problem/34542270>
+
+        Reviewed by Wenson Hsieh.
+
+        Before this patch, pasting RTFD resulted in images and other subresources in RTFD are being placed
+        into the document using WebKit fake URL, and DocumentLoader was overridden to return the appropriate
+        data upon resource requests. This is bad because there is no mechanism for websites to access its content.
+
+        Like r222119 and r208451, this patch fixes thie problem by using a blob URL instead of a WebKit fake URL.
+        This patch also adds a Blob::create variant which takes a SharedBuffer.
+
+        API Tests: PasteRTFD
+
+        * editing/WebCorePasteboardFileReader.cpp:
+        (WebCore::WebCorePasteboardFileReader::readBuffer):
+        * editing/cocoa/WebContentReaderCocoa.mm:
+        (WebCore::DeferredLoadingScope): Extracted out of createFragmentAndAddResources for clarity.
+        (WebCore::DeferredLoadingScope::DeferredLoadingScope):
+        (WebCore::DeferredLoadingScope::~DeferredLoadingScope):
+        (WebCore::createFragmentAndAddResources): Instead of adding resources to document loader, replace each
+        URL in the document by a blob URL.
+        (WebCore::WebContentReader::readImage):
+        * editing/markup.cpp:
+        (WebCore::replaceSubresourceURLs): Added. A helper to replace each URL in the document fragment by a blob
+        URL created for each subresource. This won't work for iframes or srcset but that's okay for now since DOM
+        constructed from RTFD doesn't use either.
+        * editing/markup.h:
+        * fileapi/Blob.cpp:
+        (WebCore::Blob::Blob): Added a variant which takes a SharedBuffer.
+        * fileapi/Blob.h:
+        (WebCore::Blob::create): Ditto.
+
 2017-10-04  Michael Catanzaro  <[email protected]>
 
         REGRESSION(r222392): [WPE][GTK] Many forms tests are failing due to broken event timestamps

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp (222838 => 222839)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2017-10-04 11:06:15 UTC (rev 222839)
@@ -108,7 +108,7 @@
 void FetchBodyOwner::blob(Ref<DeferredPromise>&& promise)
 {
     if (isBodyNullOrOpaque()) {
-        promise->resolve<IDLInterface<Blob>>(Blob::create({ }, Blob::normalizedContentType(extractMIMETypeFromMediaType(m_contentType))));
+        promise->resolve<IDLInterface<Blob>>(Blob::create(Vector<uint8_t> { }, Blob::normalizedContentType(extractMIMETypeFromMediaType(m_contentType))));
         return;
     }
     if (isDisturbedOrLocked()) {

Modified: trunk/Source/WebCore/editing/WebCorePasteboardFileReader.cpp (222838 => 222839)


--- trunk/Source/WebCore/editing/WebCorePasteboardFileReader.cpp	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/editing/WebCorePasteboardFileReader.cpp	2017-10-04 11:06:15 UTC (rev 222839)
@@ -40,9 +40,7 @@
 
 void WebCorePasteboardFileReader::readBuffer(const String& filename, const String& type, Ref<SharedBuffer>&& buffer)
 {
-    Vector<uint8_t> data;
-    data.append(buffer->data(), buffer->size());
-    files.append(File::create(Blob::create(WTFMove(data), type), filename));
+    files.append(File::create(Blob::create(buffer.get(), type), filename));
 }
 
 }

Modified: trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm (222838 => 222839)


--- trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2017-10-04 11:06:15 UTC (rev 222839)
@@ -122,6 +122,38 @@
 
 #endif
 
+class DeferredLoadingScope {
+public:
+    DeferredLoadingScope(Frame& frame)
+        : m_frame(frame)
+        , m_cachedResourceLoader(frame.document()->cachedResourceLoader())
+    {
+        if (!frame.page()->defersLoading()) {
+            frame.page()->setDefersLoading(true);
+            m_didEnabledDeferredLoading = true;
+        }
+
+        if (m_cachedResourceLoader->imagesEnabled()) {
+            m_cachedResourceLoader->setImagesEnabled(false);
+            m_didDisableImage = true;
+        }
+    }
+
+    ~DeferredLoadingScope()
+    {
+        if (m_didEnabledDeferredLoading)
+            m_cachedResourceLoader->setImagesEnabled(true);
+        if (m_didDisableImage)
+            m_frame->page()->setDefersLoading(false);
+    }
+
+private:
+    Ref<Frame> m_frame;
+    Ref<CachedResourceLoader> m_cachedResourceLoader;
+    bool m_didEnabledDeferredLoading { false };
+    bool m_didDisableImage { false };
+};
+
 RefPtr<DocumentFragment> createFragmentAndAddResources(Frame& frame, NSAttributedString *string)
 {
     if (!frame.page() || !frame.document())
@@ -131,26 +163,19 @@
     if (!document.isHTMLDocument() || !string)
         return nullptr;
 
-    bool wasDeferringCallbacks = frame.page()->defersLoading();
-    if (!wasDeferringCallbacks)
-        frame.page()->setDefersLoading(true);
+    DeferredLoadingScope scope(frame);
+    auto fragmentAndResources = createFragment(frame, string);
+    if (!fragmentAndResources.fragment)
+        return nullptr;
 
-    auto& cachedResourceLoader = document.cachedResourceLoader();
-    bool wasImagesEnabled = cachedResourceLoader.imagesEnabled();
-    if (wasImagesEnabled)
-        cachedResourceLoader.setImagesEnabled(false);
-
-    auto fragmentAndResources = createFragment(frame, string);
-    if (auto* loader = frame.loader().documentLoader()) {
-        for (auto& resource : fragmentAndResources.resources)
-            loader->addArchiveResource(WTFMove(resource));
+    HashMap<AtomicString, AtomicString> blobURLMap;
+    for (const Ref<ArchiveResource>& subresource : fragmentAndResources.resources) {
+        auto blob = Blob::create(subresource->data(), subresource->mimeType());
+        String blobURL = DOMURL::createObjectURL(document, blob);
+        blobURLMap.set(subresource->url().string(), blobURL);
     }
+    replaceSubresourceURLs(*fragmentAndResources.fragment, WTFMove(blobURLMap));
 
-    if (wasImagesEnabled)
-        cachedResourceLoader.setImagesEnabled(true);
-    if (!wasDeferringCallbacks)
-        frame.page()->setDefersLoading(false);
-
     return WTFMove(fragmentAndResources.fragment);
 }
 
@@ -225,9 +250,7 @@
 
 bool WebContentReader::readImage(Ref<SharedBuffer>&& buffer, const String& type)
 {
-    Vector<uint8_t> data;
-    data.append(buffer->data(), buffer->size());
-    auto blob = Blob::create(WTFMove(data), type);
+    auto blob = Blob::create(buffer.get(), type);
     ASSERT(frame.document());
     auto& document = *frame.document();
     String blobURL = DOMURL::createObjectURL(document, blob);

Modified: trunk/Source/WebCore/editing/markup.cpp (222838 => 222839)


--- trunk/Source/WebCore/editing/markup.cpp	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/editing/markup.cpp	2017-10-04 11:06:15 UTC (rev 222839)
@@ -116,6 +116,25 @@
     for (auto& change : changes)
         change.apply();
 }
+
+void replaceSubresourceURLs(Ref<DocumentFragment>&& fragment, HashMap<AtomicString, AtomicString>&& replacementMap)
+{
+    Vector<AttributeChange> changes;
+    for (auto& element : descendantsOfType<Element>(fragment)) {
+        if (!element.hasAttributes())
+            continue;
+        for (const Attribute& attribute : element.attributesIterator()) {
+            // FIXME: This won't work for srcset.
+            if (element.attributeContainsURL(attribute) && !attribute.value().isEmpty()) {
+                auto replacement = replacementMap.get(attribute.value());
+                if (!replacement.isNull())
+                    changes.append({ &element, attribute.name(), replacement });
+            }
+        }
+    }
+    for (auto& change : changes)
+        change.apply();
+}
     
 class StyledMarkupAccumulator final : public MarkupAccumulator {
 public:

Modified: trunk/Source/WebCore/editing/markup.h (222838 => 222839)


--- trunk/Source/WebCore/editing/markup.h	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/editing/markup.h	2017-10-04 11:06:15 UTC (rev 222839)
@@ -29,6 +29,7 @@
 #include "FragmentScriptingPermission.h"
 #include "HTMLInterchange.h"
 #include <wtf/Forward.h>
+#include <wtf/HashMap.h>
 
 namespace WebCore {
 
@@ -44,6 +45,8 @@
 class QualifiedName;
 class Range;
 
+void replaceSubresourceURLs(Ref<DocumentFragment>&&, HashMap<AtomicString, AtomicString>&&);
+
 enum EChildrenOnly { IncludeNode, ChildrenOnly };
 enum EAbsoluteURLs { DoNotResolveURLs, ResolveAllURLs, ResolveNonLocalURLs };
 enum EFragmentSerialization { HTMLFragmentSerialization, XMLFragmentSerialization };

Modified: trunk/Source/WebCore/fileapi/Blob.cpp (222838 => 222839)


--- trunk/Source/WebCore/fileapi/Blob.cpp	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/fileapi/Blob.cpp	2017-10-04 11:06:15 UTC (rev 222839)
@@ -36,6 +36,7 @@
 #include "BlobURL.h"
 #include "File.h"
 #include "ScriptExecutionContext.h"
+#include "SharedBuffer.h"
 #include "ThreadableBlobRegistry.h"
 #include <wtf/NeverDestroyed.h>
 #include <wtf/text/CString.h>
@@ -96,6 +97,19 @@
     ThreadableBlobRegistry::registerBlobURL(m_internalURL, builder.finalize(), m_type);
 }
 
+Blob::Blob(const SharedBuffer& buffer, const String& contentType)
+    : m_type(contentType)
+    , m_size(buffer.size())
+{
+    Vector<uint8_t> data;
+    data.append(buffer.data(), buffer.size());
+
+    Vector<BlobPart> blobParts;
+    blobParts.append(BlobPart(WTFMove(data)));
+    m_internalURL = BlobURL::createInternalURL();
+    ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
+}
+
 Blob::Blob(Vector<uint8_t>&& data, const String& contentType)
     : m_type(contentType)
     , m_size(data.size())

Modified: trunk/Source/WebCore/fileapi/Blob.h (222838 => 222839)


--- trunk/Source/WebCore/fileapi/Blob.h	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebCore/fileapi/Blob.h	2017-10-04 11:06:15 UTC (rev 222839)
@@ -45,6 +45,7 @@
 
 class Blob;
 class ScriptExecutionContext;
+class SharedBuffer;
 
 using BlobPartVariant = Variant<RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>, RefPtr<Blob>, String>;
 
@@ -60,6 +61,11 @@
         return adoptRef(*new Blob(WTFMove(blobPartVariants), propertyBag));
     }
 
+    static Ref<Blob> create(const SharedBuffer& buffer, const String& contentType)
+    {
+        return adoptRef(*new Blob(buffer, contentType));
+    }
+
     static Ref<Blob> create(Vector<uint8_t>&& data, const String& contentType)
     {
         return adoptRef(*new Blob(WTFMove(data), contentType));
@@ -99,6 +105,7 @@
 protected:
     Blob();
     Blob(Vector<BlobPartVariant>&&, const BlobPropertyBag&);
+    Blob(const SharedBuffer&, const String& contentType);
     Blob(Vector<uint8_t>&&, const String& contentType);
 
     enum ReferencingExistingBlobConstructor { referencingExistingBlobConstructor };

Modified: trunk/Source/WebKit/ChangeLog (222838 => 222839)


--- trunk/Source/WebKit/ChangeLog	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebKit/ChangeLog	2017-10-04 11:06:15 UTC (rev 222839)
@@ -1,3 +1,16 @@
+2017-10-04  Ryosuke Niwa  <[email protected]>
+
+        Use blob URL when pasting RTFD instead of overriding DocumentLoader
+        https://bugs.webkit.org/show_bug.cgi?id=177801
+        <rdar://problem/34542270>
+
+        Reviewed by Wenson Hsieh.
+
+        Fixed the assertion failure when RTFD content is empty.
+
+        * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
+        (WebKit::WebPasteboardProxy::getPasteboardBufferForType):
+
 2017-10-04  Michael Catanzaro  <[email protected]>
 
         REGRESSION(r222392): [WPE][GTK] Many forms tests are failing due to broken event timestamps

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm (222838 => 222839)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2017-10-04 11:06:15 UTC (rev 222839)
@@ -75,6 +75,8 @@
     if (!buffer)
         return;
     size = buffer->size();
+    if (!size)
+        return;
     RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(size);
     if (!sharedMemoryBuffer)
         return;

Modified: trunk/Tools/ChangeLog (222838 => 222839)


--- trunk/Tools/ChangeLog	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Tools/ChangeLog	2017-10-04 11:06:15 UTC (rev 222839)
@@ -1,3 +1,19 @@
+2017-10-04  Ryosuke Niwa  <[email protected]>
+
+        Use blob URL when pasting RTFD instead of overriding DocumentLoader
+        https://bugs.webkit.org/show_bug.cgi?id=177801
+        <rdar://problem/34542270>
+
+        Reviewed by Wenson Hsieh.
+
+        Added a regression test for an assertion failure when pasting an empty RTFD as well as a test for pasting
+        RTFD with an image, which should result in an image element with a blob URL.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm:
+        * TestWebKitAPI/Tests/WebKitCocoa/PasteRTFD.mm:
+        * TestWebKitAPI/Tests/WebKitCocoa/paste-rtfd.html:
+
 2017-10-03  Gustavo Noronha Silva  <[email protected]>
 
         [GLib] Let WebCore know of low power situations

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (222838 => 222839)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-10-04 11:06:15 UTC (rev 222839)
@@ -545,6 +545,7 @@
 		9B26FCCA159D16DE00CC3765 /* HTMLFormCollectionNamedItem.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9B26FCB4159D15E700CC3765 /* HTMLFormCollectionNamedItem.html */; };
 		9B270FEE1DDC2C0B002D53F3 /* closed-shadow-tree-test.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9B270FED1DDC25FD002D53F3 /* closed-shadow-tree-test.html */; };
 		9B4F8FA7159D52DD002D9F94 /* HTMLCollectionNamedItem.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9B4F8FA6159D52CA002D9F94 /* HTMLCollectionNamedItem.html */; };
+		9B7D740F1F8378770006C432 /* paste-rtfd.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9B7D740E1F8377E60006C432 /* paste-rtfd.html */; };
 		9BD4239A1E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BD423991E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm */; };
 		9BD4239C1E04C01C00200395 /* chinese-character-with-image.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BD4239B1E04BFD000200395 /* chinese-character-with-image.html */; };
 		9BD6D3A21F7B218300BD4962 /* sunset-in-cupertino-100px.tiff in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BD6D3A11F7B202100BD4962 /* sunset-in-cupertino-100px.tiff */; };
@@ -553,6 +554,7 @@
 		9BD6D3A51F7B218300BD4962 /* sunset-in-cupertino-600px.jpg in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BD6D39E1F7B201E00BD4962 /* sunset-in-cupertino-600px.jpg */; };
 		9BD6D3A71F7B21DC00BD4962 /* paste-image.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9BD6D3A61F7B21CC00BD4962 /* paste-image.html */; };
 		9BDCCD871F7D0B0700009A18 /* PasteImage.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDCCD851F7D0B0700009A18 /* PasteImage.mm */; };
+		9BDD95581F83683600D20C60 /* PasteRTFD.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9BDD95561F83683600D20C60 /* PasteRTFD.mm */; };
 		9C64DC321D76198A004B598E /* YouTubePluginReplacement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9C64DC311D76198A004B598E /* YouTubePluginReplacement.cpp */; };
 		A10F047E1E3AD29C00C95E19 /* NSFileManagerExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = A10F047C1E3AD29C00C95E19 /* NSFileManagerExtras.mm */; };
 		A1146A8D1D2D7115000FE710 /* ContentFiltering.mm in Sources */ = {isa = PBXBuildFile; fileRef = A1146A8A1D2D704F000FE710 /* ContentFiltering.mm */; };
@@ -978,6 +980,7 @@
 				A57A34F216AF6B2B00C2501F /* PageVisibilityStateWithWindowChanges.html in Copy Resources */,
 				A1409AD91E7254D4004949D9 /* password-protected.pages in Copy Resources */,
 				9BD6D3A71F7B21DC00BD4962 /* paste-image.html in Copy Resources */,
+				9B7D740F1F8378770006C432 /* paste-rtfd.html in Copy Resources */,
 				3FCC4FE81EC4E8CA0076E37C /* PictureInPictureDelegate.html in Copy Resources */,
 				F415086D1DA040C50044BE9B /* play-audio-on-click.html in Copy Resources */,
 				F41AB9A81EF4696B0083FA08 /* prevent-operation.html in Copy Resources */,
@@ -1507,6 +1510,7 @@
 		9B4F8FA3159D52B1002D9F94 /* HTMLCollectionNamedItem.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = HTMLCollectionNamedItem.mm; sourceTree = "<group>"; };
 		9B4F8FA6159D52CA002D9F94 /* HTMLCollectionNamedItem.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = HTMLCollectionNamedItem.html; sourceTree = "<group>"; };
 		9B79164F1BD89D0D00D50B8F /* FirstResponderScrollingPosition.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FirstResponderScrollingPosition.mm; sourceTree = "<group>"; };
+		9B7D740E1F8377E60006C432 /* paste-rtfd.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "paste-rtfd.html"; sourceTree = "<group>"; };
 		9BD423991E04BD9800200395 /* AttributedSubstringForProposedRangeWithImage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AttributedSubstringForProposedRangeWithImage.mm; sourceTree = "<group>"; };
 		9BD4239B1E04BFD000200395 /* chinese-character-with-image.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "chinese-character-with-image.html"; sourceTree = "<group>"; };
 		9BD6D39E1F7B201E00BD4962 /* sunset-in-cupertino-600px.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "sunset-in-cupertino-600px.jpg"; sourceTree = "<group>"; };
@@ -1515,6 +1519,7 @@
 		9BD6D3A11F7B202100BD4962 /* sunset-in-cupertino-100px.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "sunset-in-cupertino-100px.tiff"; sourceTree = "<group>"; };
 		9BD6D3A61F7B21CC00BD4962 /* paste-image.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "paste-image.html"; sourceTree = "<group>"; };
 		9BDCCD851F7D0B0700009A18 /* PasteImage.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteImage.mm; sourceTree = "<group>"; };
+		9BDD95561F83683600D20C60 /* PasteRTFD.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PasteRTFD.mm; sourceTree = "<group>"; };
 		9C64DC311D76198A004B598E /* YouTubePluginReplacement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YouTubePluginReplacement.cpp; sourceTree = "<group>"; };
 		A10F047C1E3AD29C00C95E19 /* NSFileManagerExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NSFileManagerExtras.mm; sourceTree = "<group>"; };
 		A1146A8A1D2D704F000FE710 /* ContentFiltering.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContentFiltering.mm; sourceTree = "<group>"; };
@@ -2014,6 +2019,7 @@
 				CEA6CF2219CCF5BD0064F5A7 /* OpenAndCloseWindow.mm */,
 				CEBCA12E1E3A660100C73293 /* OverrideContentSecurityPolicy.mm */,
 				9BDCCD851F7D0B0700009A18 /* PasteImage.mm */,
+				9BDD95561F83683600D20C60 /* PasteRTFD.mm */,
 				3FCC4FE41EC4E8520076E37C /* PictureInPictureDelegate.mm */,
 				83BAEE8C1EF4625500DDE894 /* PluginLoadClientPolicies.mm */,
 				C95501BE19AD2FAF0049BE3E /* Preferences.mm */,
@@ -2308,6 +2314,7 @@
 				CEBCA1371E3A803400C73293 /* page-without-csp.html */,
 				A1409AD81E7254AC004949D9 /* password-protected.pages */,
 				9BD6D3A61F7B21CC00BD4962 /* paste-image.html */,
+				9B7D740E1F8377E60006C432 /* paste-rtfd.html */,
 				3FCC4FE61EC4E87E0076E37C /* PictureInPictureDelegate.html */,
 				F415086C1DA040C10044BE9B /* play-audio-on-click.html */,
 				F41AB9941EF4692C0083FA08 /* prevent-operation.html */,
@@ -3374,6 +3381,7 @@
 				7C83E0511D0A641800FEBCF3 /* ParsedContentRange.cpp in Sources */,
 				7CCE7F0A1A411AE600447C4C /* PasteboardNotifications.mm in Sources */,
 				9BDCCD871F7D0B0700009A18 /* PasteImage.mm in Sources */,
+				9BDD95581F83683600D20C60 /* PasteRTFD.mm in Sources */,
 				7C83E0531D0A643A00FEBCF3 /* PendingAPIRequestURL.cpp in Sources */,
 				3FCC4FE51EC4E8520076E37C /* PictureInPictureDelegate.mm in Sources */,
 				7CCE7EAF1A411A3800447C4C /* PlatformUtilities.cpp in Sources */,

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm (222838 => 222839)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm	2017-10-04 10:03:20 UTC (rev 222838)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteImage.mm	2017-10-04 11:06:15 UTC (rev 222839)
@@ -27,10 +27,8 @@
 
 #if WK_API_ENABLED && PLATFORM(COCOA)
 
-#import "AppKitSPI.h"
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
-#import <wtf/BlockPtr.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/text/WTFString.h>
 

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteRTFD.mm (0 => 222839)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteRTFD.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteRTFD.mm	2017-10-04 11:06:15 UTC (rev 222839)
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if WK_API_ENABLED && PLATFORM(COCOA)
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <wtf/RetainPtr.h>
+#import <wtf/text/WTFString.h>
+
+#if PLATFORM(IOS)
+#include <MobileCoreServices/MobileCoreServices.h>
+#endif
+
+@interface WKWebView ()
+- (void)paste:(id)sender;
+@end
+
+#if PLATFORM(MAC)
+void writeRTFDToPasteboard(NSData *data)
+{
+    [[NSPasteboard generalPasteboard] declareTypes:@[NSRTFDPboardType] owner:nil];
+    [[NSPasteboard generalPasteboard] setData:data forType:NSRTFDPboardType];
+}
+#else
+
+@interface NSAttributedString ()
+- (id)initWithRTF:(NSData *)data documentAttributes:(NSDictionary **)dict;
+- (id)initWithRTFD:(NSData *)data documentAttributes:(NSDictionary **)dict;
+- (NSData *)RTFFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict;
+- (NSData *)RTFDFromRange:(NSRange)range documentAttributes:(NSDictionary *)dict;
+- (BOOL)containsAttachments;
+@end
+
+void writeRTFDToPasteboard(NSData *data)
+{
+    [[UIPasteboard generalPasteboard] setItems:@[@{ (NSString *)kUTTypeFlatRTFD : data}]];
+}
+#endif
+
+TEST(PasteRTFD, EmptyRTFD)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
+    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html><html><body><div id='editor' contenteditable></div></body></html>"];
+
+    writeRTFDToPasteboard([NSData data]);
+    [webView stringByEvaluatingJavaScript:@"document.getElementById('editor').focus()"];
+    [webView paste:nil];
+}
+
+TEST(PasteRTFD, ImageElementsUseBlobURL)
+{
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
+    [webView synchronouslyLoadTestPageNamed:@"paste-rtfd"];
+
+    auto *pngData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sunset-in-cupertino-200px" ofType:@"png" inDirectory:@"TestWebKitAPI.resources"]];
+    auto attachment = adoptNS([[NSTextAttachment alloc] initWithData:pngData ofType:(NSString *)kUTTypePNG]);
+    NSAttributedString *string = [NSAttributedString attributedStringWithAttachment:attachment.get()];
+    NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:@{ }];
+
+    writeRTFDToPasteboard(RTFDData);
+    [webView paste:nil];
+
+    [webView waitForMessage:@"loaded"];
+    EXPECT_WK_STREQ("200", [webView stringByEvaluatingJavaScript:@"imageElement = document.querySelector('img'); imageElement.width"]);
+    EXPECT_WK_STREQ("blob:", [webView stringByEvaluatingJavaScript:@"url = "" URL(imageElement.src).protocol"]);
+}
+
+#endif // WK_API_ENABLED && PLATFORM(MAC)
+
+
+

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/paste-rtfd.html (0 => 222839)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/paste-rtfd.html	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/paste-rtfd.html	2017-10-04 11:06:15 UTC (rev 222839)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="editor" contenteditable></div>
+<script>
+const editor = document.getElementById('editor');
+editor.focus();
+
+editor.addEventListener('paste', (event) => {
+    setTimeout(() => {
+       let img = document.querySelector('img');
+       if (img.complete)
+           notifyLoaded();
+       else
+           img._onload_ = notifyLoaded;
+    }, 0);
+});
+
+function notifyLoaded()
+{
+    webkit.messageHandlers.testHandler.postMessage('loaded');
+}
+
+</script>
+</body>
+</html>
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to