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)