Use Blob URL instead of webkit-fake-url when pasting an image
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Nov 2016 19:14:17 +0000 (19:14 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 9 Nov 2016 19:14:17 +0000 (19:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=49141

Reviewed by Darin Adler.

Source/WebCore:

Use Blob URL instead of webkit-fake-url when pasting an image.

Tests: editing/pasteboard/paste-image-as-blob-url.html
       editing/pasteboard/paste-image-using-image-data.html

* editing/Editor.h:
* editing/mac/EditorMac.mm:
(WebCore::Editor::WebContentReader::readImage):
(WebCore::Editor::createFragmentForImageAndURL):

LayoutTests:

Add layout test coverage checking that the image shows as expected and that the
resulting URL is indeed a Blob URL.

* editing/pasteboard/paste-image-as-blob-url-expected.txt: Added.
* editing/pasteboard/paste-image-as-blob-url.html: Added.
* editing/pasteboard/paste-image-using-image-data-expected.html: Added.
* editing/pasteboard/paste-image-using-image-data.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208451 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/editing/pasteboard/paste-image-as-blob-url-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/paste-image-as-blob-url.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/paste-image-using-image-data-expected.html [new file with mode: 0644]
LayoutTests/editing/pasteboard/paste-image-using-image-data.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/editing/Editor.h
Source/WebCore/editing/mac/EditorMac.mm
Source/WebCore/fileapi/Blob.cpp
Source/WebCore/fileapi/Blob.h
Source/WebCore/platform/network/BlobPart.h

index 9ea63c0..cbdfcb9 100644 (file)
@@ -1,3 +1,18 @@
+2016-11-09  Chris Dumez  <cdumez@apple.com>
+
+        Use Blob URL instead of webkit-fake-url when pasting an image
+        https://bugs.webkit.org/show_bug.cgi?id=49141
+
+        Reviewed by Darin Adler.
+
+        Add layout test coverage checking that the image shows as expected and that the
+        resulting URL is indeed a Blob URL.
+
+        * editing/pasteboard/paste-image-as-blob-url-expected.txt: Added.
+        * editing/pasteboard/paste-image-as-blob-url.html: Added.
+        * editing/pasteboard/paste-image-using-image-data-expected.html: Added.
+        * editing/pasteboard/paste-image-using-image-data.html: Added.
+
 2016-11-07  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         [JSC] The implementation of 8 bit operation in MacroAssembler should care about uint8_t / int8_t
diff --git a/LayoutTests/editing/pasteboard/paste-image-as-blob-url-expected.txt b/LayoutTests/editing/pasteboard/paste-image-as-blob-url-expected.txt
new file mode 100644 (file)
index 0000000..b2cd2d4
--- /dev/null
@@ -0,0 +1,12 @@
+Tests that pasted images use blob URL, not webkit fake URLs.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS pastedImages.length is 1
+PASS url.protocol is "blob:"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
diff --git a/LayoutTests/editing/pasteboard/paste-image-as-blob-url.html b/LayoutTests/editing/pasteboard/paste-image-as-blob-url.html
new file mode 100644 (file)
index 0000000..261fe27
--- /dev/null
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../resources/js-test-pre.js"></script>
+<div id="destination" contenteditable="true" style="width: 500px; height: 100px; border: solid red 1px"></div>
+<iframe id="iframe" src="../resources/abe.png" onload="selectInFrame()"></iframe>
+</body>
+<script>
+    description("Tests that pasted images use blob URL, not webkit fake URLs.");
+    jsTestIsAsync = true;
+
+    function selectInFrame() {
+        if (window.internals)
+            window.internals.settings.setPreferMIMETypeForImages(true);
+        var iframe = document.getElementById("iframe");
+        var iframeDocument = iframe.contentDocument;
+        var destination = document.getElementById("destination");
+        iframeDocument.body.focus();
+        iframeDocument.execCommand("SelectAll");
+        iframeDocument.execCommand("Copy");
+        destination.focus();
+        document.execCommand("Paste");
+
+        pastedImages = destination.getElementsByTagName("img");
+        shouldBe("pastedImages.length", "1");
+        img = pastedImages[0];
+        url = new URL(img.src);
+        shouldBeEqualToString("url.protocol", "blob:");
+
+        finishJSTest();
+    }
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
diff --git a/LayoutTests/editing/pasteboard/paste-image-using-image-data-expected.html b/LayoutTests/editing/pasteboard/paste-image-using-image-data-expected.html
new file mode 100644 (file)
index 0000000..7d108e9
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="destination" contenteditable="true" style="width: 500px; height: 100px; border: solid red 1px">
+<img src="../resources/abe.png">
+</div>
+<iframe id="iframe" src="../resources/abe.png"></iframe>
+</body>
+</html>
diff --git a/LayoutTests/editing/pasteboard/paste-image-using-image-data.html b/LayoutTests/editing/pasteboard/paste-image-using-image-data.html
new file mode 100644 (file)
index 0000000..43c6b41
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="destination" contenteditable="true" style="width: 500px; height: 100px; border: solid red 1px"></div>
+<iframe id="iframe" src="../resources/abe.png" onload="selectInFrame()"></iframe>
+</body>
+<script>
+    function selectInFrame() {
+        if (window.internals)
+            window.internals.settings.setPreferMIMETypeForImages(true);
+        var iframe = document.getElementById("iframe");
+        var iframeDocument = iframe.contentDocument;
+        var destination = document.getElementById("destination");
+        iframeDocument.body.focus();
+        iframeDocument.execCommand("SelectAll");
+        iframeDocument.execCommand("Copy");
+        destination.focus();
+        document.execCommand("Paste");
+        destination.blur();
+    }
+</script>
+</html>
index 5bcc725..9696a2a 100644 (file)
@@ -1,3 +1,20 @@
+2016-11-09  Chris Dumez  <cdumez@apple.com>
+
+        Use Blob URL instead of webkit-fake-url when pasting an image
+        https://bugs.webkit.org/show_bug.cgi?id=49141
+
+        Reviewed by Darin Adler.
+
+        Use Blob URL instead of webkit-fake-url when pasting an image.
+
+        Tests: editing/pasteboard/paste-image-as-blob-url.html
+               editing/pasteboard/paste-image-using-image-data.html
+
+        * editing/Editor.h:
+        * editing/mac/EditorMac.mm:
+        (WebCore::Editor::WebContentReader::readImage):
+        (WebCore::Editor::createFragmentForImageAndURL):
+
 2016-11-09  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         Fix error message when SQLite initialization fails
index e2bbc49..27ea615 100644 (file)
@@ -518,6 +518,7 @@ private:
     RefPtr<SharedBuffer> imageInWebArchiveFormat(Element&);
     RefPtr<Range> adjustedSelectionRange();
     RefPtr<DocumentFragment> createFragmentForImageResourceAndAddResource(RefPtr<ArchiveResource>&&);
+    Ref<DocumentFragment> createFragmentForImageAndURL(const String&);
     RefPtr<DocumentFragment> createFragmentAndAddResources(NSAttributedString *);
     FragmentAndResources createFragment(NSAttributedString *);
     void fillInUserVisibleForm(PasteboardURL&);
index 5e7eaea..f3b31e1 100644 (file)
 #import "config.h"
 #import "Editor.h"
 
+#import "Blob.h"
 #import "CSSPrimitiveValueMappings.h"
 #import "CSSValuePool.h"
 #import "CachedResourceLoader.h"
 #import "ColorMac.h"
+#import "DOMURL.h"
 #import "DataTransfer.h"
 #import "DocumentFragment.h"
 #import "DocumentLoader.h"
@@ -610,9 +612,14 @@ bool Editor::WebContentReader::readImage(Ref<SharedBuffer>&& buffer, const Strin
     ASSERT(type.contains('/'));
     String typeAsFilenameWithExtension = type;
     typeAsFilenameWithExtension.replace('/', '.');
-    URL imageURL = URL::fakeURLWithRelativePart(typeAsFilenameWithExtension);
 
-    fragment = frame.editor().createFragmentForImageResourceAndAddResource(ArchiveResource::create(WTFMove(buffer), imageURL, type, emptyString(), emptyString()));
+    Vector<uint8_t> data;
+    data.append(buffer->data(), buffer->size());
+    auto blob = Blob::create(WTFMove(data), type);
+    ASSERT(frame.document());
+    String blobURL = DOMURL::createObjectURL(*frame.document(), blob);
+
+    fragment = frame.editor().createFragmentForImageAndURL(blobURL);
     return fragment;
 }
 
@@ -671,6 +678,17 @@ RefPtr<DocumentFragment> Editor::createFragmentForImageResourceAndAddResource(Re
     return WTFMove(fragment);
 }
 
+Ref<DocumentFragment> Editor::createFragmentForImageAndURL(const String& url)
+{
+    auto imageElement = HTMLImageElement::create(*m_frame.document());
+    imageElement->setAttributeWithoutSynchronization(HTMLNames::srcAttr, url);
+
+    auto fragment = document().createDocumentFragment();
+    fragment->appendChild(imageElement);
+
+    return fragment;
+}
+
 RefPtr<DocumentFragment> Editor::createFragmentAndAddResources(NSAttributedString *string)
 {
     if (!m_frame.page() || !document().isHTMLDocument())
index cd031a3..f642626 100644 (file)
@@ -77,7 +77,7 @@ Blob::Blob()
     ThreadableBlobRegistry::registerBlobURL(m_internalURL, Vector<BlobPart>(), String());
 }
 
-Blob::Blob(Vector<uint8_t> data, const String& contentType)
+Blob::Blob(Vector<uint8_t>&& data, const String& contentType)
     : m_type(contentType)
     , m_size(data.size())
 {
@@ -87,7 +87,7 @@ Blob::Blob(Vector<uint8_t> data, const String& contentType)
     ThreadableBlobRegistry::registerBlobURL(m_internalURL, WTFMove(blobParts), contentType);
 }
 
-Blob::Blob(Vector<BlobPart> blobParts, const String& contentType)
+Blob::Blob(Vector<BlobPart>&& blobParts, const String& contentType)
     : m_type(contentType)
     , m_size(-1)
 {
index ef7dd46..a889eee 100644 (file)
@@ -48,12 +48,12 @@ public:
         return adoptRef(*new Blob);
     }
 
-    static Ref<Blob> create(Vector<uint8_t> data, const String& contentType)
+    static Ref<Blob> create(Vector<uint8_t>&& data, const String& contentType)
     {
         return adoptRef(*new Blob(WTFMove(data), contentType));
     }
 
-    static Ref<Blob> create(Vector<BlobPart> blobParts, const String& contentType)
+    static Ref<Blob> create(Vector<BlobPart>&& blobParts, const String& contentType)
     {
         return adoptRef(*new Blob(WTFMove(blobParts), contentType));
     }
@@ -91,8 +91,8 @@ public:
 
 protected:
     Blob();
-    Blob(Vector<uint8_t>, const String& contentType);
-    Blob(Vector<BlobPart>, const String& contentType);
+    Blob(Vector<uint8_t>&&, const String& contentType);
+    Blob(Vector<BlobPart>&&, const String& contentType);
 
     enum UninitializedContructor { uninitializedContructor };
     Blob(UninitializedContructor);
index ba19c3c..9fef761 100644 (file)
@@ -42,7 +42,7 @@ public:
     {
     }
 
-    BlobPart(Vector<uint8_t> data)
+    BlobPart(Vector<uint8_t>&& data)
         : m_type(Data)
         , m_data(WTFMove(data))
     {