Title: [237624] trunk
Revision
237624
Author
[email protected]
Date
2018-10-30 22:29:17 -0700 (Tue, 30 Oct 2018)

Log Message

[Cocoa] Attachment dropped from one web view to another is missing its file wrapper
https://bugs.webkit.org/show_bug.cgi?id=190530
<rdar://problem/45232149>

Reviewed by Tim Horton.

Source/WebCore:

Add support for copying and pasting attachment elements across web views by encoding and adding file wrapper
data as subresources in the web archive when writing selected web content to the pasteboard, and then decoding
and creating NSFileWrappers upon reading web content.

Test: WKAttachmentTests.CopyAndPasteBetweenWebViews

* WebCore.xcodeproj/project.pbxproj:
* editing/Editor.cpp:
(WebCore::Editor::registerAttachments):
* editing/Editor.h:

Add registerAttachments(), which registers _WKAttachments in the UI process given a list of
SerializedAttachmentData. This behaves similarly to registerAttachmentIdentifiers(), but differs in that (1) it
sends serialized file wrapper data, and (2) it sends a list of serialized attachments, rather than information
about just a single attachment.

* editing/SerializedAttachmentData.h:

Introduce SerializedAttachmentData, a struct containing information needed to serialize and deserialize an
attachment. These are used both when writing attachment data to the pasteboard, and when consuming attachment
data upon paste.

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

Add a step when pasting rich content with attachments, to collect and send serialized attachments to the client.
Also, drive-by fix: don't WTFMove() the Ref here if it's still going to be used below.

* html/HTMLAttachmentElement.cpp:
(WebCore::HTMLAttachmentElement::archiveResourceURL):
* html/HTMLAttachmentElement.h:

Add a static helper function to compute a URL that represents the data for the given attachment identifier, for
use in a web archive resource.

* loader/archive/cf/LegacyWebArchive.cpp:
(WebCore::addSubresourcesForAttachmentElementsIfNecessary):

Add a helper function to create and append ArchiveResources representing attachment element data when writing
attachments to the pasteboard via web archive data.

(WebCore::LegacyWebArchive::create):
* page/EditorClient.h:
(WebCore::EditorClient::registerAttachments):
(WebCore::EditorClient::serializedAttachmentDataForIdentifiers):

Source/WebKit:

See WebCore ChangeLog for more details.

* Shared/WebCoreArgumentCoders.cpp:
(IPC::ArgumentCoder<SerializedAttachmentData>::encode):
(IPC::ArgumentCoder<SerializedAttachmentData>::decode):
* Shared/WebCoreArgumentCoders.h:

Add IPC encoding/decoding support for SerializedAttachmentData.

* UIProcess/API/APIAttachment.cpp:
(API::Attachment::createSerializedRepresentation const):
(API::Attachment::updateFromSerializedRepresentation):
* UIProcess/API/APIAttachment.h:
* UIProcess/API/Cocoa/APIAttachmentCocoa.mm:
(API::Attachment::createSerializedRepresentation const):

Add a method to serialize and return attachment info as a blob of data.

(API::Attachment::updateFromSerializedRepresentation):

Add a method to update the attachment, given a serialized blob of data. On Cocoa platforms, this fails
gracefully if the serialized data cannot be decoded.

* UIProcess/Cocoa/PageClientImplCocoa.h:
* UIProcess/Cocoa/PageClientImplCocoa.mm:
(WebKit::PageClientImplCocoa::allocFileWrapperInstance const):
(WebKit::PageClientImplCocoa::serializableFileWrapperClasses const):
(WebKit::PageClientImplCocoa::allocFileWrapperInstance): Deleted.

Add an additional hook to return the list of NSFileWrapper subclasses suitable for deserialization. This
array contains (at minimum) NSFileWrapper, but may additionally include a custom NSFileWrapper subclass, if
configured.

* UIProcess/PageClient.h:
(WebKit::PageClient::allocFileWrapperInstance const):
(WebKit::PageClient::serializableFileWrapperClasses const):
(WebKit::PageClient::allocFileWrapperInstance): Deleted.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::registerAttachmentsFromSerializedData):

Registers the given serialized attachment data, creating new _WKAttachment instances if necessary. Currently,
this does not update the file wrappers of existing _WKAttachments; we should revisit this in the future to see
if we can additionally update file wrappers for existing attachments, without breaking the case where the user
copies and pastes or drags and drops attachments within a single web view and the client expects _WKAttachment
instances to be reused.

(WebKit::WebPageProxy::serializedAttachmentDataForIdentifiers):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::registerAttachments):
(WebKit::WebEditorClient::serializedAttachmentDataForIdentifiers):

Implement a new IPC hook to fetch an array of serialized attachment data blobs, given a list of attachment
identifiers.

* WebProcess/WebCoreSupport/WebEditorClient.h:

Tools:

Add a test to verify that copying different types of attachments and pasting in a new web view inserts
attachments in the second web view that are backed by _WKAttachment objects, whose NSFileWrappers hold data that
is equivalent to the original file wrappers used to insert attachments in the first web view.

Existing API tests verify that when copying and pasting within a single web view, the pasted attachment element
is still backed by the same NSFileWrapper instance.

* TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
(TestWebKitAPI::TEST):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (237623 => 237624)


--- trunk/Source/WebCore/ChangeLog	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/ChangeLog	2018-10-31 05:29:17 UTC (rev 237624)
@@ -1,3 +1,57 @@
+2018-10-30  Wenson Hsieh  <[email protected]>
+
+        [Cocoa] Attachment dropped from one web view to another is missing its file wrapper
+        https://bugs.webkit.org/show_bug.cgi?id=190530
+        <rdar://problem/45232149>
+
+        Reviewed by Tim Horton.
+
+        Add support for copying and pasting attachment elements across web views by encoding and adding file wrapper
+        data as subresources in the web archive when writing selected web content to the pasteboard, and then decoding
+        and creating NSFileWrappers upon reading web content.
+
+        Test: WKAttachmentTests.CopyAndPasteBetweenWebViews
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/Editor.cpp:
+        (WebCore::Editor::registerAttachments):
+        * editing/Editor.h:
+
+        Add registerAttachments(), which registers _WKAttachments in the UI process given a list of
+        SerializedAttachmentData. This behaves similarly to registerAttachmentIdentifiers(), but differs in that (1) it
+        sends serialized file wrapper data, and (2) it sends a list of serialized attachments, rather than information
+        about just a single attachment.
+
+        * editing/SerializedAttachmentData.h:
+
+        Introduce SerializedAttachmentData, a struct containing information needed to serialize and deserialize an
+        attachment. These are used both when writing attachment data to the pasteboard, and when consuming attachment
+        data upon paste.
+
+        * editing/cocoa/WebContentReaderCocoa.mm:
+        (WebCore::replaceRichContentWithAttachments):
+
+        Add a step when pasting rich content with attachments, to collect and send serialized attachments to the client.
+        Also, drive-by fix: don't WTFMove() the Ref here if it's still going to be used below.
+
+        * html/HTMLAttachmentElement.cpp:
+        (WebCore::HTMLAttachmentElement::archiveResourceURL):
+        * html/HTMLAttachmentElement.h:
+
+        Add a static helper function to compute a URL that represents the data for the given attachment identifier, for
+        use in a web archive resource.
+
+        * loader/archive/cf/LegacyWebArchive.cpp:
+        (WebCore::addSubresourcesForAttachmentElementsIfNecessary):
+
+        Add a helper function to create and append ArchiveResources representing attachment element data when writing
+        attachments to the pasteboard via web archive data.
+
+        (WebCore::LegacyWebArchive::create):
+        * page/EditorClient.h:
+        (WebCore::EditorClient::registerAttachments):
+        (WebCore::EditorClient::serializedAttachmentDataForIdentifiers):
+
 2018-10-30  David Kilzer  <[email protected]>
 
         XSLTProcessor should limit max transform depth

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (237623 => 237624)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-10-31 05:29:17 UTC (rev 237624)
@@ -4889,6 +4889,7 @@
 		F49786881FF45FA500E060AB /* PasteboardItemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F49786871FF45FA500E060AB /* PasteboardItemInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; };
 		F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; };
+		F4D43D662188038B00ECECAC /* SerializedAttachmentData.h in Headers */ = {isa = PBXBuildFile; fileRef = F4D43D64218802E600ECECAC /* SerializedAttachmentData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4E57EDC213F3F5F004EA98E /* FontAttributeChanges.h in Headers */ = {isa = PBXBuildFile; fileRef = F4E57EDA213F3F5F004EA98E /* FontAttributeChanges.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4E57EE1213F434A004EA98E /* WebCoreNSFontManagerExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = F4E57EDF213F434A004EA98E /* WebCoreNSFontManagerExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F50664F8157F52DC00AC226F /* FormController.h in Headers */ = {isa = PBXBuildFile; fileRef = F50664F6157F52DC00AC226F /* FormController.h */; };
@@ -14798,6 +14799,7 @@
 		F48D2AA32159740D00C6752B /* ColorCocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorCocoa.h; sourceTree = "<group>"; };
 		F48D2AA42159740D00C6752B /* ColorCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ColorCocoa.mm; sourceTree = "<group>"; };
 		F49786871FF45FA500E060AB /* PasteboardItemInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasteboardItemInfo.h; sourceTree = "<group>"; };
+		F4D43D64218802E600ECECAC /* SerializedAttachmentData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SerializedAttachmentData.h; sourceTree = "<group>"; };
 		F4E57EDA213F3F5F004EA98E /* FontAttributeChanges.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FontAttributeChanges.h; sourceTree = "<group>"; };
 		F4E57EDF213F434A004EA98E /* WebCoreNSFontManagerExtras.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebCoreNSFontManagerExtras.h; sourceTree = "<group>"; };
 		F4E57EE0213F434A004EA98E /* WebCoreNSFontManagerExtras.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreNSFontManagerExtras.mm; sourceTree = "<group>"; };
@@ -20621,6 +20623,7 @@
 				93309DBB099E64910056E581 /* ReplaceSelectionCommand.h */,
 				51405C86190B014400754F94 /* SelectionRectGatherer.cpp */,
 				51405C87190B014400754F94 /* SelectionRectGatherer.h */,
+				F4D43D64218802E600ECECAC /* SerializedAttachmentData.h */,
 				93309DC0099E64910056E581 /* SetNodeAttributeCommand.cpp */,
 				93309DC1099E64910056E581 /* SetNodeAttributeCommand.h */,
 				B8DBDB47130B0F8A00F5CDB1 /* SetSelectionCommand.cpp */,
@@ -30704,6 +30707,7 @@
 				415071581685067300C3C7B3 /* SelectorFilter.h in Headers */,
 				43107BE218CC19DE00CC18E8 /* SelectorPseudoTypeMap.h in Headers */,
 				E45322AC140CE267005A0F92 /* SelectorQuery.h in Headers */,
+				F4D43D662188038B00ECECAC /* SerializedAttachmentData.h in Headers */,
 				E18DF33518AAF12C00773E59 /* SerializedCryptoKeyWrap.h in Headers */,
 				077AF14018F4AE400001ED61 /* SerializedPlatformRepresentation.h in Headers */,
 				077AF14318F4B1BB0001ED61 /* SerializedPlatformRepresentationMac.h in Headers */,

Modified: trunk/Source/WebCore/editing/Editor.cpp (237623 => 237624)


--- trunk/Source/WebCore/editing/Editor.cpp	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/editing/Editor.cpp	2018-10-31 05:29:17 UTC (rev 237624)
@@ -85,8 +85,10 @@
 #include "ReplaceRangeWithTextCommand.h"
 #include "ReplaceSelectionCommand.h"
 #include "RuntimeEnabledFeatures.h"
+#include "SerializedAttachmentData.h"
 #include "Settings.h"
 #include "ShadowRoot.h"
+#include "SharedBuffer.h"
 #include "SimplifyMarkupCommand.h"
 #include "SpellChecker.h"
 #include "SpellingCorrectionCommand.h"
@@ -4010,6 +4012,12 @@
         client->registerAttachmentIdentifier(identifier, contentType, filePath);
 }
 
+void Editor::registerAttachments(Vector<SerializedAttachmentData>&& data)
+{
+    if (auto* client = this->client())
+        client->registerAttachments(WTFMove(data));
+}
+
 void Editor::registerAttachmentIdentifier(const String& identifier)
 {
     if (auto* client = this->client())

Modified: trunk/Source/WebCore/editing/Editor.h (237623 => 237624)


--- trunk/Source/WebCore/editing/Editor.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/editing/Editor.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -86,6 +86,10 @@
 struct PasteboardURL;
 struct TextCheckingResult;
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+struct SerializedAttachmentData;
+#endif
+
 enum EditorCommandSource { CommandFromMenuOrKeyBinding, CommandFromDOM, CommandFromDOMWithUserInterface };
 enum EditorParagraphSeparator { EditorParagraphSeparatorIsDiv, EditorParagraphSeparatorIsP };
 
@@ -509,8 +513,9 @@
 
 #if ENABLE(ATTACHMENT_ELEMENT)
     WEBCORE_EXPORT void insertAttachment(const String& identifier, std::optional<uint64_t>&& fileSize, const String& fileName, const String& contentType);
-    void registerAttachmentIdentifier(const String&, const String& /* contentType */, const String& /* preferredFileName */, Ref<SharedBuffer>&&);
-    void registerAttachmentIdentifier(const String&, const String& /* contentType */, const String& /* filePath */);
+    void registerAttachmentIdentifier(const String&, const String& contentType, const String& preferredFileName, Ref<SharedBuffer>&& fileData);
+    void registerAttachments(Vector<SerializedAttachmentData>&&);
+    void registerAttachmentIdentifier(const String&, const String& contentType, const String& filePath);
     void registerAttachmentIdentifier(const String&);
     void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier);
     void didInsertAttachmentElement(HTMLAttachmentElement&);

Copied: trunk/Source/WebCore/editing/SerializedAttachmentData.h (from rev 237623, trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h) (0 => 237624)


--- trunk/Source/WebCore/editing/SerializedAttachmentData.h	                        (rev 0)
+++ trunk/Source/WebCore/editing/SerializedAttachmentData.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+#include "SharedBuffer.h"
+#include <wtf/Ref.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class SharedBuffer;
+
+struct SerializedAttachmentData {
+    String identifier;
+    String mimeType;
+    Ref<SharedBuffer> data;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)

Modified: trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm (237623 => 237624)


--- trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-10-31 05:29:17 UTC (rev 237624)
@@ -51,6 +51,7 @@
 #import "Page.h"
 #import "PublicURLManager.h"
 #import "RuntimeEnabledFeatures.h"
+#import "SerializedAttachmentData.h"
 #import "Settings.h"
 #import "SocketProvider.h"
 #import "TypedElementDescendantIterator.h"
@@ -274,6 +275,20 @@
             urlToResourceMap.set(url.string(), subresource.copyRef());
     }
 
+    Vector<SerializedAttachmentData> serializedAttachmentData;
+    for (auto& attachment : descendantsOfType<HTMLAttachmentElement>(fragment)) {
+        auto resourceURL = HTMLAttachmentElement::archiveResourceURL(attachment.uniqueIdentifier());
+        auto resourceEntry = urlToResourceMap.find(resourceURL.string());
+        if (resourceEntry == urlToResourceMap.end())
+            continue;
+
+        auto& resource = resourceEntry->value;
+        serializedAttachmentData.append({ attachment.uniqueIdentifier(), resource->mimeType(), resource->data() });
+    }
+
+    if (!serializedAttachmentData.isEmpty())
+        frame.editor().registerAttachments(WTFMove(serializedAttachmentData));
+
     Vector<Ref<Element>> elementsToRemove;
     Vector<AttachmentInsertionInfo> attachmentInsertionInfo;
     for (auto& image : descendantsOfType<HTMLImageElement>(fragment)) {
@@ -323,7 +338,7 @@
             if (is<HTMLImageElement>(originalElement.get()) && contentTypeIsSuitableForInlineImageRepresentation(info.contentType)) {
                 auto& image = downcast<HTMLImageElement>(originalElement.get());
                 image.setAttributeWithoutSynchronization(HTMLNames::srcAttr, DOMURL::createObjectURL(*frame.document(), Blob::create(info.data, info.contentType)));
-                image.setAttachmentElement(WTFMove(attachment));
+                image.setAttachmentElement(attachment.copyRef());
             } else {
                 attachment->updateAttributes(info.data->size(), info.contentType, info.fileName);
                 parent->replaceChild(attachment, WTFMove(originalElement));

Modified: trunk/Source/WebCore/html/HTMLAttachmentElement.cpp (237623 => 237624)


--- trunk/Source/WebCore/html/HTMLAttachmentElement.cpp	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/html/HTMLAttachmentElement.cpp	2018-10-31 05:29:17 UTC (rev 237624)
@@ -38,6 +38,7 @@
 #include "MIMETypeRegistry.h"
 #include "RenderAttachment.h"
 #include "SharedBuffer.h"
+#include "URLParser.h"
 #include <pal/FileSizeFormatter.h>
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/UUID.h>
@@ -85,6 +86,13 @@
     return identifier;
 }
 
+URL HTMLAttachmentElement::archiveResourceURL(const String& identifier)
+{
+    auto resourceURL = URLParser("applewebdata://attachment/"_s).result();
+    resourceURL.setPath(identifier);
+    return resourceURL;
+}
+
 File* HTMLAttachmentElement::file() const
 {
     return m_file.get();

Modified: trunk/Source/WebCore/html/HTMLAttachmentElement.h (237623 => 237624)


--- trunk/Source/WebCore/html/HTMLAttachmentElement.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/html/HTMLAttachmentElement.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -41,6 +41,7 @@
 public:
     static Ref<HTMLAttachmentElement> create(const QualifiedName&, Document&);
     static const String& getAttachmentIdentifier(HTMLImageElement&);
+    static URL archiveResourceURL(const String&);
 
     WEBCORE_EXPORT URL blobURL() const;
     WEBCORE_EXPORT File* file() const;

Modified: trunk/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp (237623 => 237624)


--- trunk/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/loader/archive/cf/LegacyWebArchive.cpp	2018-10-31 05:29:17 UTC (rev 237624)
@@ -32,10 +32,13 @@
 #include "CachedResource.h"
 #include "Document.h"
 #include "DocumentLoader.h"
+#include "Editor.h"
+#include "EditorClient.h"
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameSelection.h"
 #include "FrameTree.h"
+#include "HTMLAttachmentElement.h"
 #include "HTMLFrameElement.h"
 #include "HTMLFrameOwnerElement.h"
 #include "HTMLIFrameElement.h"
@@ -47,7 +50,10 @@
 #include "MemoryCache.h"
 #include "Page.h"
 #include "Range.h"
+#include "RuntimeEnabledFeatures.h"
+#include "SerializedAttachmentData.h"
 #include "Settings.h"
+#include "SharedBuffer.h"
 #include "markup.h"
 #include <wtf/ListHashSet.h>
 #include <wtf/RetainPtr.h>
@@ -464,6 +470,42 @@
     return create(markupString, *frame, nodeList, nullptr);
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+static void addSubresourcesForAttachmentElementsIfNecessary(Frame& frame, const Vector<Node*>& nodes, Vector<Ref<ArchiveResource>>& subresources)
+{
+    if (!RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled())
+        return;
+
+    Vector<String> identifiers;
+    for (auto* node : nodes) {
+        if (!is<HTMLAttachmentElement>(node))
+            continue;
+
+        auto uniqueIdentifier = downcast<HTMLAttachmentElement>(*node).uniqueIdentifier();
+        if (uniqueIdentifier.isEmpty())
+            continue;
+
+        identifiers.append(WTFMove(uniqueIdentifier));
+    }
+
+    if (identifiers.isEmpty())
+        return;
+
+    auto* editorClient = frame.editor().client();
+    if (!editorClient)
+        return;
+
+    auto frameName = frame.tree().uniqueName();
+    for (auto& data : editorClient->serializedAttachmentDataForIdentifiers(WTFMove(identifiers))) {
+        auto resourceURL = HTMLAttachmentElement::archiveResourceURL(data.identifier);
+        if (auto resource = ArchiveResource::create(data.data.ptr(), WTFMove(resourceURL), data.mimeType, { }, frameName))
+            subresources.append(resource.releaseNonNull());
+    }
+}
+
+#endif
+
 RefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString, Frame& frame, const Vector<Node*>& nodes, WTF::Function<bool (Frame&)>&& frameFilter)
 {
     auto& response = frame.loader().documentLoader()->response();
@@ -528,6 +570,10 @@
         }
     }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+    addSubresourcesForAttachmentElementsIfNecessary(frame, nodes, subresources);
+#endif
+
     // If we are archiving the entire page, add any link icons that we have data for.
     if (!nodes.isEmpty() && nodes[0]->isDocumentNode()) {
         auto* documentLoader = frame.loader().documentLoader();

Modified: trunk/Source/WebCore/page/EditorClient.h (237623 => 237624)


--- trunk/Source/WebCore/page/EditorClient.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebCore/page/EditorClient.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -27,6 +27,7 @@
 #pragma once
 
 #include "EditorInsertAction.h"
+#include "SerializedAttachmentData.h"
 #include "TextAffinity.h"
 #include "TextChecking.h"
 #include "UndoStep.h"
@@ -75,11 +76,13 @@
 #if ENABLE(ATTACHMENT_ELEMENT)
     virtual void registerAttachmentIdentifier(const String& /* identifier */, const String& /* contentType */, const String& /* preferredFileName */, Ref<SharedBuffer>&&) { }
     virtual void registerAttachmentIdentifier(const String& /* identifier */, const String& /* contentType */, const String& /* filePath */) { }
+    virtual void registerAttachments(Vector<SerializedAttachmentData>&&) { }
     virtual void registerAttachmentIdentifier(const String& /* identifier */) { }
     virtual void cloneAttachmentData(const String& /* fromIdentifier */, const String& /* toIdentifier */) { }
     virtual void didInsertAttachmentWithIdentifier(const String& /* identifier */, const String& /* source */, bool /* hasEnclosingImage */) { }
     virtual void didRemoveAttachmentWithIdentifier(const String&) { }
     virtual bool supportsClientSideAttachmentData() const { return false; }
+    virtual Vector<SerializedAttachmentData> serializedAttachmentDataForIdentifiers(const Vector<String>&) { return { }; }
 #endif
 
     virtual void didBeginEditing() = 0;

Modified: trunk/Source/WebKit/ChangeLog (237623 => 237624)


--- trunk/Source/WebKit/ChangeLog	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/ChangeLog	2018-10-31 05:29:17 UTC (rev 237624)
@@ -1,3 +1,69 @@
+2018-10-30  Wenson Hsieh  <[email protected]>
+
+        [Cocoa] Attachment dropped from one web view to another is missing its file wrapper
+        https://bugs.webkit.org/show_bug.cgi?id=190530
+        <rdar://problem/45232149>
+
+        Reviewed by Tim Horton.
+
+        See WebCore ChangeLog for more details.
+
+        * Shared/WebCoreArgumentCoders.cpp:
+        (IPC::ArgumentCoder<SerializedAttachmentData>::encode):
+        (IPC::ArgumentCoder<SerializedAttachmentData>::decode):
+        * Shared/WebCoreArgumentCoders.h:
+
+        Add IPC encoding/decoding support for SerializedAttachmentData.
+
+        * UIProcess/API/APIAttachment.cpp:
+        (API::Attachment::createSerializedRepresentation const):
+        (API::Attachment::updateFromSerializedRepresentation):
+        * UIProcess/API/APIAttachment.h:
+        * UIProcess/API/Cocoa/APIAttachmentCocoa.mm:
+        (API::Attachment::createSerializedRepresentation const):
+
+        Add a method to serialize and return attachment info as a blob of data.
+
+        (API::Attachment::updateFromSerializedRepresentation):
+
+        Add a method to update the attachment, given a serialized blob of data. On Cocoa platforms, this fails
+        gracefully if the serialized data cannot be decoded.
+
+        * UIProcess/Cocoa/PageClientImplCocoa.h:
+        * UIProcess/Cocoa/PageClientImplCocoa.mm:
+        (WebKit::PageClientImplCocoa::allocFileWrapperInstance const):
+        (WebKit::PageClientImplCocoa::serializableFileWrapperClasses const):
+        (WebKit::PageClientImplCocoa::allocFileWrapperInstance): Deleted.
+
+        Add an additional hook to return the list of NSFileWrapper subclasses suitable for deserialization. This
+        array contains (at minimum) NSFileWrapper, but may additionally include a custom NSFileWrapper subclass, if
+        configured.
+
+        * UIProcess/PageClient.h:
+        (WebKit::PageClient::allocFileWrapperInstance const):
+        (WebKit::PageClient::serializableFileWrapperClasses const):
+        (WebKit::PageClient::allocFileWrapperInstance): Deleted.
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::registerAttachmentsFromSerializedData):
+
+        Registers the given serialized attachment data, creating new _WKAttachment instances if necessary. Currently,
+        this does not update the file wrappers of existing _WKAttachments; we should revisit this in the future to see
+        if we can additionally update file wrappers for existing attachments, without breaking the case where the user
+        copies and pastes or drags and drops attachments within a single web view and the client expects _WKAttachment
+        instances to be reused.
+
+        (WebKit::WebPageProxy::serializedAttachmentDataForIdentifiers):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::registerAttachments):
+        (WebKit::WebEditorClient::serializedAttachmentDataForIdentifiers):
+
+        Implement a new IPC hook to fetch an array of serialized attachment data blobs, given a list of attachment
+        identifiers.
+
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+
 2018-10-30  Chris Dumez  <[email protected]>
 
         [PSON] View gesture snapshot gets taken down early when process-swapping

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp (237623 => 237624)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.cpp	2018-10-31 05:29:17 UTC (rev 237624)
@@ -28,6 +28,7 @@
 
 #include "DataReference.h"
 #include "ShareableBitmap.h"
+#include "SharedBufferDataReference.h"
 #include <WebCore/AuthenticationChallenge.h>
 #include <WebCore/BlobPart.h>
 #include <WebCore/CacheQueryOptions.h>
@@ -69,6 +70,7 @@
 #include <WebCore/ScrollingCoordinator.h>
 #include <WebCore/SearchPopupMenu.h>
 #include <WebCore/SecurityOrigin.h>
+#include <WebCore/SerializedAttachmentData.h>
 #include <WebCore/ServiceWorkerClientData.h>
 #include <WebCore/ServiceWorkerClientIdentifier.h>
 #include <WebCore/ServiceWorkerData.h>
@@ -3012,4 +3014,30 @@
     return attributes;
 }
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+void ArgumentCoder<SerializedAttachmentData>::encode(IPC::Encoder& encoder, const WebCore::SerializedAttachmentData& data)
+{
+    encoder << data.identifier << data.mimeType << IPC::SharedBufferDataReference { data.data.get() };
+}
+
+std::optional<SerializedAttachmentData> ArgumentCoder<WebCore::SerializedAttachmentData>::decode(IPC::Decoder& decoder)
+{
+    String identifier;
+    if (!decoder.decode(identifier))
+        return std::nullopt;
+
+    String mimeType;
+    if (!decoder.decode(mimeType))
+        return std::nullopt;
+
+    IPC::DataReference data;
+    if (!decoder.decode(data))
+        return std::nullopt;
+
+    return {{ WTFMove(identifier), WTFMove(mimeType), WebCore::SharedBuffer::create(data.data(), data.size()) }};
+}
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
 } // namespace IPC

Modified: trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h (237623 => 237624)


--- trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/Shared/WebCoreArgumentCoders.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -164,6 +164,10 @@
 struct MediaConstraints;
 #endif
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+struct SerializedAttachmentData;
+#endif
+
 #if ENABLE(INDEXED_DATABASE)
 using IDBKeyPath = Variant<String, Vector<String>>;
 #endif
@@ -720,6 +724,15 @@
     static std::optional<WebCore::FontAttributes> decode(Decoder&);
 };
 
+#if ENABLE(ATTACHMENT_ELEMENT)
+
+template<> struct ArgumentCoder<WebCore::SerializedAttachmentData> {
+    static void encode(Encoder&, const WebCore::SerializedAttachmentData&);
+    static std::optional<WebCore::SerializedAttachmentData> decode(Decoder&);
+};
+
+#endif // ENABLE(ATTACHMENT_ELEMENT)
+
 } // namespace IPC
 
 namespace WTF {

Modified: trunk/Source/WebKit/UIProcess/API/APIAttachment.cpp (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/API/APIAttachment.cpp	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/API/APIAttachment.cpp	2018-10-31 05:29:17 UTC (rev 237624)
@@ -96,6 +96,15 @@
     return nullptr;
 }
 
+RefPtr<WebCore::SharedBuffer> Attachment::createSerializedRepresentation() const
+{
+    return nullptr;
+}
+
+void Attachment::updateFromSerializedRepresentation(Ref<WebCore::SharedBuffer>&&, const WTF::String&)
+{
+}
+
 #endif // !PLATFORM(COCOA)
 
 }

Modified: trunk/Source/WebKit/UIProcess/API/APIAttachment.h (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/API/APIAttachment.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/API/APIAttachment.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -85,6 +85,9 @@
     void setHasEnclosingImage(bool hasEnclosingImage) { m_hasEnclosingImage = hasEnclosingImage; }
     bool hasEnclosingImage() const { return m_hasEnclosingImage; }
 
+    RefPtr<WebCore::SharedBuffer> createSerializedRepresentation() const;
+    void updateFromSerializedRepresentation(Ref<WebCore::SharedBuffer>&&, const WTF::String& contentType);
+
 private:
     explicit Attachment(const WTF::String& identifier, WebKit::WebPageProxy&);
 

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/APIAttachmentCocoa.mm (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/APIAttachmentCocoa.mm	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/APIAttachmentCocoa.mm	2018-10-31 05:29:17 UTC (rev 237624)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "APIAttachment.h"
 
+#import "PageClient.h"
 #import <WebCore/MIMETypeRegistry.h>
 #import <WebCore/SharedBuffer.h>
 #if PLATFORM(IOS_FAMILY)
@@ -33,6 +34,7 @@
 #else
 #import <CoreServices/CoreServices.h>
 #endif
+#import <pal/spi/cocoa/NSKeyedArchiverSPI.h>
 
 namespace API {
 
@@ -125,4 +127,33 @@
     return !m_fileWrapper;
 }
 
+RefPtr<WebCore::SharedBuffer> Attachment::createSerializedRepresentation() const
+{
+    if (!m_fileWrapper || !m_webPage)
+        return nullptr;
+
+    NSData *serializedData = securelyArchivedDataWithRootObject(m_fileWrapper.get());
+    if (!serializedData)
+        return nullptr;
+
+    return WebCore::SharedBuffer::create(serializedData);
+}
+
+void Attachment::updateFromSerializedRepresentation(Ref<WebCore::SharedBuffer>&& serializedRepresentation, const WTF::String& contentType)
+{
+    if (!m_webPage)
+        return;
+
+    auto serializedData = serializedRepresentation->createNSData();
+    if (!serializedData)
+        return;
+
+    NSFileWrapper *fileWrapper = unarchivedObjectOfClassesFromData(m_webPage->pageClient().serializableFileWrapperClasses(), serializedData.get());
+    if (!fileWrapper)
+        return;
+
+    setFileWrapperAndUpdateContentType(fileWrapper, contentType);
+    m_webPage->updateAttachmentAttributes(*this, [] (auto) { });
+}
+
 } // namespace API

Modified: trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -45,7 +45,8 @@
 #if ENABLE(ATTACHMENT_ELEMENT)
     void didInsertAttachment(API::Attachment&, const String& source) final;
     void didRemoveAttachment(API::Attachment&) final;
-    NSFileWrapper *allocFileWrapperInstance() final;
+    NSFileWrapper *allocFileWrapperInstance() const final;
+    NSSet *serializableFileWrapperClasses() const final;
 #endif
 
 protected:

Modified: trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm	2018-10-31 05:29:17 UTC (rev 237624)
@@ -66,7 +66,7 @@
 #endif
 }
 
-NSFileWrapper *PageClientImplCocoa::allocFileWrapperInstance()
+NSFileWrapper *PageClientImplCocoa::allocFileWrapperInstance() const
 {
 #if WK_API_ENABLED
     Class cls = m_webView.configuration._attachmentFileWrapperClass ?: [NSFileWrapper self];
@@ -76,6 +76,17 @@
 #endif
 }
 
+NSSet *PageClientImplCocoa::serializableFileWrapperClasses() const
+{
+    Class defaultFileWrapperClass = NSFileWrapper.self;
+#if WK_API_ENABLED
+    Class configuredFileWrapperClass = m_webView.configuration._attachmentFileWrapperClass;
+    if (configuredFileWrapperClass && configuredFileWrapperClass != defaultFileWrapperClass)
+        return [NSSet setWithObjects:configuredFileWrapperClass, defaultFileWrapperClass, nil];
 #endif
+    return [NSSet setWithObjects:defaultFileWrapperClass, nil];
+}
+
+#endif
     
 }

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -45,6 +45,7 @@
 
 OBJC_CLASS CALayer;
 OBJC_CLASS NSFileWrapper;
+OBJC_CLASS NSSet;
 OBJC_CLASS _WKRemoteObjectRegistry;
 
 #if USE(APPKIT)
@@ -445,7 +446,8 @@
     virtual void didInsertAttachment(API::Attachment&, const String& source) { }
     virtual void didRemoveAttachment(API::Attachment&) { }
 #if PLATFORM(COCOA)
-    virtual NSFileWrapper *allocFileWrapperInstance() { return nullptr; }
+    virtual NSFileWrapper *allocFileWrapperInstance() const { return nullptr; }
+    virtual NSSet *serializableFileWrapperClasses() const { return nullptr; }
 #endif
 #endif
 };

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-10-31 05:29:17 UTC (rev 237624)
@@ -7900,6 +7900,15 @@
         m_attachmentIdentifierToAttachmentMap.set(identifier, ensureAttachment(identifier));
 }
 
+void WebPageProxy::registerAttachmentsFromSerializedData(Vector<WebCore::SerializedAttachmentData>&& data)
+{
+    for (auto& serializedData : data) {
+        auto identifier = WTFMove(serializedData.identifier);
+        if (!attachmentForIdentifier(identifier))
+            ensureAttachment(identifier)->updateFromSerializedRepresentation(WTFMove(serializedData.data), WTFMove(serializedData.mimeType));
+    }
+}
+
 void WebPageProxy::cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier)
 {
     auto newAttachment = ensureAttachment(toIdentifier);
@@ -7925,6 +7934,21 @@
     m_attachmentIdentifierToAttachmentMap.clear();
 }
 
+void WebPageProxy::serializedAttachmentDataForIdentifiers(const Vector<String>& identifiers, Vector<WebCore::SerializedAttachmentData>& serializedData)
+{
+    for (auto identifier : identifiers) {
+        auto attachment = attachmentForIdentifier(identifier);
+        if (!attachment)
+            continue;
+
+        auto data = ""
+        if (!data)
+            continue;
+
+        serializedData.append({ identifier, attachment->mimeType(), data.releaseNonNull() });
+    }
+}
+
 #if !PLATFORM(COCOA)
 
 void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&&, const String&, const IPC::DataReference&)

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -231,6 +231,7 @@
 class RemoteLayerTreeTransaction;
 class RemoteScrollingCoordinatorProxy;
 class SecKeyProxyStore;
+class SharedBufferDataReference;
 class UserData;
 class ViewSnapshot;
 class VisitedLinkStore;
@@ -1344,6 +1345,7 @@
     RefPtr<API::Attachment> attachmentForIdentifier(const String& identifier) const;
     void insertAttachment(Ref<API::Attachment>&&, Function<void(CallbackBase::Error)>&&);
     void updateAttachmentAttributes(const API::Attachment&, Function<void(CallbackBase::Error)>&&);
+    void serializedAttachmentDataForIdentifiers(const Vector<String>&, Vector<WebCore::SerializedAttachmentData>&);
 #endif
 
 #if ENABLE(APPLICATION_MANIFEST)
@@ -1829,6 +1831,7 @@
 #if ENABLE(ATTACHMENT_ELEMENT)
     void registerAttachmentIdentifierFromData(const String&, const String& contentType, const String& preferredFileName, const IPC::DataReference&);
     void registerAttachmentIdentifierFromFilePath(const String&, const String& contentType, const String& filePath);
+    void registerAttachmentsFromSerializedData(Vector<WebCore::SerializedAttachmentData>&&);
     void registerAttachmentIdentifier(const String&);
     void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier);
 

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (237623 => 237624)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2018-10-31 05:29:17 UTC (rev 237624)
@@ -534,9 +534,11 @@
     RegisterAttachmentIdentifierFromData(String identifier, String contentType, String preferredFileName, IPC::SharedBufferDataReference data)
     RegisterAttachmentIdentifierFromFilePath(String identifier, String contentType, String filePath)
     RegisterAttachmentIdentifier(String identifier)
+    registerAttachmentsFromSerializedData(Vector<WebCore::SerializedAttachmentData> data)
     CloneAttachmentData(String fromIdentifier, String toIdentifier)
     DidInsertAttachmentWithIdentifier(String identifier, String source, bool hasEnclosingImage)
     DidRemoveAttachmentWithIdentifier(String identifier)
+    SerializedAttachmentDataForIdentifiers(Vector<String> identifiers) -> (Vector<WebCore::SerializedAttachmentData> seralizedData) LegacySync
 #endif
 
 #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp (237623 => 237624)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp	2018-10-31 05:29:17 UTC (rev 237624)
@@ -49,6 +49,7 @@
 #include <WebCore/KeyboardEvent.h>
 #include <WebCore/NotImplemented.h>
 #include <WebCore/Page.h>
+#include <WebCore/SerializedAttachmentData.h>
 #include <WebCore/SpellChecker.h>
 #include <WebCore/StyleProperties.h>
 #include <WebCore/TextIterator.h>
@@ -165,6 +166,11 @@
     m_page->send(Messages::WebPageProxy::RegisterAttachmentIdentifierFromData(identifier, contentType, preferredFileName, { data }));
 }
 
+void WebEditorClient::registerAttachments(Vector<WebCore::SerializedAttachmentData>&& data)
+{
+    m_page->send(Messages::WebPageProxy::registerAttachmentsFromSerializedData(WTFMove(data)));
+}
+
 void WebEditorClient::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& filePath)
 {
     m_page->send(Messages::WebPageProxy::RegisterAttachmentIdentifierFromFilePath(identifier, contentType, filePath));
@@ -190,6 +196,13 @@
     m_page->send(Messages::WebPageProxy::DidRemoveAttachmentWithIdentifier(identifier));
 }
 
+Vector<SerializedAttachmentData> WebEditorClient::serializedAttachmentDataForIdentifiers(const Vector<String>& identifiers)
+{
+    Vector<WebCore::SerializedAttachmentData> serializedData;
+    m_page->sendSync(Messages::WebPageProxy::SerializedAttachmentDataForIdentifiers(identifiers), Messages::WebPageProxy::SerializedAttachmentDataForIdentifiers::Reply(serializedData));
+    return serializedData;
+}
+
 #endif
 
 void WebEditorClient::didApplyStyle()

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h (237623 => 237624)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h	2018-10-31 05:29:17 UTC (rev 237624)
@@ -63,10 +63,12 @@
     void registerAttachmentIdentifier(const String&, const String& contentType, const String& preferredFileName, Ref<WebCore::SharedBuffer>&&) final;
     void registerAttachmentIdentifier(const String&, const String& contentType, const String& filePath) final;
     void registerAttachmentIdentifier(const String&) final;
+    void registerAttachments(Vector<WebCore::SerializedAttachmentData>&&) final;
     void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier) final;
     void didInsertAttachmentWithIdentifier(const String& identifier, const String& source, bool hasEnclosingImage) final;
     void didRemoveAttachmentWithIdentifier(const String& identifier) final;
     bool supportsClientSideAttachmentData() const final { return true; }
+    Vector<WebCore::SerializedAttachmentData> serializedAttachmentDataForIdentifiers(const Vector<String>&) final;
 #endif
 
     void didBeginEditing() final;

Modified: trunk/Tools/ChangeLog (237623 => 237624)


--- trunk/Tools/ChangeLog	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Tools/ChangeLog	2018-10-31 05:29:17 UTC (rev 237624)
@@ -1,3 +1,21 @@
+2018-10-30  Wenson Hsieh  <[email protected]>
+
+        [Cocoa] Attachment dropped from one web view to another is missing its file wrapper
+        https://bugs.webkit.org/show_bug.cgi?id=190530
+        <rdar://problem/45232149>
+
+        Reviewed by Tim Horton.
+
+        Add a test to verify that copying different types of attachments and pasting in a new web view inserts
+        attachments in the second web view that are backed by _WKAttachment objects, whose NSFileWrappers hold data that
+        is equivalent to the original file wrappers used to insert attachments in the first web view.
+
+        Existing API tests verify that when copying and pasting within a single web view, the pasted attachment element
+        is still backed by the same NSFileWrapper instance.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
+        (TestWebKitAPI::TEST):
+
 2018-10-30  Fujii Hironori  <[email protected]>
 
         [Win] Remove obsolete code for Visual Studio Express in webkitdirs.pm

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm (237623 => 237624)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2018-10-31 05:05:31 UTC (rev 237623)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm	2018-10-31 05:29:17 UTC (rev 237624)
@@ -1462,6 +1462,52 @@
     EXPECT_EQ([FileWrapper self], [insertedAttachments.firstObject.info.fileWrapper class]);
 }
 
+TEST(WKAttachmentTests, CopyAndPasteBetweenWebViews)
+{
+    auto file = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testHTMLData()]);
+    [file setPreferredFilename:@"test.foobar"];
+    auto image = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testImageData()]);
+    auto document = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testPDFData()]);
+    auto folder = adoptNS([[NSFileWrapper alloc] initDirectoryWithFileWrappers:@{ @"image.png": image.get(), @"document.pdf": document.get() }]);
+    [folder setPreferredFilename:@"folder"];
+    auto archive = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testZIPData()]);
+    [archive setPreferredFilename:@"archive"];
+
+    @autoreleasepool {
+        auto firstWebView = webViewForTestingAttachments();
+        [firstWebView synchronouslyInsertAttachmentWithFileWrapper:file.get() contentType:@"application/octet-stream"];
+        [firstWebView synchronouslyInsertAttachmentWithFileWrapper:folder.get() contentType:(__bridge NSString *)kUTTypeFolder];
+        [firstWebView synchronouslyInsertAttachmentWithFileWrapper:archive.get() contentType:@"application/zip"];
+        [firstWebView selectAll:nil];
+        [firstWebView _executeEditCommand:@"Copy" argument:nil completion:nil];
+    }
+
+    auto secondWebView = webViewForTestingAttachments();
+    ObserveAttachmentUpdatesForScope observer(secondWebView.get());
+    [secondWebView paste:nil];
+    [secondWebView expectElementCount:3 tagName:@"attachment"];
+    EXPECT_EQ(3U, observer.observer().inserted.count);
+
+    NSString *plainFileIdentifier = [secondWebView stringByEvaluatingJavaScript:@"document.querySelector('attachment[title^=test]').uniqueIdentifier"];
+    NSString *folderIdentifier = [secondWebView stringByEvaluatingJavaScript:@"document.querySelector('attachment[title=folder]').uniqueIdentifier"];
+    NSString *archiveIdentifier = [secondWebView stringByEvaluatingJavaScript:@"document.querySelector('attachment[title=archive]').uniqueIdentifier"];
+
+    _WKAttachmentInfo *pastedFileInfo = [secondWebView _attachmentForIdentifier:plainFileIdentifier].info;
+    _WKAttachmentInfo *pastedFolderInfo = [secondWebView _attachmentForIdentifier:folderIdentifier].info;
+    _WKAttachmentInfo *pastedArchiveInfo = [secondWebView _attachmentForIdentifier:archiveIdentifier].info;
+
+    NSDictionary<NSString *, NSFileWrapper *> *pastedFolderContents = pastedFolderInfo.fileWrapper.fileWrappers;
+    NSFileWrapper *documentFromFolder = [pastedFolderContents objectForKey:@"document.pdf"];
+    NSFileWrapper *imageFromFolder = [pastedFolderContents objectForKey:@"image.png"];
+    EXPECT_TRUE([[document regularFileContents] isEqualToData:documentFromFolder.regularFileContents]);
+    EXPECT_TRUE([[image regularFileContents] isEqualToData:imageFromFolder.regularFileContents]);
+    EXPECT_TRUE([[file regularFileContents] isEqualToData:pastedFileInfo.fileWrapper.regularFileContents]);
+    EXPECT_TRUE([[archive regularFileContents] isEqualToData:pastedArchiveInfo.fileWrapper.regularFileContents]);
+    EXPECT_WK_STREQ("application/octet-stream", pastedFileInfo.contentType);
+    EXPECT_WK_STREQ("public.directory", pastedFolderInfo.contentType);
+    EXPECT_WK_STREQ("application/zip", pastedArchiveInfo.contentType);
+}
+
 #pragma mark - Platform-specific tests
 
 #if PLATFORM(MAC)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to