WebKit Bugzilla
Attachment 347500 Details for
Bug 188744
: Test bug; please ignore
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188744-20180820085341.patch (text/plain), 144.71 KB, created by
Wenson Hsieh
on 2018-08-20 08:53:42 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2018-08-20 08:53:42 PDT
Size:
144.71 KB
patch
obsolete
>Subversion Revision: 235065 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 70bd1a9cd7558064b57c991ae1cbb4050ab43f7a..a1f0b2cb10018adb945a385757bd354aada3a040 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,124 @@ >+2018-08-18 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Test bug; please ignore >+ https://bugs.webkit.org/show_bug.cgi?id=188744 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Refactors logic around HTMLAttachmentElement and pasteboard reading helpers, in support of moving the data >+ backing for attachment elements to the client layer, instead of keeping it in the attachment element's File. >+ Augmented existing API tests in WKAttachmentTests, and also added a new API test (see Tools for more detail). >+ >+ * WebCore.xcodeproj/project.pbxproj: >+ * dom/Document.cpp: >+ (WebCore::Document::didInsertAttachmentElement): >+ >+ Notify the client layer when a newly inserted attachment element's identifier has been updated to avoid >+ colliding with the identifier of an existing attachment element. This can happen if, for instance, one or more >+ attachments are copied and pasted within the same document. >+ >+ * editing/Editor.cpp: >+ (WebCore::Editor::registerAttachmentIdentifier): >+ (WebCore::Editor::cloneAttachmentData): >+ >+ Add new helper functions to notify the client when the attachment identifier to data mapping needs to be >+ updated. This can happen in three ways: (1) an attachment is created with raw data, or (2) an attachment is >+ created with a file path, or (3) the unique identifier for an attachment element has been reassigned. These >+ correspond to the two versions of `registerAttachmentIdentifier`, and `cloneAttachmentData`, respectively. >+ >+ (WebCore::EditorClient::supportsClientSideAttachmentData const): >+ >+ Add a new EditorClient hook to determine whether client-side attachment data management is supported. Currently, >+ this only returns true for WebKit2. If this flag is set to true, we register attachment identifiers and don't >+ create a new File object for the attachment element; otherwise, fall back to creating and setting a File for the >+ new attachment element. >+ >+ (WebCore::Editor::insertAttachment): >+ (WebCore::Editor::insertAttachmentFromFile): Deleted. >+ >+ Adjust logic when inserting an attachment; we now only need to update the attributes of the attachment element >+ with metadata from the client layer. >+ >+ * editing/Editor.h: >+ * editing/cocoa/WebContentReaderCocoa.mm: >+ (WebCore::supportsClientSideAttachmentData): >+ (WebCore::createFragmentForImageAttachment): >+ >+ Notify the client when creating an attachment element from image data on the pasteboard. >+ >+ (WebCore::replaceRichContentWithAttachments): >+ >+ Refactor this helper function to no longer connect attachment elements to File objects created from >+ subresources. Instead, just update each attachment element's attributes using information about the subresource, >+ and then notify the client about the new attachment data and attachment identifier. >+ >+ (WebCore::createFragmentAndAddResources): >+ (WebCore::sanitizeMarkupWithArchive): >+ >+ Plumb the current WebContentReader's Frame& to each of these helpers, so that it can call out to the client. >+ >+ (WebCore::WebContentReader::readWebArchive): >+ (WebCore::WebContentMarkupReader::readWebArchive): >+ (WebCore::WebContentReader::readImage): >+ (WebCore::WebContentReader::readFilePaths): >+ >+ Notify the client when creating an attachment from the path of a dropped file. >+ >+ * html/AttachmentTypes.h: >+ >+ Remove AttachmentInfo. This is no longer necessary because we don't need to request attachment data from the web >+ process anymore. >+ >+ * html/HTMLAttachmentElement.cpp: >+ (WebCore::HTMLAttachmentElement::ensureUniqueIdentifier): >+ >+ Add a helper function on the attachment element to create and return a unique identifier if needed. >+ >+ (WebCore::HTMLAttachmentElement::updateAttributes): >+ >+ Add a helper method to update the displayed element attributes (type, title and subtitle) or an attachment. >+ >+ (WebCore::AttachmentDataReader::create): Deleted. >+ (WebCore::AttachmentDataReader::AttachmentDataReader): Deleted. >+ >+ Remove AttachmentDataReader. This helper class was only used to load attachment data when requesting attachment >+ information in the client, but this is now obviated by moving attachment data to the client layer. >+ >+ (): Deleted. >+ (WebCore::HTMLAttachmentElement::updateFileWithData): Deleted. >+ (WebCore::HTMLAttachmentElement::requestInfo): Deleted. >+ (WebCore::HTMLAttachmentElement::destroyReader): Deleted. >+ (WebCore::AttachmentDataReader::~AttachmentDataReader): Deleted. >+ (WebCore::AttachmentDataReader::didFinishLoading): Deleted. >+ (WebCore::AttachmentDataReader::didFail): Deleted. >+ (WebCore::AttachmentDataReader::invokeCallbackAndFinishReading): Deleted. >+ * html/HTMLAttachmentElement.h: >+ * page/DragClient.h: >+ * page/DragController.cpp: >+ (WebCore::DragController::startDrag): >+ (WebCore::DragController::doSystemDrag): >+ (WebCore::DragController::promisedAttachmentInfo): >+ >+ Allow dragging an attachment (even if it does not have a file) as long as it has a unique identifier and a >+ content type. >+ >+ (WebCore::DragController::promisedBlobInfo): Deleted. >+ * page/DragController.h: >+ * page/EditorClient.h: >+ (WebCore::EditorClient::registerAttachmentIdentifier): >+ (WebCore::EditorClient::cloneAttachmentData): >+ * platform/DragItem.h: >+ (WebCore::DragItem::encode const): >+ (WebCore::DragItem::decode): >+ * platform/PromisedAttachmentInfo.h: Renamed from Source/WebCore/platform/PromisedBlobInfo.h. >+ >+ Add an attachment identifier to PromisedBlobInfo. Additionally, rename PromisedBlobInfo to >+ PromisedAttachmentInfo, since it is currently exclusively used to attachment element data to the pasteboard. >+ In the future, this could be renamed to something more general (e.g. PromisedPasteboardData), should we use this >+ mechanism to write data from other sources to the pasteboard. >+ >+ (WebCore::PromisedAttachmentInfo::operator bool const): >+ > 2018-08-20 Rob Buis <rbuis@igalia.com> > > Throw an exception if window.open() gets passed a URL that cannot be parsed >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 65f4f102ac5f23d0bbaab46c05b406eb0ed4a9bb..7657996e14c287b4259971f86a9a5b2e964ebb3d 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,183 @@ >+2018-08-18 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Test bug; please ignore >+ https://bugs.webkit.org/show_bug.cgi?id=188744 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adjusts WebKit's attachment editing SPI with the following modifications: >+ ⢠Deprecate `-_insertAttachmentWithFilename:contentType:data:options:completion:` in favor of >+ `-_insertAttachmentWithFileWrapper:contentType:options:completion:`. >+ ⢠Deprecate `-requestInfo:` and in favor of just `-info`. >+ ⢠Add a `-fileWrapper` property to `_WKAttachmentInfo` that returns an `NSFileWrapper`. >+ ⢠Remove some SPI methods that would otherwise be deprecated, but are not even necessary, since they're no >+ longer even used by Mail. >+ >+ To make this possible, we refactor where and how attachment data is tracked. Currently, the data is stored in >+ the network process, and made accessible to the web process via blob URLs stored in the File object in the >+ attachment element. As such, requests from the UI process for attachment data would first be routed through the >+ web process to network process and back. >+ >+ Instead, we now keep the relevant attachment data (in the form of NSFileWrapper on Cocoa platforms) in the UI >+ process, on API::Attachment. We additionally keep a map of attachment identifiers to API::Attachments, which >+ allows us to propagate the same _WKAttachment wrapper object to the SPI client for each uniquely identified >+ attachment element. This also has the benefit of allowing us to remove the asynchronous version of `-requestInfo:` >+ and replace it with just an `info` property. >+ >+ Changes are covered by new and existing API tests. >+ >+ * Scripts/webkit/messages.py: >+ * Shared/WebCoreArgumentCoders.cpp: >+ (IPC::ArgumentCoder<PromisedAttachmentInfo>::encode): >+ (IPC::ArgumentCoder<PromisedAttachmentInfo>::decode): >+ (IPC::ArgumentCoder<PromisedBlobInfo>::encode): Deleted. >+ (IPC::ArgumentCoder<PromisedBlobInfo>::decode): Deleted. >+ (IPC::ArgumentCoder<AttachmentInfo>::encode): Deleted. >+ (IPC::ArgumentCoder<AttachmentInfo>::decode): Deleted. >+ * Shared/WebCoreArgumentCoders.h: >+ >+ Continue removing encoding support for WebCore::AttachmentInfo. Additionally, rename PromisedBlobInfo to >+ PromisedAttachmentInfo. >+ >+ * UIProcess/API/APIAttachment.cpp: >+ (API::Attachment::updateAttributes): >+ >+ Rename setDataAndContentType to just updateAttributes; instead of sending data, only send the information needed >+ to update the presentational attributes of the attachment element. >+ >+ (API::Attachment::requestInfo): Deleted. >+ >+ Just call the completion handler with the result of `self.info`. >+ >+ (API::Attachment::setDataAndContentType): Deleted. >+ * UIProcess/API/APIAttachment.h: >+ >+ Add additional attributes: a content type, a file path, and (on Cocoa platforms) an NSFileWrapper. >+ >+ * UIProcess/API/Cocoa/WKUIDelegatePrivate.h: >+ >+ Remove -_webView:didInsertAttachment:, since this is unused by any client currently, and is superceded by >+ -_webView:didInsertAttachment:withSource:. >+ >+ * UIProcess/API/Cocoa/WKWebView.mm: >+ (-[WKWebView _didInsertAttachment:withSource:]): >+ (-[WKWebView _didRemoveAttachment:]): >+ >+ Look up the API::Attachment corresponding to the identifier, and send its wrapper object to the client. >+ >+ (-[WKWebView _insertAttachmentWithFilename:contentType:data:options:completion:]): >+ (-[WKWebView _insertAttachmentWithFileWrapper:contentType:options:completion:]): >+ >+ Add a way to insert an attachment using NSFileWrapper, and reimplement _insertAttachmentWithFilename: using it. >+ >+ * UIProcess/API/Cocoa/WKWebViewPrivate.h: >+ * UIProcess/API/Cocoa/_WKAttachment.h: >+ * UIProcess/API/Cocoa/_WKAttachment.mm: >+ (-[_WKAttachmentInfo initWithFileWrapper:filePath:contentType:]): >+ (-[_WKAttachmentInfo data]): >+ (-[_WKAttachmentInfo name]): >+ (isDeclaredOrDynamicTypeIdentifier): >+ (-[_WKAttachmentInfo _typeIdentifierFromPathExtension]): >+ (-[_WKAttachmentInfo contentType]): >+ (-[_WKAttachmentInfo mimeType]): >+ (-[_WKAttachmentInfo utiType]): >+ (-[_WKAttachmentInfo fileWrapper]): >+ (-[_WKAttachment info]): >+ (-[_WKAttachment requestInfo:]): >+ >+ Add a property on _WKAttachment to retrieve a _WKAttachmentInfo (a snapshot of the current state of the >+ attachment, along with the NSFileWrapper). Reimplement requestInfo using this property. >+ >+ (-[_WKAttachment setFileWrapper:contentType:completion:]): >+ (-[_WKAttachment setData:newContentType:newFilename:completion:]): >+ >+ Reimplemented by calling -setFileWrapper:contentType:completion: with an NSFileWrapper created using the given >+ data. Additionally, create and associate the unique identifier with an API::Attachment right away. >+ >+ (-[_WKAttachment uniqueIdentifier]): >+ (-[_WKAttachment description]): >+ (-[_WKAttachmentInfo initWithInfo:]): Deleted. >+ (-[_WKAttachmentInfo fileLoadingError]): Deleted. >+ (-[_WKAttachment isEqual:]): Deleted. >+ (-[_WKAttachment hash]): Deleted. >+ >+ There's no longer any point to implementing these methods, since the SPI client is now guaranteed a unique >+ mapping of _WKAttachments to attachment elements in the document. >+ >+ * UIProcess/Cocoa/PageClientImplCocoa.mm: >+ (WebKit::PageClientImplCocoa::didInsertAttachment): >+ * UIProcess/Cocoa/WebPageProxyCocoa.mm: >+ (WebKit::WebPageProxy::platformRegisterAttachment): >+ (WebKit::WebPageProxy::platformCloneAttachment): >+ >+ Extend the behavior of registering new attachment data on Cocoa platforms by additionally creating and setting >+ NSFileWrappers on the API::Attachment. >+ >+ * UIProcess/WebPageProxy.cpp: >+ (WebKit::WebPageProxy::resetStateAfterProcessExited): >+ >+ Clear out the map of attachment identifiers to API::Attachments when the web content process is terminated. >+ >+ (WebKit::WebPageProxy::attachmentForIdentifier const): >+ >+ Helper function to look up an API::Attachment for the given attachment identifier. Returns null if the >+ attachment is not found, or the attachment identifier is invalid. >+ >+ (WebKit::WebPageProxy::insertAttachment): >+ (WebKit::WebPageProxy::updateAttachmentAttributes): >+ (WebKit::WebPageProxy::registerAttachmentIdentifierFromData): >+ (WebKit::WebPageProxy::registerAttachmentIdentifierFromFilePath): >+ (WebKit::WebPageProxy::cloneAttachmentData): >+ (WebKit::WebPageProxy::platformRegisterAttachment): >+ (WebKit::WebPageProxy::platformCloneAttachment): >+ (WebKit::WebPageProxy::didInsertAttachment): >+ >+ Create an entry in the attachment identifier to API::Attachment map when an attachment is inserted, if one does >+ not already exist. An attachment mapping would not exist only in the case where an attachment element was >+ created via bindings; in this case, the client wouldn't have access to an NSFileWrapper containing the contents >+ of the file; in the future, this can be improved by adding a mechanism to register an attachment element with >+ this data, but for now, this is unnecessary for Mail's purposes. >+ >+ (WebKit::WebPageProxy::didRemoveAttachment): >+ (WebKit::WebPageProxy::ensureAttachment): >+ >+ Ensures an attachment identifier to API::Attachment mapping. >+ >+ (WebKit::WebPageProxy::attachmentInfoCallback): Deleted. >+ (WebKit::WebPageProxy::requestAttachmentInfo): Deleted. >+ (WebKit::WebPageProxy::setAttachmentDataAndContentType): Deleted. >+ * UIProcess/WebPageProxy.h: >+ * UIProcess/WebPageProxy.messages.in: >+ * UIProcess/ios/PageClientImplIOS.h: >+ * UIProcess/ios/PageClientImplIOS.mm: >+ * UIProcess/ios/WKContentViewInteraction.h: >+ * UIProcess/ios/WKContentViewInteraction.mm: >+ (-[WKContentView _startDrag:item:]): >+ (-[WKContentView _prepareToDragPromisedAttachment:]): >+ (-[WKContentView _prepareToDragPromisedBlob:]): Deleted. >+ >+ Reimplement the way promised attachment data is delivered to the destination when an attachment element is >+ dragged. Instead of relying on the blob URL of the File on the attachment element, first try to find an API >+ Attachment object corresponding to the unique identifier of the dragged attachment, and use its NSFileWrapper to >+ deliver promised data to the destination file URL. The blob URL codepath still exists in the case where script >+ specifies the dragged attachment's File. >+ >+ * UIProcess/mac/PageClientImplMac.h: >+ * UIProcess/mac/PageClientImplMac.mm: >+ * WebProcess/WebCoreSupport/WebEditorClient.cpp: >+ (WebKit::WebEditorClient::registerAttachmentIdentifier): >+ (WebKit::WebEditorClient::cloneAttachmentData): >+ * WebProcess/WebCoreSupport/WebEditorClient.h: >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::insertAttachment): >+ (WebKit::WebPage::updateAttachmentAttributes): >+ (WebKit::WebPage::requestAttachmentInfo): Deleted. >+ (WebKit::WebPage::setAttachmentDataAndContentType): Deleted. >+ * WebProcess/WebPage/WebPage.h: >+ * WebProcess/WebPage/WebPage.messages.in: >+ >+ More renaming and IPC message plumbing. >+ > 2018-08-20 Carlos Garcia Campos <cgarcia@igalia.com> > > Unreviewed. Fix GTK/WPE cookie API tests after r234396. >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index e996fed47c89810aeb8e9456221bc8d6ca450314..2252118f880b11f2f186937a62fe6f068e09b326 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -4817,7 +4817,7 @@ > F478755419983AFF0024A287 /* ScrollSnapAnimatorState.h in Headers */ = {isa = PBXBuildFile; fileRef = F478755219983AFF0024A287 /* ScrollSnapAnimatorState.h */; settings = {ATTRIBUTES = (Private, ); }; }; > F47A09D120A93A9700240FAE /* DisabledAdaptations.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A09CF20A939F600240FAE /* DisabledAdaptations.h */; settings = {ATTRIBUTES = (Private, ); }; }; > F47A5E3E195B8C8A00483100 /* StyleScrollSnapPoints.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- F47A633D1FF6FD500081B3CC /* PromisedBlobInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A633C1FF6FD500081B3CC /* PromisedBlobInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; >+ F47A633D1FF6FD500081B3CC /* PromisedAttachmentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A633C1FF6FD500081B3CC /* PromisedAttachmentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; > F48223101E3869B80066FC79 /* WebItemProviderPasteboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = F482230E1E3869B80066FC79 /* WebItemProviderPasteboard.mm */; }; > F48223111E3869B80066FC79 /* WebItemProviderPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F482230F1E3869B80066FC79 /* WebItemProviderPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; }; > F48223131E386E240066FC79 /* AbstractPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F48223121E386E240066FC79 /* AbstractPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; }; >@@ -14566,7 +14566,7 @@ > F47A09D420A9DD0400240FAE /* DisabledAdaptations.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisabledAdaptations.cpp; sourceTree = "<group>"; }; > F47A5E3A195B8C8A00483100 /* StyleScrollSnapPoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleScrollSnapPoints.cpp; sourceTree = "<group>"; }; > F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleScrollSnapPoints.h; sourceTree = "<group>"; }; >- F47A633C1FF6FD500081B3CC /* PromisedBlobInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PromisedBlobInfo.h; sourceTree = "<group>"; }; >+ F47A633C1FF6FD500081B3CC /* PromisedAttachmentInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PromisedAttachmentInfo.h; sourceTree = "<group>"; }; > F482230E1E3869B80066FC79 /* WebItemProviderPasteboard.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebItemProviderPasteboard.mm; sourceTree = "<group>"; }; > F482230F1E3869B80066FC79 /* WebItemProviderPasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebItemProviderPasteboard.h; sourceTree = "<group>"; }; > F48223121E386E240066FC79 /* AbstractPasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPasteboard.h; sourceTree = "<group>"; }; >@@ -24602,7 +24602,7 @@ > BC3BE12A0E98092F00835588 /* PopupMenuStyle.h */, > 51F645D21FECDBC800B54DED /* Process.cpp */, > 51F645D31FECDBC800B54DED /* Process.h */, >- F47A633C1FF6FD500081B3CC /* PromisedBlobInfo.h */, >+ F47A633C1FF6FD500081B3CC /* PromisedAttachmentInfo.h */, > 0081FEFD16B0A244008AAA7A /* PublicSuffix.h */, > 5C97A3361F5F7A6500105207 /* RectEdges.h */, > CA1635DC2072E76900E7D2CE /* ReferrerPolicy.cpp */, >@@ -29850,7 +29850,7 @@ > A715E653134BBBEC00D8E713 /* ProgressShadowElement.h in Headers */, > 1A2A68240B5BEDE70002A480 /* ProgressTracker.h in Headers */, > 1ACADD791880D91C00D8B71D /* ProgressTrackerClient.h in Headers */, >- F47A633D1FF6FD500081B3CC /* PromisedBlobInfo.h in Headers */, >+ F47A633D1FF6FD500081B3CC /* PromisedAttachmentInfo.h in Headers */, > A578F4351DE00EEB003DFC6A /* PromiseRejectionEvent.h in Headers */, > E4BBED0F14F4025D003F0B98 /* PropertySetCSSStyleDeclaration.h in Headers */, > 37BAAE581980D1DD005DFE71 /* ProtectionSpace.h in Headers */, >diff --git a/Source/WebCore/dom/Document.cpp b/Source/WebCore/dom/Document.cpp >index 39b5342858a57e455f2cea8892dbdabf2842cdb3..da1acf54936f6664d526f9350218e34b529b9e71 100644 >--- a/Source/WebCore/dom/Document.cpp >+++ b/Source/WebCore/dom/Document.cpp >@@ -7944,15 +7944,21 @@ Vector<RefPtr<WebAnimation>> Document::getAnimations() > void Document::didInsertAttachmentElement(HTMLAttachmentElement& attachment) > { > auto identifier = attachment.uniqueIdentifier(); >- if (identifier.isEmpty() || m_attachmentIdentifierToElementMap.contains(identifier)) { >+ auto previousIdentifier = identifier; >+ bool previousIdentifierIsNotUnique = !previousIdentifier.isEmpty() && m_attachmentIdentifierToElementMap.contains(previousIdentifier); >+ if (identifier.isEmpty() || previousIdentifierIsNotUnique) { >+ previousIdentifier = identifier; > identifier = createCanonicalUUIDString(); > attachment.setUniqueIdentifier(identifier); > } > > m_attachmentIdentifierToElementMap.set(identifier, attachment); > >- if (frame()) >- frame()->editor().didInsertAttachmentElement(attachment); >+ if (auto* frame = this->frame()) { >+ if (previousIdentifierIsNotUnique) >+ frame->editor().cloneAttachmentData(previousIdentifier, identifier); >+ frame->editor().didInsertAttachmentElement(attachment); >+ } > } > > void Document::didRemoveAttachmentElement(HTMLAttachmentElement& attachment) >diff --git a/Source/WebCore/editing/Editor.cpp b/Source/WebCore/editing/Editor.cpp >index 1b20d78199c0b17d674dce0e851f37b65eab326a..c4a2f7b165435a63b9d4ed6fc396f1301f60eaa2 100644 >--- a/Source/WebCore/editing/Editor.cpp >+++ b/Source/WebCore/editing/Editor.cpp >@@ -3817,6 +3817,24 @@ void Editor::scheduleEditorUIUpdate() > > #if ENABLE(ATTACHMENT_ELEMENT) > >+void Editor::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& preferredFileName, Ref<SharedBuffer>&& data) >+{ >+ if (auto* client = this->client()) >+ client->registerAttachmentIdentifier(identifier, contentType, preferredFileName, WTFMove(data)); >+} >+ >+void Editor::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& filePath) >+{ >+ if (auto* client = this->client()) >+ client->registerAttachmentIdentifier(identifier, contentType, filePath); >+} >+ >+void Editor::cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier) >+{ >+ if (auto* client = this->client()) >+ client->cloneAttachmentData(fromIdentifier, toIdentifier); >+} >+ > void Editor::didInsertAttachmentElement(HTMLAttachmentElement& attachment) > { > auto identifier = attachment.uniqueIdentifier(); >@@ -3861,28 +3879,11 @@ void Editor::notifyClientOfAttachmentUpdates() > } > } > >-void Editor::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, const String& filepath, std::optional<String> contentType) >-{ >- if (!contentType) >- contentType = File::contentTypeForFile(filename); >- insertAttachmentFromFile(identifier, options, filename, *contentType, File::create(filepath)); >-} >- >-void Editor::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType) >-{ >- if (!contentType) >- contentType = File::contentTypeForFile(filename); >- insertAttachmentFromFile(identifier, options, filename, *contentType, File::create(Blob::create(WTFMove(data), *contentType), filename)); >-} >- >-void Editor::insertAttachmentFromFile(const String& identifier, const AttachmentDisplayOptions&, const String& filename, const String& contentType, Ref<File>&& file) >+void Editor::insertAttachment(const String& identifier, const AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String>&& explicitContentType) > { > auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document()); >- attachment->setAttribute(HTMLNames::titleAttr, filename); >- attachment->setAttribute(HTMLNames::subtitleAttr, fileSizeDescription(file->size())); >- attachment->setAttribute(HTMLNames::typeAttr, contentType); > attachment->setUniqueIdentifier(identifier); >- attachment->setFile(WTFMove(file)); >+ attachment->updateAttributes(fileSize, WTFMove(explicitContentType), fileName); > > auto fragmentToInsert = document().createDocumentFragment(); > fragmentToInsert->appendChild(attachment.get()); >diff --git a/Source/WebCore/editing/Editor.h b/Source/WebCore/editing/Editor.h >index 8ad78820b2251fdd0cfe6e3e34b03903bc841b32..e2bcc91a8d3635316ee6a2d440a65a0c949d6e75 100644 >--- a/Source/WebCore/editing/Editor.h >+++ b/Source/WebCore/editing/Editor.h >@@ -503,8 +503,10 @@ public: > bool isGettingDictionaryPopupInfo() const { return m_isGettingDictionaryPopupInfo; } > > #if ENABLE(ATTACHMENT_ELEMENT) >- WEBCORE_EXPORT void insertAttachment(const String& identifier, const AttachmentDisplayOptions&, const String& filename, const String& filepath, std::optional<String> contentType = std::nullopt); >- WEBCORE_EXPORT void insertAttachment(const String& identifier, const AttachmentDisplayOptions&, const String& filename, Ref<SharedBuffer>&& data, std::optional<String> contentType = std::nullopt); >+ WEBCORE_EXPORT void insertAttachment(const String& identifier, const AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String>&& explicitContentType = std::nullopt); >+ void registerAttachmentIdentifier(const String&, const String& /* contentType */, const String& /* preferredFileName */, Ref<SharedBuffer>&&); >+ void registerAttachmentIdentifier(const String&, const String& /* contentType */, const String& /* filePath */); >+ void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier); > void didInsertAttachmentElement(HTMLAttachmentElement&); > void didRemoveAttachmentElement(HTMLAttachmentElement&); > >@@ -516,10 +518,6 @@ public: > private: > Document& document() const; > >-#if ENABLE(ATTACHMENT_ELEMENT) >- void insertAttachmentFromFile(const String& identifier, const AttachmentDisplayOptions&, const String& filename, const String& contentType, Ref<File>&&); >-#endif >- > bool canDeleteRange(Range*) const; > bool canSmartReplaceWithPasteboard(Pasteboard&); > void pasteAsPlainTextWithPasteboard(Pasteboard&); >diff --git a/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm b/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm >index 1cb2b1ce6adca4656117cda274b0811d3188b459..b0cb79627838c226f15f727c4d9da0e7a0797587 100644 >--- a/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm >+++ b/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm >@@ -35,6 +35,7 @@ > #import "DocumentFragment.h" > #import "DocumentLoader.h" > #import "File.h" >+#import "FileSystem.h" > #import "Frame.h" > #import "FrameLoader.h" > #import "FrameLoaderClient.h" >@@ -204,11 +205,30 @@ static bool shouldReplaceRichContentWithAttachments() > #endif > } > >-static Ref<DocumentFragment> createFragmentForImageAttachment(Document& document, Ref<Blob>&& blob) >+#if ENABLE(ATTACHMENT_ELEMENT) >+ >+static bool supportsClientSideAttachmentData(const Frame& frame) >+{ >+ if (auto* client = frame.editor().client()) >+ return client->supportsClientSideAttachmentData(); >+ >+ return false; >+} >+ >+#endif >+ >+static Ref<DocumentFragment> createFragmentForImageAttachment(Frame& frame, Document& document, Ref<SharedBuffer>&& buffer, const String& contentType) > { > #if ENABLE(ATTACHMENT_ELEMENT) > auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document); >- attachment->setFile(File::create(blob, AtomicString("image")), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); >+ // FIXME: This fallback image name needs to be a localized string. >+ String defaultImageAttachmentName { "image"_s }; >+ >+ if (supportsClientSideAttachmentData(frame)) { >+ attachment->updateAttributes(buffer->size(), contentType, defaultImageAttachmentName); >+ frame.editor().registerAttachmentIdentifier(attachment->ensureUniqueIdentifier(), contentType, defaultImageAttachmentName, WTFMove(buffer)); >+ } else >+ attachment->setFile(File::create(Blob::create(buffer.get(), contentType), defaultImageAttachmentName), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); > > auto fragment = document.createDocumentFragment(); > fragment->appendChild(attachment); >@@ -220,11 +240,13 @@ static Ref<DocumentFragment> createFragmentForImageAttachment(Document& document > #endif > } > >-static void replaceRichContentWithAttachments(DocumentFragment& fragment, const Vector<Ref<ArchiveResource>>& subresources) >+static void replaceRichContentWithAttachments(Frame& frame, DocumentFragment& fragment, const Vector<Ref<ArchiveResource>>& subresources) > { > #if ENABLE(ATTACHMENT_ELEMENT) > struct AttachmentReplacementInfo { >- Ref<File> file; >+ String fileName; >+ String contentType; >+ Ref<SharedBuffer> data; > Ref<Element> elementToReplace; > }; > >@@ -233,11 +255,11 @@ static void replaceRichContentWithAttachments(DocumentFragment& fragment, const > return; > > // FIXME: Handle resources in subframe archives. >- HashMap<AtomicString, Ref<Blob>> urlToBlobMap; >- for (const Ref<ArchiveResource>& subresource : subresources) { >+ HashMap<AtomicString, Ref<ArchiveResource>> urlToResourceMap; >+ for (auto& subresource : subresources) { > auto& url = subresource->url(); > if (shouldReplaceSubresourceURL(url)) >- urlToBlobMap.set(url.string(), Blob::create(subresource->data(), subresource->mimeType())); >+ urlToResourceMap.set(url.string(), subresource.copyRef()); > } > > Vector<Ref<Element>> elementsToRemove; >@@ -247,15 +269,15 @@ static void replaceRichContentWithAttachments(DocumentFragment& fragment, const > if (resourceURLString.isEmpty()) > continue; > >- auto blob = urlToBlobMap.get(resourceURLString); >- if (!blob) >+ auto resource = urlToResourceMap.find(resourceURLString); >+ if (resource == urlToResourceMap.end()) > continue; > >- auto title = URLParser { resourceURLString }.result().lastPathComponent(); >- if (title.isEmpty()) >- title = AtomicString("media"); >+ auto name = URLParser { resourceURLString }.result().lastPathComponent(); >+ if (name.isEmpty()) >+ name = AtomicString("media"); > >- attachmentReplacementInfo.append({ File::create(*blob, title), image }); >+ attachmentReplacementInfo.append({ name, resource->value->mimeType(), resource->value->data(), image }); > } > > for (auto& object : descendantsOfType<HTMLObjectElement>(fragment)) { >@@ -265,28 +287,30 @@ static void replaceRichContentWithAttachments(DocumentFragment& fragment, const > continue; > } > >- auto blob = urlToBlobMap.get(resourceURLString); >- if (!blob) { >- elementsToRemove.append(object); >+ auto resource = urlToResourceMap.find(resourceURLString); >+ if (resource == urlToResourceMap.end()) > continue; >- } > >- auto title = URLParser { resourceURLString }.result().lastPathComponent(); >- if (title.isEmpty()) >- title = AtomicString("file"); >+ auto name = URLParser { resourceURLString }.result().lastPathComponent(); >+ if (name.isEmpty()) >+ name = AtomicString("file"); > >- attachmentReplacementInfo.append({ File::create(*blob, title), object }); >+ attachmentReplacementInfo.append({ name, resource->value->mimeType(), resource->value->data(), object }); > } > > for (auto& info : attachmentReplacementInfo) { >- auto file = WTFMove(info.file); > auto elementToReplace = WTFMove(info.elementToReplace); > auto parent = makeRefPtr(elementToReplace->parentNode()); > if (!parent) > continue; > > auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, fragment.document()); >- attachment->setFile(WTFMove(file), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); >+ if (supportsClientSideAttachmentData(frame)) { >+ attachment->updateAttributes(info.data->size(), info.contentType, info.fileName); >+ frame.editor().registerAttachmentIdentifier(attachment->ensureUniqueIdentifier(), WTFMove(info.contentType), WTFMove(info.fileName), WTFMove(info.data)); >+ } else >+ attachment->setFile(File::create(Blob::create(info.data, info.contentType), info.fileName), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); >+ > parent->replaceChild(attachment, elementToReplace); > } > >@@ -349,7 +373,7 @@ RefPtr<DocumentFragment> createFragmentAndAddResources(Frame& frame, NSAttribute > replaceSubresourceURLsWithURLsFromClient(*fragmentAndResources.fragment, fragmentAndResources.resources, unreplacedResources); > > if (shouldReplaceRichContentWithAttachments()) { >- replaceRichContentWithAttachments(*fragmentAndResources.fragment, unreplacedResources); >+ replaceRichContentWithAttachments(frame, *fragmentAndResources.fragment, unreplacedResources); > return WTFMove(fragmentAndResources.fragment); > } > >@@ -387,7 +411,7 @@ static std::optional<MarkupAndArchive> extractMarkupAndArchive(SharedBuffer& buf > return MarkupAndArchive { String::fromUTF8(mainResource->data().data(), mainResource->data().size()), mainResource.releaseNonNull(), archive.releaseNonNull() }; > } > >-static String sanitizeMarkupWithArchive(Document& destinationDocument, MarkupAndArchive& markupAndArchive, MSOListQuirks msoListQuirks, const std::function<bool(const String)>& canShowMIMETypeAsHTML) >+static String sanitizeMarkupWithArchive(Frame& frame, Document& destinationDocument, MarkupAndArchive& markupAndArchive, MSOListQuirks msoListQuirks, const std::function<bool(const String)>& canShowMIMETypeAsHTML) > { > auto page = createPageForSanitizingWebContent(); > Document* stagingDocument = page->mainFrame().document(); >@@ -398,7 +422,7 @@ static String sanitizeMarkupWithArchive(Document& destinationDocument, MarkupAnd > replaceSubresourceURLsWithURLsFromClient(fragment, markupAndArchive.archive->subresources(), unreplacedResources); > > if (shouldReplaceRichContentWithAttachments()) { >- replaceRichContentWithAttachments(fragment, unreplacedResources); >+ replaceRichContentWithAttachments(frame, fragment, unreplacedResources); > return sanitizedMarkupForFragmentInDocument(WTFMove(fragment), *stagingDocument, msoListQuirks, markupAndArchive.markup); > } > >@@ -428,7 +452,7 @@ static String sanitizeMarkupWithArchive(Document& destinationDocument, MarkupAnd > > MarkupAndArchive subframeContent = { String::fromUTF8(subframeMainResource->data().data(), subframeMainResource->data().size()), > subframeMainResource.releaseNonNull(), subframeArchive.copyRef() }; >- auto subframeMarkup = sanitizeMarkupWithArchive(destinationDocument, subframeContent, MSOListQuirks::Disabled, canShowMIMETypeAsHTML); >+ auto subframeMarkup = sanitizeMarkupWithArchive(frame, destinationDocument, subframeContent, MSOListQuirks::Disabled, canShowMIMETypeAsHTML); > > CString utf8 = subframeMarkup.utf8(); > Vector<uint8_t> blobBuffer; >@@ -469,7 +493,7 @@ bool WebContentReader::readWebArchive(SharedBuffer& buffer) > return true; > } > >- String sanitizedMarkup = sanitizeMarkupWithArchive(*frame.document(), *result, msoListQuirksForMarkup(), [&] (const String& type) { >+ String sanitizedMarkup = sanitizeMarkupWithArchive(frame, *frame.document(), *result, msoListQuirksForMarkup(), [&] (const String& type) { > return frame.loader().client().canShowMIMETypeAsHTML(type); > }); > fragment = createFragmentFromMarkup(*frame.document(), sanitizedMarkup, blankURL(), DisallowScriptingAndPluginContent); >@@ -496,7 +520,7 @@ bool WebContentMarkupReader::readWebArchive(SharedBuffer& buffer) > return true; > } > >- markup = sanitizeMarkupWithArchive(*frame.document(), *result, msoListQuirksForMarkup(), [&] (const String& type) { >+ markup = sanitizeMarkupWithArchive(frame, *frame.document(), *result, msoListQuirksForMarkup(), [&] (const String& type) { > return frame.loader().client().canShowMIMETypeAsHTML(type); > }); > >@@ -635,11 +659,10 @@ bool WebContentReader::readImage(Ref<SharedBuffer>&& buffer, const String& type) > return true; > } > >- auto blob = Blob::create(buffer.get(), type); > if (shouldReplaceRichContentWithAttachments()) >- addFragment(createFragmentForImageAttachment(document, WTFMove(blob))); >+ addFragment(createFragmentForImageAttachment(frame, document, WTFMove(buffer), type)); > else >- addFragment(createFragmentForImageAndURL(document, DOMURL::createObjectURL(document, blob))); >+ addFragment(createFragmentForImageAndURL(document, DOMURL::createObjectURL(document, Blob::create(buffer.get(), type)))); > > return fragment; > } >@@ -657,7 +680,15 @@ bool WebContentReader::readFilePaths(const Vector<String>& paths) > if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled()) { > for (auto& path : paths) { > auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document); >- attachment->setFile(File::create(path), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); >+ if (supportsClientSideAttachmentData(frame)) { >+ long long fileSize { 0 }; >+ FileSystem::getFileSize(path, fileSize); >+ auto contentType = File::contentTypeForFile(path); >+ attachment->updateAttributes(fileSize, contentType, FileSystem::pathGetFileName(path)); >+ frame.editor().registerAttachmentIdentifier(attachment->ensureUniqueIdentifier(), contentType, path); >+ } else >+ attachment->setFile(File::create(path), HTMLAttachmentElement::UpdateDisplayAttributes::Yes); >+ > fragment->appendChild(attachment); > } > } >diff --git a/Source/WebCore/html/AttachmentTypes.h b/Source/WebCore/html/AttachmentTypes.h >index b5077ca4082217550e1bf5cb74285cc4a43ee6cc..89bbcabae8f3412a7ee592bd66b09ae88ce24304 100644 >--- a/Source/WebCore/html/AttachmentTypes.h >+++ b/Source/WebCore/html/AttachmentTypes.h >@@ -32,8 +32,6 @@ > > namespace WebCore { > >-class SharedBuffer; >- > struct AttachmentDisplayOptions { > template<class Encoder> void encode(Encoder&) const; > template<class Decoder> static std::optional<AttachmentDisplayOptions> decode(Decoder&); >@@ -50,13 +48,6 @@ template<class Decoder> inline std::optional<AttachmentDisplayOptions> Attachmen > return AttachmentDisplayOptions(); > } > >-struct AttachmentInfo { >- String contentType; >- String name; >- String filePath; >- RefPtr<SharedBuffer> data; >-}; >- > } // namespace WebCore > > #endif // ENABLE(ATTACHMENT_ELEMENT) >diff --git a/Source/WebCore/html/HTMLAttachmentElement.cpp b/Source/WebCore/html/HTMLAttachmentElement.cpp >index e1719cd11f666035bd804db3b97b2f336a00f306..e74975f09fed05358f69a13fdfa66daeb810cc33 100644 >--- a/Source/WebCore/html/HTMLAttachmentElement.cpp >+++ b/Source/WebCore/html/HTMLAttachmentElement.cpp >@@ -32,14 +32,13 @@ > #include "Document.h" > #include "Editor.h" > #include "File.h" >-#include "FileReaderLoader.h" >-#include "FileReaderLoaderClient.h" > #include "Frame.h" > #include "HTMLNames.h" > #include "RenderAttachment.h" > #include "SharedBuffer.h" > #include <pal/FileSizeFormatter.h> > #include <wtf/IsoMallocInlines.h> >+#include <wtf/UUID.h> > > namespace WebCore { > >@@ -47,36 +46,6 @@ WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLAttachmentElement); > > using namespace HTMLNames; > >-class AttachmentDataReader : public FileReaderLoaderClient { >-public: >- static std::unique_ptr<AttachmentDataReader> create(HTMLAttachmentElement& attachment, Function<void(RefPtr<SharedBuffer>&&)>&& callback) >- { >- return std::make_unique<AttachmentDataReader>(attachment, WTFMove(callback)); >- } >- >- AttachmentDataReader(HTMLAttachmentElement& attachment, Function<void(RefPtr<SharedBuffer>&&)>&& callback) >- : m_attachment(attachment) >- , m_callback(std::make_unique<Function<void(RefPtr<SharedBuffer>&&)>>(WTFMove(callback))) >- , m_loader(std::make_unique<FileReaderLoader>(FileReaderLoader::ReadType::ReadAsArrayBuffer, this)) >- { >- m_loader->start(&attachment.document(), *attachment.file()); >- } >- >- ~AttachmentDataReader(); >- >-private: >- void didStartLoading() final { } >- void didReceiveData() final { } >- void didFinishLoading() final; >- void didFail(int error) final; >- >- void invokeCallbackAndFinishReading(RefPtr<SharedBuffer>&&); >- >- HTMLAttachmentElement& m_attachment; >- std::unique_ptr<Function<void(RefPtr<SharedBuffer>&&)>> m_callback; >- std::unique_ptr<FileReaderLoader> m_loader; >-}; >- > HTMLAttachmentElement::HTMLAttachmentElement(const QualifiedName& tagName, Document& document) > : HTMLElement(tagName, document) > { >@@ -140,6 +109,13 @@ void HTMLAttachmentElement::removedFromAncestor(RemovalType type, ContainerNode& > document().didRemoveAttachmentElement(*this); > } > >+String HTMLAttachmentElement::ensureUniqueIdentifier() >+{ >+ if (m_uniqueIdentifier.isEmpty()) >+ m_uniqueIdentifier = createCanonicalUUIDString(); >+ return m_uniqueIdentifier; >+} >+ > void HTMLAttachmentElement::parseAttribute(const QualifiedName& name, const AtomicString& value) > { > if (name == progressAttr || name == subtitleAttr || name == titleAttr || name == typeAttr) { >@@ -168,68 +144,17 @@ String HTMLAttachmentElement::attachmentPath() const > return attributeWithoutSynchronization(webkitattachmentpathAttr); > } > >-void HTMLAttachmentElement::updateFileWithData(Ref<SharedBuffer>&& data, std::optional<String>&& newContentType, std::optional<String>&& newFilename) >-{ >- auto filename = newFilename ? *newFilename : attachmentTitle(); >- auto contentType = newContentType ? *newContentType : File::contentTypeForFile(filename); >- auto file = File::create(Blob::create(WTFMove(data), contentType), filename); >- setFile(WTFMove(file), UpdateDisplayAttributes::Yes); >-} >- >-void HTMLAttachmentElement::requestInfo(Function<void(const AttachmentInfo&)>&& callback) >-{ >- if (!m_file) { >- callback({ }); >- return; >- } >- >- AttachmentInfo infoWithoutData { m_file->type(), m_file->name(), m_file->path(), nullptr }; >- if (!m_file->path().isEmpty()) { >- callback(infoWithoutData); >- return; >- } >- >- m_attachmentReaders.append(AttachmentDataReader::create(*this, [infoWithoutData = WTFMove(infoWithoutData), protectedFile = makeRef(*m_file), callback = WTFMove(callback)] (RefPtr<SharedBuffer>&& data) { >- callback({ infoWithoutData.contentType, infoWithoutData.name, infoWithoutData.filePath, WTFMove(data) }); >- })); >-} >- >-void HTMLAttachmentElement::destroyReader(AttachmentDataReader& finishedReader) >+void HTMLAttachmentElement::updateAttributes(uint64_t fileSize, std::optional<String>&& newContentType, std::optional<String>&& newFilename) > { >- m_attachmentReaders.removeFirstMatching([&] (const std::unique_ptr<AttachmentDataReader>& reader) -> bool { >- return reader.get() == &finishedReader; >- }); >-} >+ if (newFilename) >+ setAttributeWithoutSynchronization(HTMLNames::titleAttr, *newFilename); > >-AttachmentDataReader::~AttachmentDataReader() >-{ >- invokeCallbackAndFinishReading(nullptr); >-} >+ if (newContentType || newFilename) >+ setAttributeWithoutSynchronization(HTMLNames::typeAttr, newContentType ? *newContentType : File::contentTypeForFile(*newFilename)); > >-void AttachmentDataReader::didFinishLoading() >-{ >- if (auto arrayBuffer = m_loader->arrayBufferResult()) >- invokeCallbackAndFinishReading(SharedBuffer::create(reinterpret_cast<uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength())); >- else >- invokeCallbackAndFinishReading(nullptr); >- m_attachment.destroyReader(*this); >-} >- >-void AttachmentDataReader::didFail(int) >-{ >- invokeCallbackAndFinishReading(nullptr); >- m_attachment.destroyReader(*this); >-} >- >-void AttachmentDataReader::invokeCallbackAndFinishReading(RefPtr<SharedBuffer>&& data) >-{ >- auto callback = WTFMove(m_callback); >- if (!callback) >- return; >- >- m_loader->cancel(); >- m_loader = nullptr; >- (*callback)(WTFMove(data)); >+ setAttributeWithoutSynchronization(HTMLNames::subtitleAttr, fileSizeDescription(fileSize)); >+ if (auto* renderer = this->renderer()) >+ renderer->invalidate(); > } > > } // namespace WebCore >diff --git a/Source/WebCore/html/HTMLAttachmentElement.h b/Source/WebCore/html/HTMLAttachmentElement.h >index 14fc84bd9a5790160d0b87af33fd9849c4c9a93f..db806ac991a8fa345b6ae8cbbb48260e0f1e8697 100644 >--- a/Source/WebCore/html/HTMLAttachmentElement.h >+++ b/Source/WebCore/html/HTMLAttachmentElement.h >@@ -32,12 +32,8 @@ > > namespace WebCore { > >-class AttachmentDataReader; > class File; >-class HTMLImageElement; >-class HTMLVideoElement; > class RenderAttachment; >-class SharedBuffer; > > class HTMLAttachmentElement final : public HTMLElement { > WTF_MAKE_ISO_ALLOCATED(HTMLAttachmentElement); >@@ -53,20 +49,19 @@ public: > String uniqueIdentifier() const { return m_uniqueIdentifier; } > void setUniqueIdentifier(const String& uniqueIdentifier) { m_uniqueIdentifier = uniqueIdentifier; } > >- WEBCORE_EXPORT void updateFileWithData(Ref<SharedBuffer>&& data, std::optional<String>&& newContentType = std::nullopt, std::optional<String>&& newFilename = std::nullopt); >+ WEBCORE_EXPORT void updateAttributes(uint64_t fileSize, std::optional<String>&& newContentType = std::nullopt, std::optional<String>&& newFilename = std::nullopt); > > InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final; > void removedFromAncestor(RemovalType, ContainerNode&) final; > >+ String ensureUniqueIdentifier(); >+ > WEBCORE_EXPORT String attachmentTitle() const; > String attachmentType() const; > String attachmentPath() const; > > RenderAttachment* renderer() const; > >- WEBCORE_EXPORT void requestInfo(Function<void(const AttachmentInfo&)>&& callback); >- void destroyReader(AttachmentDataReader&); >- > private: > HTMLAttachmentElement(const QualifiedName&, Document&); > virtual ~HTMLAttachmentElement(); >@@ -83,7 +78,6 @@ private: > void parseAttribute(const QualifiedName&, const AtomicString&) final; > > RefPtr<File> m_file; >- Vector<std::unique_ptr<AttachmentDataReader>> m_attachmentReaders; > String m_uniqueIdentifier; > }; > >diff --git a/Source/WebCore/page/DragClient.h b/Source/WebCore/page/DragClient.h >index b74485d07ebe781ed4b67463b05c8061445464b3..37860680996e39cae3883db487703e8e4a27673e 100644 >--- a/Source/WebCore/page/DragClient.h >+++ b/Source/WebCore/page/DragClient.h >@@ -37,7 +37,7 @@ class DataTransfer; > class Element; > class Frame; > class Image; >-struct PromisedBlobInfo; >+struct PromisedAttachmentInfo; > > class DragClient { > public: >diff --git a/Source/WebCore/page/DragController.cpp b/Source/WebCore/page/DragController.cpp >index 9f9bc324245ff904890d5d6f22377773757b7b91..d50e118b1de9231df791515c8d8ffad4b10e3b1e 100644 >--- a/Source/WebCore/page/DragController.cpp >+++ b/Source/WebCore/page/DragController.cpp >@@ -69,7 +69,7 @@ > #include "PluginDocument.h" > #include "PluginViewBase.h" > #include "Position.h" >-#include "PromisedBlobInfo.h" >+#include "PromisedAttachmentInfo.h" > #include "RenderAttachment.h" > #include "RenderFileUploadControl.h" > #include "RenderImage.h" >@@ -1136,11 +1136,11 @@ bool DragController::startDrag(Frame& src, const DragState& state, DragOperation > auto previousSelection = src.selection().selection(); > selectElement(element); > >- PromisedBlobInfo promisedBlob; >+ PromisedAttachmentInfo promisedAttachment; > if (hasData == HasNonDefaultPasteboardData::No) { >- promisedBlob = promisedBlobInfo(src, attachment); >+ promisedAttachment = promisedAttachmentInfo(src, attachment); > auto& editor = src.editor(); >- if (!promisedBlob && editor.client()) { >+ if (!promisedAttachment && editor.client()) { > #if PLATFORM(COCOA) > // Otherwise, if no file URL is specified, call out to the injected bundle to populate the pasteboard with data. > editor.willWriteSelectionToPasteboard(src.selection().toNormalizedRange().get()); >@@ -1164,7 +1164,7 @@ bool DragController::startDrag(Frame& src, const DragState& state, DragOperation > dragLoc = dragLocForSelectionDrag(src); > m_dragOffset = IntPoint(dragOrigin.x() - dragLoc.x(), dragOrigin.y() - dragLoc.y()); > } >- doSystemDrag(WTFMove(dragImage), dragLoc, dragOrigin, src, state, WTFMove(promisedBlob)); >+ doSystemDrag(WTFMove(dragImage), dragLoc, dragOrigin, src, state, WTFMove(promisedAttachment)); > if (!element.isContentRichlyEditable()) > src.selection().setSelection(previousSelection); > src.editor().setIgnoreSelectionChanges(false); >@@ -1270,7 +1270,7 @@ void DragController::beginDrag(DragItem dragItem, Frame& frame, const IntPoint& > cleanupAfterSystemDrag(); > } > >-void DragController::doSystemDrag(DragImage image, const IntPoint& dragLoc, const IntPoint& eventPos, Frame& frame, const DragState& state, PromisedBlobInfo&& promisedBlob) >+void DragController::doSystemDrag(DragImage image, const IntPoint& dragLoc, const IntPoint& eventPos, Frame& frame, const DragState& state, PromisedAttachmentInfo&& promisedAttachmentInfo) > { > m_didInitiateDrag = true; > m_dragInitiator = frame.document(); >@@ -1281,7 +1281,7 @@ void DragController::doSystemDrag(DragImage image, const IntPoint& dragLoc, cons > DragItem item; > item.image = WTFMove(image); > item.sourceAction = state.type; >- item.promisedBlob = WTFMove(promisedBlob); >+ item.promisedAttachmentInfo = WTFMove(promisedAttachmentInfo); > > auto eventPositionInRootViewCoordinates = frame.view()->contentsToRootView(eventPos); > auto dragLocationInRootViewCoordinates = frame.view()->contentsToRootView(dragLoc); >@@ -1367,11 +1367,8 @@ String DragController::platformContentTypeForBlobType(const String& type) const > > #if ENABLE(ATTACHMENT_ELEMENT) > >-PromisedBlobInfo DragController::promisedBlobInfo(Frame& frame, HTMLAttachmentElement& attachment) >+PromisedAttachmentInfo DragController::promisedAttachmentInfo(Frame& frame, HTMLAttachmentElement& attachment) > { >- if (!attachment.file()) >- return { }; >- > Vector<String> additionalTypes; > Vector<RefPtr<SharedBuffer>> additionalData; > #if PLATFORM(COCOA) >@@ -1379,8 +1376,10 @@ PromisedBlobInfo DragController::promisedBlobInfo(Frame& frame, HTMLAttachmentEl > frame.editor().getPasteboardTypesAndDataForAttachment(attachment, additionalTypes, additionalData); > #endif > >- auto& file = *attachment.file(); >- return { file.url(), platformContentTypeForBlobType(file.type()), file.name(), WTFMove(additionalTypes), WTFMove(additionalData) }; >+ if (auto* file = attachment.file()) >+ return { file->url(), platformContentTypeForBlobType(file->type()), file->name(), attachment.uniqueIdentifier(), WTFMove(additionalTypes), WTFMove(additionalData) }; >+ >+ return { { }, platformContentTypeForBlobType(attachment.attachmentType()), attachment.attachmentTitle(), attachment.uniqueIdentifier(), WTFMove(additionalTypes), WTFMove(additionalData) }; > } > > #endif // ENABLE(ATTACHMENT_ELEMENT) >diff --git a/Source/WebCore/page/DragController.h b/Source/WebCore/page/DragController.h >index 83e575da72350add867003cfd9ed596d88d923ff..22a69583aadb66e9bdf27103a35a2d8470d8ba53 100644 >--- a/Source/WebCore/page/DragController.h >+++ b/Source/WebCore/page/DragController.h >@@ -48,7 +48,7 @@ class PlatformMouseEvent; > > struct DragItem; > struct DragState; >-struct PromisedBlobInfo; >+struct PromisedAttachmentInfo; > > class DragController { > WTF_MAKE_NONCOPYABLE(DragController); WTF_MAKE_FAST_ALLOCATED; >@@ -116,7 +116,7 @@ struct PromisedBlobInfo; > bool shouldUseCachedImageForDragImage(const Image&) const; > > void doImageDrag(Element&, const IntPoint&, const IntRect&, Frame&, IntPoint&, const DragState&); >- void doSystemDrag(DragImage, const IntPoint&, const IntPoint&, Frame&, const DragState&, PromisedBlobInfo&&); >+ void doSystemDrag(DragImage, const IntPoint&, const IntPoint&, Frame&, const DragState&, PromisedAttachmentInfo&&); > > void beginDrag(DragItem, Frame&, const IntPoint& mouseDownPoint, const IntPoint& mouseDraggedPoint, DataTransfer&, DragSourceAction); > >@@ -135,7 +135,7 @@ struct PromisedBlobInfo; > void declareAndWriteDragImage(DataTransfer&, Element&, const URL&, const String& label); > > #if ENABLE(ATTACHMENT_ELEMENT) >- PromisedBlobInfo promisedBlobInfo(Frame&, HTMLAttachmentElement&); >+ PromisedAttachmentInfo promisedAttachmentInfo(Frame&, HTMLAttachmentElement&); > #endif > Page& m_page; > DragClient& m_client; >diff --git a/Source/WebCore/page/EditorClient.h b/Source/WebCore/page/EditorClient.h >index 36ad7be869c17286cc435791cd85218550835944..8ffd7360c6aa7eb2b2c7ca90c1f4b1396bfd312b 100644 >--- a/Source/WebCore/page/EditorClient.h >+++ b/Source/WebCore/page/EditorClient.h >@@ -73,8 +73,12 @@ public: > virtual bool shouldMoveRangeAfterDelete(Range*, Range*) = 0; > > #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 cloneAttachmentData(const String& /* fromIdentifier */, const String& /* toIdentifier */) { } > virtual void didInsertAttachment(const String& /* identifier */, const String& /* source */) { } > virtual void didRemoveAttachment(const String&) { } >+ virtual bool supportsClientSideAttachmentData() const { return false; } > #endif > > virtual void didBeginEditing() = 0; >diff --git a/Source/WebCore/platform/DragItem.h b/Source/WebCore/platform/DragItem.h >index 3eae743754289ad1573d5309c9fb144bda8f71b9..5992bea18bb360d283a2e7c919fcf8c505e3bc91 100644 >--- a/Source/WebCore/platform/DragItem.h >+++ b/Source/WebCore/platform/DragItem.h >@@ -31,7 +31,7 @@ > #include "IntPoint.h" > #include "IntRect.h" > #include "PasteboardWriterData.h" >-#include "PromisedBlobInfo.h" >+#include "PromisedAttachmentInfo.h" > > namespace WebCore { > >@@ -50,7 +50,7 @@ struct DragItem final { > IntRect dragPreviewFrameInRootViewCoordinates; > > PasteboardWriterData data; >- PromisedBlobInfo promisedBlob; >+ PromisedAttachmentInfo promisedAttachmentInfo; > > template<class Encoder> void encode(Encoder&) const; > template<class Decoder> static bool decode(Decoder&, DragItem&); >@@ -71,7 +71,7 @@ void DragItem::encode(Encoder& encoder) const > encoder << hasVisiblePath; > if (hasVisiblePath) > encoder << image.visiblePath().value(); >- encoder << promisedBlob; >+ encoder << promisedAttachmentInfo; > } > > template<class Decoder> >@@ -113,7 +113,7 @@ bool DragItem::decode(Decoder& decoder, DragItem& result) > return false; > result.image.setVisiblePath(*visiblePath); > } >- if (!decoder.decode(result.promisedBlob)) >+ if (!decoder.decode(result.promisedAttachmentInfo)) > return false; > return true; > } >diff --git a/Source/WebCore/platform/PromisedAttachmentInfo.h b/Source/WebCore/platform/PromisedAttachmentInfo.h >new file mode 100644 >index 0000000000000000000000000000000000000000..d38a31dbae7b52e100c9a34a09ed604f8163e9fc >--- /dev/null >+++ b/Source/WebCore/platform/PromisedAttachmentInfo.h >@@ -0,0 +1,63 @@ >+/* >+ * 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 >+ >+#include <wtf/Forward.h> >+#include <wtf/RefPtr.h> >+ >+namespace WebCore { >+ >+class SharedBuffer; >+class URL; >+ >+struct PromisedAttachmentInfo { >+ URL blobURL; >+ String contentType; >+ String filename; >+ >+#if ENABLE(ATTACHMENT_ELEMENT) >+ String attachmentIdentifier; >+#endif >+ >+ Vector<String> additionalTypes; >+ Vector<RefPtr<SharedBuffer>> additionalData; >+ >+ operator bool() const >+ { >+ if (contentType.isEmpty()) >+ return false; >+ >+#if ENABLE(ATTACHMENT_ELEMENT) >+ if (!attachmentIdentifier.isEmpty()) >+ return true; >+#endif >+ >+ return !blobURL.isEmpty(); >+ } >+}; >+ >+} // namespace WebCore >+ >diff --git a/Source/WebCore/platform/PromisedBlobInfo.h b/Source/WebCore/platform/PromisedBlobInfo.h >deleted file mode 100644 >index 2f4ba7092e84d7773f8e50c2e0684fa630672c54..0000000000000000000000000000000000000000 >--- a/Source/WebCore/platform/PromisedBlobInfo.h >+++ /dev/null >@@ -1,46 +0,0 @@ >-/* >- * 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 >- >-#include "SharedBuffer.h" >- >-namespace WebCore { >- >-class URL; >- >-struct PromisedBlobInfo { >- URL blobURL; >- String contentType; >- String filename; >- >- Vector<String> additionalTypes; >- Vector<RefPtr<SharedBuffer>> additionalData; >- >- operator bool() const { return !blobURL.isEmpty(); } >-}; >- >-} // namespace WebCore >- >diff --git a/Source/WebKit/Scripts/webkit/messages.py b/Source/WebKit/Scripts/webkit/messages.py >index a782baac9d45bb3c9d0b8992622faa6252aa184d..c2a3e4e29361f4097c1591752415ec105d5e9ff6 100644 >--- a/Source/WebKit/Scripts/webkit/messages.py >+++ b/Source/WebKit/Scripts/webkit/messages.py >@@ -378,7 +378,6 @@ def headers_for_type(type): > 'String': ['<wtf/text/WTFString.h>'], > 'PAL::SessionID': ['<pal/SessionID.h>'], > 'WebCore::AttachmentDisplayOptions': ['<WebCore/AttachmentTypes.h>'], >- 'WebCore::AttachmentInfo': ['<WebCore/AttachmentTypes.h>'], > 'WebCore::AutoplayEventFlags': ['<WebCore/AutoplayEvent.h>'], > 'WebCore::ExceptionDetails': ['<WebCore/JSDOMExceptionHandling.h>'], > 'WebCore::FileChooserSettings': ['<WebCore/FileChooser.h>'], >diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp >index baa2fcf03e9ab2c9cff6a8adb9ff330bb03d896e..5f83e9f09c08f2fd4ab2e6d51af807a01824405c 100644 >--- a/Source/WebKit/Shared/WebCoreArgumentCoders.cpp >+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.cpp >@@ -57,7 +57,7 @@ > #include <WebCore/Pasteboard.h> > #include <WebCore/Path.h> > #include <WebCore/PluginData.h> >-#include <WebCore/PromisedBlobInfo.h> >+#include <WebCore/PromisedAttachmentInfo.h> > #include <WebCore/ProtectionSpace.h> > #include <WebCore/RectEdges.h> > #include <WebCore/Region.h> >@@ -2863,15 +2863,18 @@ std::optional<MediaSelectionOption> ArgumentCoder<MediaSelectionOption>::decode( > return {{ WTFMove(*displayName), WTFMove(*type) }}; > } > >-void ArgumentCoder<PromisedBlobInfo>::encode(Encoder& encoder, const PromisedBlobInfo& info) >+void ArgumentCoder<PromisedAttachmentInfo>::encode(Encoder& encoder, const PromisedAttachmentInfo& info) > { > encoder << info.blobURL; > encoder << info.contentType; > encoder << info.filename; >+#if ENABLE(ATTACHMENT_ELEMENT) >+ encoder << info.attachmentIdentifier; >+#endif > encodeTypesAndData(encoder, info.additionalTypes, info.additionalData); > } > >-bool ArgumentCoder<PromisedBlobInfo>::decode(Decoder& decoder, PromisedBlobInfo& info) >+bool ArgumentCoder<PromisedAttachmentInfo>::decode(Decoder& decoder, PromisedAttachmentInfo& info) > { > if (!decoder.decode(info.blobURL)) > return false; >@@ -2882,51 +2885,17 @@ bool ArgumentCoder<PromisedBlobInfo>::decode(Decoder& decoder, PromisedBlobInfo& > if (!decoder.decode(info.filename)) > return false; > >- if (!decodeTypesAndData(decoder, info.additionalTypes, info.additionalData)) >- return false; >- >- return true; >-} >- > #if ENABLE(ATTACHMENT_ELEMENT) >- >-void ArgumentCoder<AttachmentInfo>::encode(Encoder& encoder, const AttachmentInfo& info) >-{ >- bool dataIsNull = !info.data; >- encoder << info.contentType << info.name << info.filePath << dataIsNull; >- if (!dataIsNull) { >- SharedBufferDataReference dataReference { info.data.get() }; >- encoder << static_cast<DataReference&>(dataReference); >- } >-} >- >-bool ArgumentCoder<AttachmentInfo>::decode(Decoder& decoder, AttachmentInfo& info) >-{ >- if (!decoder.decode(info.contentType)) >- return false; >- >- if (!decoder.decode(info.name)) >- return false; >- >- if (!decoder.decode(info.filePath)) >+ if (!decoder.decode(info.attachmentIdentifier)) > return false; >+#endif > >- bool dataIsNull = true; >- if (!decoder.decode(dataIsNull)) >+ if (!decodeTypesAndData(decoder, info.additionalTypes, info.additionalData)) > return false; > >- if (!dataIsNull) { >- DataReference dataReference; >- if (!decoder.decode(dataReference)) >- return false; >- info.data = SharedBuffer::create(dataReference.data(), dataReference.size()); >- } >- > return true; > } > >-#endif // ENABLE(ATTACHMENT_ELEMENT) >- > void ArgumentCoder<Vector<RefPtr<SecurityOrigin>>>::encode(Encoder& encoder, const Vector<RefPtr<SecurityOrigin>>& origins) > { > encoder << static_cast<uint64_t>(origins.size()); >diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.h b/Source/WebKit/Shared/WebCoreArgumentCoders.h >index f2afcad596033940f1b49ad0623a089a8c539a75..8ca760fcffdcd4d8f62f6233929303385aafc35f 100644 >--- a/Source/WebKit/Shared/WebCoreArgumentCoders.h >+++ b/Source/WebKit/Shared/WebCoreArgumentCoders.h >@@ -95,7 +95,6 @@ class TransformationMatrix; > class UserStyleSheet; > class URL; > >-struct AttachmentInfo; > struct CacheQueryOptions; > struct CompositionUnderline; > struct DictationAlternative; >@@ -110,7 +109,7 @@ struct PasteboardImage; > struct PasteboardCustomData; > struct PasteboardURL; > struct PluginInfo; >-struct PromisedBlobInfo; >+struct PromisedAttachmentInfo; > struct RecentSearch; > struct ResourceLoadStatistics; > struct ScrollableAreaParameters; >@@ -699,20 +698,11 @@ template<> struct ArgumentCoder<WebCore::MediaSelectionOption> { > static std::optional<WebCore::MediaSelectionOption> decode(Decoder&); > }; > >-template<> struct ArgumentCoder<WebCore::PromisedBlobInfo> { >- static void encode(Encoder&, const WebCore::PromisedBlobInfo&); >- static bool decode(Decoder&, WebCore::PromisedBlobInfo&); >+template<> struct ArgumentCoder<WebCore::PromisedAttachmentInfo> { >+ static void encode(Encoder&, const WebCore::PromisedAttachmentInfo&); >+ static bool decode(Decoder&, WebCore::PromisedAttachmentInfo&); > }; > >-#if ENABLE(ATTACHMENT_ELEMENT) >- >-template<> struct ArgumentCoder<WebCore::AttachmentInfo> { >- static void encode(Encoder&, const WebCore::AttachmentInfo&); >- static bool decode(Decoder&, WebCore::AttachmentInfo&); >-}; >- >-#endif >- > template<> struct ArgumentCoder<Vector<RefPtr<WebCore::SecurityOrigin>>> { > static void encode(Encoder&, const Vector<RefPtr<WebCore::SecurityOrigin>>&); > static bool decode(Decoder&, Vector<RefPtr<WebCore::SecurityOrigin>>&); >diff --git a/Source/WebKit/UIProcess/API/APIAttachment.cpp b/Source/WebKit/UIProcess/API/APIAttachment.cpp >index 7e009d6b2e559cd85b98466812119a4c8b9696e2..afa8e368b4c77fae1cac9333ca2e62045900cd33 100644 >--- a/Source/WebKit/UIProcess/API/APIAttachment.cpp >+++ b/Source/WebKit/UIProcess/API/APIAttachment.cpp >@@ -48,14 +48,6 @@ Attachment::~Attachment() > { > } > >-void Attachment::requestInfo(Function<void(const WebCore::AttachmentInfo&, WebKit::CallbackBase::Error)>&& callback) >-{ >- if (m_webPage) >- m_webPage->requestAttachmentInfo(m_identifier, WTFMove(callback)); >- else >- callback({ }, WebKit::CallbackBase::Error::OwnerWasInvalidated); >-} >- > void Attachment::setDisplayOptions(WebCore::AttachmentDisplayOptions options, Function<void(WebKit::CallbackBase::Error)>&& callback) > { > if (m_webPage) >@@ -64,12 +56,15 @@ void Attachment::setDisplayOptions(WebCore::AttachmentDisplayOptions options, Fu > callback(WebKit::CallbackBase::Error::OwnerWasInvalidated); > } > >-void Attachment::setDataAndContentType(WebCore::SharedBuffer& data, const WTF::String& newContentType, const WTF::String& newFilename, Function<void(WebKit::CallbackBase::Error)>&& callback) >+void Attachment::updateAttributes(uint64_t fileSize, const WTF::String& newContentType, const WTF::String& newFilename, Function<void(WebKit::CallbackBase::Error)>&& callback) > { >+ setContentType(newContentType); >+ setFilePath({ }); >+ > auto optionalNewContentType = newContentType.isNull() ? std::nullopt : std::optional<WTF::String> { newContentType }; > auto optionalNewFilename = newFilename.isNull() ? std::nullopt : std::optional<WTF::String> { newFilename }; > if (m_webPage) >- m_webPage->setAttachmentDataAndContentType(m_identifier, data, WTFMove(optionalNewContentType), WTFMove(optionalNewFilename), WTFMove(callback)); >+ m_webPage->updateAttachmentAttributes(m_identifier, fileSize, WTFMove(optionalNewContentType), WTFMove(optionalNewFilename), WTFMove(callback)); > else > callback(WebKit::CallbackBase::Error::OwnerWasInvalidated); > } >diff --git a/Source/WebKit/UIProcess/API/APIAttachment.h b/Source/WebKit/UIProcess/API/APIAttachment.h >index bf7a2274296221ffadbe07892e76eefdd75cb898..e7ea9cdf905517a2f8193af627cac4cb9e85f9d4 100644 >--- a/Source/WebKit/UIProcess/API/APIAttachment.h >+++ b/Source/WebKit/UIProcess/API/APIAttachment.h >@@ -32,10 +32,11 @@ > #include <wtf/WeakPtr.h> > #include <wtf/text/WTFString.h> > >+OBJC_CLASS NSFileWrapper; >+ > namespace WebCore { > class SharedBuffer; > struct AttachmentDisplayOptions; >-struct AttachmentInfo; > } > > namespace WebKit { >@@ -50,14 +51,29 @@ public: > virtual ~Attachment(); > > const WTF::String& identifier() const { return m_identifier; } >- void requestInfo(Function<void(const WebCore::AttachmentInfo&, WebKit::CallbackBase::Error)>&&); > void setDisplayOptions(WebCore::AttachmentDisplayOptions, Function<void(WebKit::CallbackBase::Error)>&&); >- void setDataAndContentType(WebCore::SharedBuffer&, const WTF::String& newContentType, const WTF::String& newFilename, Function<void(WebKit::CallbackBase::Error)>&&); >+ void updateAttributes(uint64_t fileSize, const WTF::String& newContentType, const WTF::String& newFilename, Function<void(WebKit::CallbackBase::Error)>&&); >+ >+#if PLATFORM(COCOA) >+ NSFileWrapper *fileWrapper() const { return m_fileWrapper.get(); } >+ void setFileWrapper(NSFileWrapper *fileWrapper) { m_fileWrapper = fileWrapper; } >+#endif >+ >+ const WTF::String& filePath() const { return m_filePath; } >+ void setFilePath(const WTF::String& filePath) { m_filePath = filePath; } >+ >+ const WTF::String& contentType() const { return m_contentType; } >+ void setContentType(const WTF::String& contentType) { m_contentType = contentType; } > > private: > explicit Attachment(const WTF::String& identifier, WebKit::WebPageProxy&); > >+#if PLATFORM(COCOA) >+ RetainPtr<NSFileWrapper> m_fileWrapper; >+#endif > WTF::String m_identifier; >+ WTF::String m_filePath; >+ WTF::String m_contentType; > WeakPtr<WebKit::WebPageProxy> m_webPage; > }; > >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h >index f68cad1bcdc3bcd5af819e59432401d7e7df6cea..4c26439c4f71eb80c121b90f3f4a35f574807017 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h >@@ -114,7 +114,6 @@ struct UIEdgeInsets; > - (void)_webView:(WKWebView *)webView editorStateDidChange:(NSDictionary *)editorState WK_API_AVAILABLE(macosx(10.13.4), ios(11.3)); > > - (void)_webView:(WKWebView *)webView didRemoveAttachment:(_WKAttachment *)attachment WK_API_AVAILABLE(macosx(10.13.4), ios(11.3)); >-- (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment WK_API_AVAILABLE(macosx(10.13.4), ios(11.3)); > - (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment withSource:(NSString *)source WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > > - (void)_webView:(WKWebView *)webView didResignInputElementStrongPasswordAppearanceWithUserInfo:(id <NSSecureCoding>)userInfo WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm >index f02301813e02af3362bfc5b3c47e39dafd1c4f5e..26b3a895cc48ec9dfd762edeaefc8cb6039e7846 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm >@@ -1212,17 +1212,25 @@ static NSDictionary *dictionaryRepresentationForEditorState(const WebKit::Editor > - (void)_didInsertAttachment:(NSString *)identifier withSource:(NSString *)source > { > id <WKUIDelegatePrivate> uiDelegate = (id <WKUIDelegatePrivate>)self.UIDelegate; >- if ([uiDelegate respondsToSelector:@selector(_webView:didInsertAttachment:withSource:)]) >- [uiDelegate _webView:self didInsertAttachment:wrapper(API::Attachment::create(identifier, *_page)) withSource:source]; >- else if ([uiDelegate respondsToSelector:@selector(_webView:didInsertAttachment:)]) >- [uiDelegate _webView:self didInsertAttachment:wrapper(API::Attachment::create(identifier, *_page))]; >+ if (![uiDelegate respondsToSelector:@selector(_webView:didInsertAttachment:withSource:)]) >+ return; >+ >+ if (auto attachment = _page->attachmentForIdentifier(identifier)) >+ [uiDelegate _webView:self didInsertAttachment:wrapper(*attachment) withSource:source]; >+ else >+ ASSERT_NOT_REACHED(); > } > > - (void)_didRemoveAttachment:(NSString *)identifier > { > id <WKUIDelegatePrivate> uiDelegate = (id <WKUIDelegatePrivate>)self.UIDelegate; >- if ([uiDelegate respondsToSelector:@selector(_webView:didRemoveAttachment:)]) >- [uiDelegate _webView:self didRemoveAttachment:wrapper(API::Attachment::create(identifier, *_page))]; >+ if (![uiDelegate respondsToSelector:@selector(_webView:didRemoveAttachment:)]) >+ return; >+ >+ if (auto attachment = _page->attachmentForIdentifier(identifier)) >+ [uiDelegate _webView:self didRemoveAttachment:wrapper(*attachment)]; >+ else >+ ASSERT_NOT_REACHED(); > } > > #endif // ENABLE(ATTACHMENT_ELEMENT) >@@ -4398,18 +4406,31 @@ WEBCORE_COMMAND(yankAndSelect) > } > > - (_WKAttachment *)_insertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler >+{ >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:data]); >+ if (filename) >+ [fileWrapper setPreferredFilename:filename]; >+ return [self _insertAttachmentWithFileWrapper:fileWrapper.get() contentType:contentType options:options completion:completionHandler]; >+} >+ >+- (_WKAttachment *)_insertAttachmentWithFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler > { > #if ENABLE(ATTACHMENT_ELEMENT) > auto identifier = createCanonicalUUIDString(); >- > auto coreOptions = options ? options.coreDisplayOptions : WebCore::AttachmentDisplayOptions { }; >- auto buffer = WebCore::SharedBuffer::create(data); >- _page->insertAttachment(identifier, coreOptions, filename, contentType.length ? std::optional<String> { contentType } : std::nullopt, buffer.get(), [capturedHandler = makeBlockPtr(completionHandler), capturedBuffer = buffer.copyRef()] (WebKit::CallbackBase::Error error) { >+ auto attachment = API::Attachment::create(identifier, *_page); >+ attachment->setFileWrapper(fileWrapper); >+ >+ auto fileSize = [[[fileWrapper fileAttributes] objectForKey:NSFileSize] unsignedLongLongValue]; >+ if (!fileSize && fileWrapper.regularFile) >+ fileSize = fileWrapper.regularFileContents.length; >+ >+ _page->insertAttachment(attachment.copyRef(), coreOptions, fileSize, [fileWrapper preferredFilename], contentType.length ? std::optional<String> { contentType } : std::nullopt, [capturedHandler = makeBlockPtr(completionHandler)] (WebKit::CallbackBase::Error error) { > if (capturedHandler) > capturedHandler(error == WebKit::CallbackBase::Error::None); > }); > >- return wrapper(API::Attachment::create(identifier, *_page)); >+ return wrapper(attachment); > #else > return nil; > #endif >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h b/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h >index 581a4a67d18686b61128f867fb4981a7c6f7fc29..d0cf2b8c0743cd80a611b970b0bc989e20599645 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h >@@ -180,7 +180,8 @@ typedef NS_OPTIONS(NSUInteger, _WKRectEdge) { > > @property (nonatomic, setter=_setBackgroundExtendsBeyondPage:) BOOL _backgroundExtendsBeyondPage WK_API_AVAILABLE(macosx(10.13.4), ios(8.0)); > >-- (_WKAttachment *)_insertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler WK_API_AVAILABLE(macosx(10.13.4), ios(11.3)); >+- (_WKAttachment *)_insertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("-_insertAttachmentWithFileWrapper:contentType:options:completion:", macosx(10.13.4, WK_MAC_TBA), ios(11.3, WK_IOS_TBA)); >+- (_WKAttachment *)_insertAttachmentWithFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > > #if TARGET_OS_IPHONE > // DERECATED: The setters of the three following function are deprecated, please use overrideLayoutParameters. >diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h b/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h >index 0829939fbbca2cb27e6069860c466ffb8d304cfb..c737c2e535faf690d1e23bd7503053ca329998e7 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h >+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.h >@@ -44,19 +44,26 @@ WK_CLASS_AVAILABLE(macosx(10.13.4), ios(11.3)) > > WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)) > @interface _WKAttachmentInfo : NSObject >-@property (nonatomic, readonly) NSString *contentType; >-@property (nonatomic, readonly) NSString *name; >-@property (nonatomic, readonly) NSString *filePath; >+@property (nonatomic, readonly, nullable) NSString *contentType; >+@property (nonatomic, readonly, nullable) NSString *name; >+@property (nonatomic, readonly, nullable) NSString *filePath; > @property (nonatomic, readonly, nullable) NSData *data; >+@property (nonatomic, readonly) NSFileWrapper *fileWrapper; > @end > > WK_CLASS_AVAILABLE(macosx(10.13.4), ios(11.3)) > @interface _WKAttachment : NSObject >-- (void)requestInfo:(void(^)(_WKAttachmentInfo * _Nullable, NSError * _Nullable))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); >-- (void)requestData:(void(^)(NSData * _Nullable, NSError * _Nullable))completionHandler; >+ > - (void)setDisplayOptions:(_WKAttachmentDisplayOptions *)options completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler; >-- (void)setData:(NSData *)data newContentType:(nullable NSString *)newContentType newFilename:(nullable NSString *)newFilename completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler; >+- (void)setFileWrapper:(NSFileWrapper *)fileWrapper contentType:(nullable NSString *)contentType completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); >+ >+@property (nonatomic, readonly) _WKAttachmentInfo *info WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA)); > @property (nonatomic, readonly) NSString *uniqueIdentifier; >+ >+// Deprecated SPI. >+- (void)requestInfo:(void(^)(_WKAttachmentInfo * _Nullable, NSError * _Nullable))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("-info", macosx(WK_MAC_TBA, WK_MAC_TBA), ios(WK_IOS_TBA, WK_IOS_TBA)); >+- (void)setData:(NSData *)data newContentType:(nullable NSString *)newContentType newFilename:(nullable NSString *)newFilename completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("Please use -setFileWrapper:contentType:completion: instead.", macosx(10.13.4, WK_MAC_TBA), ios(11.3, WK_IOS_TBA)); >+ > @end > > NS_ASSUME_NONNULL_END >diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm >index 5f00c8cee2a3f5cd615a886ca57a1afb272a741d..e5c9e7b4ef923c72d3f00fdafe3a57c90c8c7bf0 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm >+++ b/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm >@@ -35,6 +35,10 @@ > #import <WebCore/SharedBuffer.h> > #import <wtf/BlockPtr.h> > >+#if PLATFORM(IOS) >+#import <MobileCoreServices/MobileCoreServices.h> >+#endif >+ > using namespace WebKit; > > @implementation _WKAttachmentDisplayOptions : NSObject >@@ -47,41 +51,36 @@ using namespace WebKit; > @end > > @implementation _WKAttachmentInfo { >- RetainPtr<NSData> _data; >- RetainPtr<NSString> _name; >- RetainPtr<NSString> _filePath; >+ RetainPtr<NSFileWrapper> _fileWrapper; > RetainPtr<NSString> _contentType; >- RetainPtr<NSError> _fileLoadingError; >+ RetainPtr<NSString> _filePath; > } > >-- (instancetype)initWithInfo:(const WebCore::AttachmentInfo&)info >+- (instancetype)initWithFileWrapper:(NSFileWrapper *)fileWrapper filePath:(NSString *)filePath contentType:(NSString *)contentType > { > if (!(self = [super init])) > return nil; > >- _data = info.data ? info.data->createNSData() : nil; >- _contentType = adoptNS([(NSString *)info.contentType ?: @"" copy]); >- _name = adoptNS([(NSString *)info.name ?: @"" copy]); >- _filePath = adoptNS([(NSString *)info.filePath ?: @"" copy]); >- _fileLoadingError = nil; >- >- if (!_data && [_filePath length]) { >- NSError *error = nil; >- _data = [NSData dataWithContentsOfFile:_filePath.get() options:NSDataReadingMappedIfSafe error:&error]; >- _fileLoadingError = error; >- } >- >+ _fileWrapper = fileWrapper; >+ _filePath = filePath; >+ _contentType = contentType; > return self; > } > > - (NSData *)data > { >- return _data.get(); >+ if (![_fileWrapper isRegularFile]) >+ return nil; >+ >+ return [_fileWrapper regularFileContents]; > } > > - (NSString *)name > { >- return _name.get(); >+ if ([_fileWrapper filename].length) >+ return [_fileWrapper filename]; >+ >+ return [_fileWrapper preferredFilename]; > } > > - (NSString *)filePath >@@ -89,14 +88,47 @@ using namespace WebKit; > return _filePath.get(); > } > >+static BOOL isDeclaredOrDynamicTypeIdentifier(NSString *type) >+{ >+ return UTTypeIsDeclared((CFStringRef)type) || UTTypeIsDynamic((CFStringRef)type); >+} >+ >+- (NSString *)_typeIdentifierFromPathExtension >+{ >+ NSString *extension = self.name.pathExtension; >+ auto typeIdentifier = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, nil)); >+ return (NSString *)typeIdentifier.autorelease(); >+} >+ > - (NSString *)contentType > { >- return _contentType.get(); >+ // A "content type" can refer to either a UTI or a MIME type. We prefer MIME type here to preserve existing behavior. >+ return self.mimeType ?: self.utiType; >+} >+ >+- (NSString *)mimeType >+{ >+ NSString *contentType = [_contentType length] ? _contentType.get() : [self _typeIdentifierFromPathExtension]; >+ if (!isDeclaredOrDynamicTypeIdentifier(contentType)) >+ return contentType; >+ >+ auto mimeType = adoptCF(UTTypeCopyPreferredTagWithClass((CFStringRef)contentType, kUTTagClassMIMEType)); >+ return (NSString *)mimeType.autorelease(); >+} >+ >+- (NSString *)utiType >+{ >+ NSString *contentType = [_contentType length] ? _contentType.get() : [self _typeIdentifierFromPathExtension]; >+ if (isDeclaredOrDynamicTypeIdentifier(contentType)) >+ return contentType; >+ >+ auto utiType = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (CFStringRef)contentType, nil)); >+ return (NSString *)utiType.autorelease(); > } > >-- (NSError *)fileLoadingError >+- (NSFileWrapper *)fileWrapper > { >- return _fileLoadingError.get(); >+ return _fileWrapper.get(); > } > > @end >@@ -108,37 +140,14 @@ using namespace WebKit; > return *_attachment; > } > >-- (BOOL)isEqual:(id)object >+- (_WKAttachmentInfo *)info > { >- return [object isKindOfClass:[_WKAttachment class]] && [self.uniqueIdentifier isEqual:[(_WKAttachment *)object uniqueIdentifier]]; >+ return [[[_WKAttachmentInfo alloc] initWithFileWrapper:_attachment->fileWrapper() filePath:_attachment->filePath() contentType:_attachment->contentType()] autorelease]; > } > > - (void)requestInfo:(void(^)(_WKAttachmentInfo *, NSError *))completionHandler > { >- _attachment->requestInfo([capturedBlock = makeBlockPtr(completionHandler)] (const WebCore::AttachmentInfo& info, CallbackBase::Error error) { >- if (!capturedBlock) >- return; >- >- if (error != CallbackBase::Error::None) { >- capturedBlock(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorWebViewInvalidated userInfo:nil]); >- return; >- } >- >- auto attachmentInfo = adoptNS([[_WKAttachmentInfo alloc] initWithInfo:info]); >- if (NSError *fileLoadingError = [attachmentInfo fileLoadingError]) { >- capturedBlock(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorUnknown userInfo:@{ NSUnderlyingErrorKey : fileLoadingError }]); >- return; >- } >- >- capturedBlock(attachmentInfo.get(), nil); >- }); >-} >- >-- (void)requestData:(void(^)(NSData *, NSError *))completionHandler >-{ >- [self requestInfo:[protectedBlock = makeBlockPtr(completionHandler)] (_WKAttachmentInfo *info, NSError *error) { >- protectedBlock(info.data, error); >- }]; >+ completionHandler(self.info, nil); > } > > - (void)setDisplayOptions:(_WKAttachmentDisplayOptions *)options completion:(void(^)(NSError *))completionHandler >@@ -155,10 +164,14 @@ using namespace WebKit; > }); > } > >-- (void)setData:(NSData *)data newContentType:(NSString *)newContentType newFilename:(NSString *)newFilename completion:(void(^)(NSError *))completionHandler >+- (void)setFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType completion:(void (^)(NSError *))completionHandler > { >- auto buffer = WebCore::SharedBuffer::create(data); >- _attachment->setDataAndContentType(buffer.get(), newContentType, newFilename, [capturedBlock = makeBlockPtr(completionHandler), capturedBuffer = buffer.copyRef()] (CallbackBase::Error error) { >+ auto fileSize = [[[fileWrapper fileAttributes] objectForKey:NSFileSize] unsignedLongLongValue]; >+ if (!fileSize && fileWrapper.regularFile) >+ fileSize = fileWrapper.regularFileContents.length; >+ >+ _attachment->setFileWrapper(fileWrapper); >+ _attachment->updateAttributes(fileSize, contentType, [fileWrapper preferredFilename], [capturedBlock = makeBlockPtr(completionHandler)] (auto error) { > if (!capturedBlock) > return; > >@@ -169,19 +182,22 @@ using namespace WebKit; > }); > } > >-- (NSString *)uniqueIdentifier >+- (void)setData:(NSData *)data newContentType:(NSString *)newContentType newFilename:(NSString *)newFilename completion:(void(^)(NSError *))completionHandler > { >- return _attachment->identifier(); >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:data]); >+ if (newFilename) >+ [fileWrapper setPreferredFilename:newFilename]; >+ [self setFileWrapper:fileWrapper.get() contentType:newContentType completion:completionHandler]; > } > >-- (NSUInteger)hash >+- (NSString *)uniqueIdentifier > { >- return [self.uniqueIdentifier hash]; >+ return _attachment->identifier(); > } > > - (NSString *)description > { >- return [NSString stringWithFormat:@"<%@ id='%@'>", [self class], self.uniqueIdentifier]; >+ return [NSString stringWithFormat:@"<%@ %p id='%@'>", [self class], self, self.uniqueIdentifier]; > } > > @end >diff --git a/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm b/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm >index 837ec1a025cae4ca93da0f106610541ffa254e7c..d6e0e4297101b645489f908d80e58b88cb01f63c 100644 >--- a/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm >+++ b/Source/WebKit/UIProcess/Cocoa/PageClientImplCocoa.mm >@@ -52,6 +52,7 @@ void PageClientImplCocoa::didInsertAttachment(const String& identifier, const St > [m_webView _didInsertAttachment:identifier withSource:source]; > #else > UNUSED_PARAM(identifier); >+ UNUSED_PARAM(source); > #endif > } > >diff --git a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm >index 5ba28240c0cd5fddc7f85e52700a9e423daf4099..ecdc6881b584206c1d224dd1d1c352aacfa9d7b5 100644 >--- a/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm >+++ b/Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm >@@ -26,6 +26,7 @@ > #import "config.h" > #import "WebPageProxy.h" > >+#import "APIAttachment.h" > #import "APIUIClient.h" > #import "DataDetectionResult.h" > #import "LoadParameters.h" >@@ -160,4 +161,27 @@ void WebPageProxy::setDragCaretRect(const IntRect& dragCaretRect) > > #endif // ENABLE(DRAG_SUPPORT) > >+#if ENABLE(ATTACHMENT_ELEMENT) >+ >+void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&& attachment, const String& preferredFileName, const IPC::DataReference& dataReference) >+{ >+ auto buffer = SharedBuffer::create(dataReference.data(), dataReference.size()); >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:buffer->createNSData().autorelease()]); >+ [fileWrapper setPreferredFilename:preferredFileName]; >+ attachment->setFileWrapper(fileWrapper.get()); >+} >+ >+void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&& attachment, const String& filePath) >+{ >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initWithURL:[NSURL fileURLWithPath:filePath] options:0 error:nil]); >+ attachment->setFileWrapper(fileWrapper.get()); >+} >+ >+void WebPageProxy::platformCloneAttachment(Ref<API::Attachment>&& fromAttachment, Ref<API::Attachment>&& toAttachment) >+{ >+ toAttachment->setFileWrapper(fromAttachment->fileWrapper()); >+} >+ >+#endif // ENABLE(ATTACHMENT_ELEMENT) >+ > } >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 270423f6eb139a68bf5cb18f8eef5a7c3868a4cb..60d965015a34933dbd43770682b79e87378a1d21 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -5601,22 +5601,6 @@ void WebPageProxy::voidCallback(CallbackID callbackID) > callback->performCallback(); > } > >-#if ENABLE(ATTACHMENT_ELEMENT) >- >-void WebPageProxy::attachmentInfoCallback(const WebCore::AttachmentInfo& info, CallbackID callbackID) >-{ >- auto callback = m_callbacks.take<AttachmentInfoCallback>(callbackID); >- if (!callback) { >- ASSERT_NOT_REACHED(); >- return; >- } >- >- MESSAGE_CHECK_URL(info.filePath); >- callback->performCallbackWithReturnValue(info); >-} >- >-#endif >- > void WebPageProxy::dataCallback(const IPC::DataReference& dataReference, CallbackID callbackID) > { > auto callback = m_callbacks.take<DataCallback>(callbackID); >@@ -6196,6 +6180,12 @@ void WebPageProxy::resetStateAfterProcessExited(ProcessTerminationReason termina > m_touchEventQueue.clear(); > #endif > >+#if ENABLE(ATTACHMENT_ELEMENT) >+ for (auto identifier : m_attachmentIdentifierToAttachmentMap.keys()) >+ m_pageClient.didRemoveAttachment(identifier); >+ m_attachmentIdentifierToAttachmentMap.clear(); >+#endif >+ > if (terminationReason != ProcessTerminationReason::NavigationSwap) { > PageLoadState::Transaction transaction = m_pageLoadState.transaction(); > m_pageLoadState.reset(transaction); >@@ -7741,26 +7731,29 @@ void WebPageProxy::touchBarMenuItemDataRemoved(const TouchBarMenuItemData& touch > > #if ENABLE(ATTACHMENT_ELEMENT) > >-void WebPageProxy::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, std::optional<String> contentType, SharedBuffer& data, Function<void(CallbackBase::Error)>&& callback) >+RefPtr<API::Attachment> WebPageProxy::attachmentForIdentifier(const String& identifier) const > { >- if (!isValid()) { >- callback(CallbackBase::Error::OwnerWasInvalidated); >- return; >- } >+ if (identifier.isEmpty()) >+ return nullptr; > >- auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken()); >- m_process->send(Messages::WebPage::InsertAttachment(identifier, options, filename, contentType, IPC::SharedBufferDataReference { &data }, callbackID), m_pageID); >+ return m_attachmentIdentifierToAttachmentMap.get(identifier); > } > >-void WebPageProxy::requestAttachmentInfo(const String& identifier, Function<void(const AttachmentInfo&, CallbackBase::Error)>&& callback) >+void WebPageProxy::insertAttachment(Ref<API::Attachment>&& attachment, const AttachmentDisplayOptions& options, uint64_t fileSize, const String& filename, std::optional<String> contentType, Function<void(CallbackBase::Error)>&& callback) > { > if (!isValid()) { >- callback({ }, CallbackBase::Error::OwnerWasInvalidated); >+ callback(CallbackBase::Error::OwnerWasInvalidated); > return; > } > >+ if (contentType) >+ attachment->setContentType(*contentType); >+ >+ auto attachmentIdentifier = attachment->identifier(); >+ m_attachmentIdentifierToAttachmentMap.set(attachmentIdentifier, WTFMove(attachment)); >+ > auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken()); >- m_process->send(Messages::WebPage::RequestAttachmentInfo(identifier, callbackID), m_pageID); >+ m_process->send(Messages::WebPage::InsertAttachment(attachmentIdentifier, options, fileSize, filename, contentType, callbackID), m_pageID); > } > > void WebPageProxy::setAttachmentDisplayOptions(const String& identifier, AttachmentDisplayOptions options, Function<void(CallbackBase::Error)>&& callback) >@@ -7774,7 +7767,7 @@ void WebPageProxy::setAttachmentDisplayOptions(const String& identifier, Attachm > m_process->send(Messages::WebPage::SetAttachmentDisplayOptions(identifier, options, callbackID), m_pageID); > } > >-void WebPageProxy::setAttachmentDataAndContentType(const String& identifier, SharedBuffer& data, std::optional<String>&& newContentType, std::optional<String>&& newFilename, Function<void(CallbackBase::Error)>&& callback) >+void WebPageProxy::updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String>&& newContentType, std::optional<String>&& newFilename, Function<void(CallbackBase::Error)>&& callback) > { > if (!isValid()) { > callback(CallbackBase::Error::OwnerWasInvalidated); >@@ -7782,19 +7775,87 @@ void WebPageProxy::setAttachmentDataAndContentType(const String& identifier, Sha > } > > auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken()); >- m_process->send(Messages::WebPage::SetAttachmentDataAndContentType(identifier, IPC::SharedBufferDataReference { &data }, WTFMove(newContentType), WTFMove(newFilename), callbackID), m_pageID); >+ m_process->send(Messages::WebPage::UpdateAttachmentAttributes(identifier, fileSize, WTFMove(newContentType), WTFMove(newFilename), callbackID), m_pageID); > } > >+void WebPageProxy::registerAttachmentIdentifierFromData(const String& identifier, const String& contentType, const String& preferredFileName, const IPC::DataReference& data) >+{ >+ if (attachmentForIdentifier(identifier)) >+ return; >+ >+ auto attachment = ensureAttachment(identifier); >+ attachment->setContentType(contentType); >+ m_attachmentIdentifierToAttachmentMap.set(identifier, attachment.copyRef()); >+ >+ platformRegisterAttachment(WTFMove(attachment), preferredFileName, data); >+} >+ >+void WebPageProxy::registerAttachmentIdentifierFromFilePath(const String& identifier, const String& contentType, const String& filePath) >+{ >+ if (attachmentForIdentifier(identifier)) >+ return; >+ >+ auto attachment = ensureAttachment(identifier); >+ attachment->setContentType(contentType); >+ attachment->setFilePath(filePath); >+ m_attachmentIdentifierToAttachmentMap.set(identifier, attachment.copyRef()); >+ >+ platformRegisterAttachment(WTFMove(attachment), filePath); >+} >+ >+void WebPageProxy::cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier) >+{ >+ auto newAttachment = ensureAttachment(toIdentifier); >+ auto existingAttachment = attachmentForIdentifier(fromIdentifier); >+ if (!existingAttachment) { >+ ASSERT_NOT_REACHED(); >+ return; >+ } >+ >+ newAttachment->setContentType(existingAttachment->contentType()); >+ newAttachment->setFilePath(existingAttachment->filePath()); >+ >+ platformCloneAttachment(existingAttachment.releaseNonNull(), WTFMove(newAttachment)); >+} >+ >+#if !PLATFORM(COCOA) >+ >+void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&&, const String& preferredFileName, const IPC::DataReference&) >+{ >+} >+ >+void WebPageProxy::platformRegisterAttachment(Ref<API::Attachment>&&, const String&) >+{ >+} >+ >+void WebPageProxy::platformCloneAttachment(Ref<API::Attachment>&&, Ref<API::Attachment>&&) >+{ >+} >+ >+#endif >+ > void WebPageProxy::didInsertAttachment(const String& identifier, const String& source) > { >+ ensureAttachment(identifier); > m_pageClient.didInsertAttachment(identifier, source); > } > > void WebPageProxy::didRemoveAttachment(const String& identifier) > { >+ ASSERT(attachmentForIdentifier(identifier)); > m_pageClient.didRemoveAttachment(identifier); > } > >+Ref<API::Attachment> WebPageProxy::ensureAttachment(const String& identifier) >+{ >+ if (auto existingAttachment = attachmentForIdentifier(identifier)) >+ return *existingAttachment; >+ >+ auto attachment = API::Attachment::create(identifier, *this); >+ m_attachmentIdentifierToAttachmentMap.set(identifier, attachment.copyRef()); >+ return attachment; >+} >+ > #endif // ENABLE(ATTACHMENT_ELEMENT) > > void WebPageProxy::writeBlobToFilePath(const URL& url, const String& path, Function<void(bool success)>&& callback) >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index a6f9587d43ecbb0a9eb4f6e560f3acfb2f9e2fe0..e4c57d90a7ae57c02d1bacb8accd63cfd31a8a59 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -135,6 +135,7 @@ class MediaSessionMetadata; > #endif > > namespace API { >+class Attachment; > class ContextMenuClient; > class FindClient; > class FindMatchesClient; >@@ -197,7 +198,6 @@ using FloatBoxExtent = RectEdges<float>; > #if ENABLE(ATTACHMENT_ELEMENT) > namespace WebCore { > struct AttachmentDisplayOptions; >-struct AttachmentInfo; > } > #endif > >@@ -275,10 +275,6 @@ typedef GenericCallback<EditingRange> EditingRangeCallback; > typedef GenericCallback<const String&> StringCallback; > typedef GenericCallback<API::SerializedScriptValue*, bool, const WebCore::ExceptionDetails&> ScriptValueCallback; > >-#if ENABLE(ATTACHMENT_ELEMENT) >-typedef GenericCallback<const WebCore::AttachmentInfo&> AttachmentInfoCallback; >-#endif >- > #if PLATFORM(GTK) > typedef GenericCallback<API::Error*> PrintFinishedCallback; > #endif >@@ -1319,11 +1315,10 @@ public: > #endif > > #if ENABLE(ATTACHMENT_ELEMENT) >- void insertAttachment(const String& identifier, const WebCore::AttachmentDisplayOptions&, const String& filename, std::optional<String> contentType, WebCore::SharedBuffer& data, Function<void(CallbackBase::Error)>&&); >- void requestAttachmentInfo(const String& identifier, Function<void(const WebCore::AttachmentInfo&, CallbackBase::Error)>&&); >+ RefPtr<API::Attachment> attachmentForIdentifier(const String& identifier) const; >+ void insertAttachment(Ref<API::Attachment>&&, const WebCore::AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String> contentType, Function<void(CallbackBase::Error)>&&); > void setAttachmentDisplayOptions(const String& identifier, WebCore::AttachmentDisplayOptions, Function<void(CallbackBase::Error)>&&); >- void setAttachmentDataAndContentType(const String& identifier, WebCore::SharedBuffer& data, std::optional<String>&& newContentType, std::optional<String>&& newFilename, Function<void(CallbackBase::Error)>&&); >- void attachmentInfoCallback(const WebCore::AttachmentInfo&, CallbackID); >+ void updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String>&& newContentType, std::optional<String>&& newFilename, Function<void(CallbackBase::Error)>&&); > #endif > > #if ENABLE(APPLICATION_MANIFEST) >@@ -1807,8 +1802,17 @@ private: > void stopAllURLSchemeTasks(); > > #if ENABLE(ATTACHMENT_ELEMENT) >+ void registerAttachmentIdentifierFromData(const String& identifier, const String& contentType, const String& preferredFileName, const IPC::DataReference&); >+ void registerAttachmentIdentifierFromFilePath(const String& identifier, const String& contentType, const String& filePath); >+ void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier); >+ >+ void platformRegisterAttachment(Ref<API::Attachment>&&, const String& preferredFileName, const IPC::DataReference&); >+ void platformRegisterAttachment(Ref<API::Attachment>&&, const String& filePath); >+ void platformCloneAttachment(Ref<API::Attachment>&& fromAttachment, Ref<API::Attachment>&& toAttachment); >+ > void didInsertAttachment(const String& identifier, const String& source); > void didRemoveAttachment(const String& identifier); >+ Ref<API::Attachment> ensureAttachment(const String& identifier); > #endif > > #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING) >@@ -2208,6 +2212,10 @@ private: > > HashMap<String, Ref<WebURLSchemeHandler>> m_urlSchemeHandlersByScheme; > HashMap<uint64_t, Ref<WebURLSchemeHandler>> m_urlSchemeHandlersByIdentifier; >+ >+#if ENABLE(ATTACHMENT_ELEMENT) >+ HashMap<String, Ref<API::Attachment>> m_attachmentIdentifierToAttachmentMap; >+#endif > > #if PLATFORM(MAC) && ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING) > std::unique_ptr<DisplayLink> m_displayLink; >diff --git a/Source/WebKit/UIProcess/WebPageProxy.messages.in b/Source/WebKit/UIProcess/WebPageProxy.messages.in >index 68d6cb9b8a0e48add9fe7a76706ebadb52c0043b..1678f322b4e48975245654b259ebbca32d27e1a4 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.messages.in >+++ b/Source/WebKit/UIProcess/WebPageProxy.messages.in >@@ -176,9 +176,6 @@ messages -> WebPageProxy { > EditingRangeCallback(struct WebKit::EditingRange range, WebKit::CallbackID callbackID) > UnsignedCallback(uint64_t result, WebKit::CallbackID callbackID) > RectForCharacterRangeCallback(WebCore::IntRect rect, struct WebKit::EditingRange actualRange, WebKit::CallbackID callbackID) >-#if ENABLE(ATTACHMENT_ELEMENT) >- AttachmentInfoCallback(struct WebCore::AttachmentInfo info, WebKit::CallbackID callbackID); >-#endif > #if ENABLE(APPLICATION_MANIFEST) > ApplicationManifestCallback(std::optional<WebCore::ApplicationManifest> manifest, WebKit::CallbackID callbackID) > #endif >@@ -528,6 +525,9 @@ messages -> WebPageProxy { > #endif > > #if ENABLE(ATTACHMENT_ELEMENT) >+ RegisterAttachmentIdentifierFromData(String identifier, String contentType, String preferredFileName, IPC::DataReference data) >+ RegisterAttachmentIdentifierFromFilePath(String identifier, String contentType, String filePath) >+ CloneAttachmentData(String fromIdentifier, String toIdentifier) > DidInsertAttachment(String identifier, String source) > DidRemoveAttachment(String identifier) > #endif >diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.h b/Source/WebKit/UIProcess/ios/PageClientImplIOS.h >index 1c7abfc26c636d9480e3fddc7c6bea51332f26b9..415e669e81be65a3e9d4d07411e9753e7b5e9c43 100644 >--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.h >+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.h >@@ -35,7 +35,7 @@ OBJC_CLASS WKContentView; > OBJC_CLASS WKEditorUndoTargetObjC; > > namespace WebCore { >-struct PromisedBlobInfo; >+struct PromisedAttachmentInfo; > } > > namespace WebKit { >diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >index f90a2f8a755d9b638244566ddd096270703e2115..017498eae20b0cabe061681452da23a397c275d3 100644 >--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm >@@ -53,7 +53,7 @@ > #import "_WKDownloadInternal.h" > #import <WebCore/NotImplemented.h> > #import <WebCore/PlatformScreen.h> >-#import <WebCore/PromisedBlobInfo.h> >+#import <WebCore/PromisedAttachmentInfo.h> > #import <WebCore/SharedBuffer.h> > #import <WebCore/TextIndicator.h> > #import <WebCore/ValidationBubble.h> >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >index cc45c5cff220d325765f0a0721e11b9985149469..a22830adff3c84b7b5ae4dde9fb3a412ba7622e5 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h >@@ -61,7 +61,7 @@ class Color; > class FloatQuad; > class IntSize; > class SelectionRect; >-struct PromisedBlobInfo; >+struct PromisedAttachmentInfo; > enum class RouteSharingPolicy; > } > >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >index e829d450125f07c8523a739360a8016566a1f968..00960498d157865b563ec6a3264ac49de1daa16e 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >@@ -80,7 +80,7 @@ > #import <WebCore/Pasteboard.h> > #import <WebCore/Path.h> > #import <WebCore/PathUtilities.h> >-#import <WebCore/PromisedBlobInfo.h> >+#import <WebCore/PromisedAttachmentInfo.h> > #import <WebCore/RuntimeApplicationChecks.h> > #import <WebCore/Scrollbar.h> > #import <WebCore/TextIndicator.h> >@@ -4873,8 +4873,8 @@ static BOOL shouldEnableDragInteractionForPolicy(_WKDragInteractionPolicy policy > { > ASSERT(item.sourceAction != DragSourceActionNone); > >- if (item.promisedBlob) >- [self _prepareToDragPromisedBlob:item.promisedBlob]; >+ if (item.promisedAttachmentInfo) >+ [self _prepareToDragPromisedAttachment:item.promisedAttachmentInfo]; > > auto dragImage = adoptNS([[UIImage alloc] initWithCGImage:image.get() scale:_page->deviceScaleFactor() orientation:UIImageOrientationUp]); > _dragDropInteractionState.stageDragItem(item, dragImage.get()); >@@ -5075,7 +5075,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop > [_editDropCaretView updateToPosition:[WKTextPosition textPositionWithRect:rect]]; > } > >-- (void)_prepareToDragPromisedBlob:(const PromisedBlobInfo&)info >+- (void)_prepareToDragPromisedAttachment:(const PromisedAttachmentInfo&)info > { > auto session = retainPtr(_dragDropInteractionState.dragSession()); > if (!session) { >@@ -5086,7 +5086,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop > auto numberOfAdditionalTypes = info.additionalTypes.size(); > ASSERT(numberOfAdditionalTypes == info.additionalData.size()); > >- RELEASE_LOG(DragAndDrop, "Drag session: %p preparing to drag blob: %s", session.get(), info.blobURL.string().utf8().data()); >+ RELEASE_LOG(DragAndDrop, "Drag session: %p preparing to drag blob: %s with attachment identifier: %s", session.get(), info.blobURL.string().utf8().data(), info.attachmentIdentifier.utf8().data()); > > auto registrationList = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]); > [registrationList setPreferredPresentationStyle:WebPreferredPresentationStyleAttachment]; >@@ -5099,7 +5099,7 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop > } > } > >- [registrationList addPromisedType:info.contentType fileCallback:[session = WTFMove(session), weakSelf = WeakObjCPtr<WKContentView>(self), url = info.blobURL] (WebItemProviderFileCallback callback) { >+ [registrationList addPromisedType:info.contentType fileCallback:[session = WTFMove(session), weakSelf = WeakObjCPtr<WKContentView>(self), info] (WebItemProviderFileCallback callback) { > auto strongSelf = weakSelf.get(); > if (!strongSelf) { > callback(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorWebViewInvalidated userInfo:nil]); >@@ -5109,13 +5109,24 @@ static NSArray<UIItemProvider *> *extractItemProvidersFromDropSession(id <UIDrop > NSString *temporaryBlobDirectory = FileSystem::createTemporaryDirectory(@"blobs"); > NSURL *destinationURL = [NSURL fileURLWithPath:[temporaryBlobDirectory stringByAppendingPathComponent:[NSUUID UUID].UUIDString] isDirectory:NO]; > >- RELEASE_LOG(DragAndDrop, "Drag session: %p delivering promised blob at path: %@", session.get(), destinationURL.path); >- strongSelf->_page->writeBlobToFilePath(url, destinationURL.path, [protectedURL = retainPtr(destinationURL), protectedCallback = makeBlockPtr(callback)] (bool success) { >- if (success) >- protectedCallback(protectedURL.get(), nil); >+ auto attachment = strongSelf->_page->attachmentForIdentifier(info.attachmentIdentifier); >+ if (attachment && attachment->fileWrapper()) { >+ RELEASE_LOG(DragAndDrop, "Drag session: %p delivering promised attachment: %s at path: %@", session.get(), info.attachmentIdentifier.utf8().data(), destinationURL.path); >+ NSError *fileWrapperError = nil; >+ if ([attachment->fileWrapper() writeToURL:destinationURL options:0 originalContentsURL:nil error:&fileWrapperError]) >+ callback(destinationURL, nil); > else >- protectedCallback(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorUnknown userInfo:nil]); >- }); >+ callback(nil, fileWrapperError); >+ } else if (!info.blobURL.isEmpty()) { >+ RELEASE_LOG(DragAndDrop, "Drag session: %p delivering promised blob at path: %@", session.get(), destinationURL.path); >+ strongSelf->_page->writeBlobToFilePath(info.blobURL, destinationURL.path, [protectedURL = retainPtr(destinationURL), protectedCallback = makeBlockPtr(callback)] (bool success) { >+ if (success) >+ protectedCallback(protectedURL.get(), nil); >+ else >+ protectedCallback(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorUnknown userInfo:nil]); >+ }); >+ } else >+ callback(nil, [NSError errorWithDomain:WKErrorDomain code:WKErrorWebViewInvalidated userInfo:nil]); > > [ensureLocalDragSessionContext(session.get()) addTemporaryDirectory:temporaryBlobDirectory]; > }]; >diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.h b/Source/WebKit/UIProcess/mac/PageClientImplMac.h >index 972ca64ff7c75bcd84c173912ce06c6bd5f475a1..c884fa2bba9f8faec9766b22321e1f3ce5e85d13 100644 >--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.h >+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.h >@@ -38,7 +38,7 @@ > namespace WebCore { > class AlternativeTextUIController; > struct DragItem; >-struct PromisedBlobInfo; >+struct PromisedAttachmentInfo; > } > > namespace WebKit { >diff --git a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm >index 3a5937934d8b8d064423e75166a66b58a0593446..0857f143488df67fdebe52bbf53a9fa8b3bb9b91 100644 >--- a/Source/WebKit/UIProcess/mac/PageClientImplMac.mm >+++ b/Source/WebKit/UIProcess/mac/PageClientImplMac.mm >@@ -70,7 +70,7 @@ > #import <WebCore/KeyboardEvent.h> > #import <WebCore/NotImplemented.h> > #import <WebCore/PlatformScreen.h> >-#import <WebCore/PromisedBlobInfo.h> >+#import <WebCore/PromisedAttachmentInfo.h> > #import <WebCore/SharedBuffer.h> > #import <WebCore/TextIndicator.h> > #import <WebCore/TextIndicatorWindow.h> >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >index d87a5384cd7e0984b7814d590eb65956ff40b75a..ce7d889255384f83eeb05d71483bb4cdc7a44722 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp >@@ -160,6 +160,21 @@ bool WebEditorClient::shouldApplyStyle(StyleProperties* style, Range* range) > > #if ENABLE(ATTACHMENT_ELEMENT) > >+void WebEditorClient::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& preferredFileName, Ref<SharedBuffer>&& data) >+{ >+ m_page->send(Messages::WebPageProxy::RegisterAttachmentIdentifierFromData(identifier, contentType, preferredFileName, IPC::SharedBufferDataReference { data.ptr() })); >+} >+ >+void WebEditorClient::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& filePath) >+{ >+ m_page->send(Messages::WebPageProxy::RegisterAttachmentIdentifierFromFilePath(identifier, contentType, filePath)); >+} >+ >+void WebEditorClient::cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier) >+{ >+ m_page->send(Messages::WebPageProxy::CloneAttachmentData(fromIdentifier, toIdentifier)); >+} >+ > void WebEditorClient::didInsertAttachment(const String& identifier, const String& source) > { > m_page->send(Messages::WebPageProxy::DidInsertAttachment(identifier, source)); >diff --git a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >index be66faf181a9cf0e8b646998efa44f039eac6493..fdb70ebd6070107a3d82b285a5463f8d74b02b7d 100644 >--- a/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >+++ b/Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h >@@ -60,8 +60,12 @@ private: > bool shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*) final; > > #if ENABLE(ATTACHMENT_ELEMENT) >+ void registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& preferredFileName, Ref<WebCore::SharedBuffer>&&) final; >+ void registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& filePath) final; >+ void cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier) final; > void didInsertAttachment(const String& identifier, const String& source) final; > void didRemoveAttachment(const String& identifier) final; >+ bool supportsClientSideAttachmentData() const final { return true; } > #endif > > void didBeginEditing() final; >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index 82fff4948d28c6a6c8b25568bc589508c9603a37..f28778a40bd874fadb70563897503879633eb5bb 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -185,7 +185,7 @@ > #include <WebCore/PlatformKeyboardEvent.h> > #include <WebCore/PluginDocument.h> > #include <WebCore/PrintContext.h> >-#include <WebCore/PromisedBlobInfo.h> >+#include <WebCore/PromisedAttachmentInfo.h> > #include <WebCore/Range.h> > #include <WebCore/RemoteDOMWindow.h> > #include <WebCore/RemoteFrame.h> >@@ -6067,36 +6067,23 @@ void WebPage::storageAccessResponse(bool wasGranted, uint64_t contextId) > > #if ENABLE(ATTACHMENT_ELEMENT) > >-void WebPage::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, const String& filename, std::optional<String> contentType, const IPC::DataReference& data, CallbackID callbackID) >+void WebPage::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, uint64_t fileSize, const String& fileName, std::optional<String> contentType, CallbackID callbackID) > { > auto& frame = m_page->focusController().focusedOrMainFrame(); >- frame.editor().insertAttachment(identifier, options, filename, SharedBuffer::create(data.data(), data.size()), contentType); >+ frame.editor().insertAttachment(identifier, options, fileSize, fileName, WTFMove(contentType)); > send(Messages::WebPageProxy::VoidCallback(callbackID)); > } > >-void WebPage::requestAttachmentInfo(const String& identifier, CallbackID callbackID) >-{ >- auto attachment = attachmentElementWithIdentifier(identifier); >- if (!attachment) { >- send(Messages::WebPageProxy::AttachmentInfoCallback({ }, callbackID)); >- return; >- } >- >- attachment->requestInfo([callbackID, protectedThis = makeRef(*this), protectedAttachment = WTFMove(attachment)] (const AttachmentInfo& info) { >- protectedThis->send(Messages::WebPageProxy::AttachmentInfoCallback(info, callbackID)); >- }); >-} >- > void WebPage::setAttachmentDisplayOptions(const String&, const AttachmentDisplayOptions&, CallbackID callbackID) > { > send(Messages::WebPageProxy::VoidCallback(callbackID)); > } > >-void WebPage::setAttachmentDataAndContentType(const String& identifier, const IPC::DataReference& data, std::optional<String> newContentType, std::optional<String> newFilename, CallbackID callbackID) >+void WebPage::updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String> newContentType, std::optional<String> newFilename, CallbackID callbackID) > { > if (auto attachment = attachmentElementWithIdentifier(identifier)) { > attachment->document().updateLayout(); >- attachment->updateFileWithData(SharedBuffer::create(data.data(), data.size()), WTFMove(newContentType), WTFMove(newFilename)); >+ attachment->updateAttributes(fileSize, WTFMove(newContentType), WTFMove(newFilename)); > } > send(Messages::WebPageProxy::VoidCallback(callbackID)); > } >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h >index 2b27cc882e25da7239de09a01ccb3eb8498bc63c..06e31e56bbbe12fb26f192d07cf09fec12d09c1d 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.h >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h >@@ -168,7 +168,7 @@ struct GlobalFrameIdentifier; > struct GlobalWindowIdentifier; > struct Highlight; > struct KeypressCommand; >-struct PromisedBlobInfo; >+struct PromisedAttachmentInfo; > struct TextCheckingResult; > struct ViewportArguments; > >@@ -1073,10 +1073,9 @@ public: > #endif > > #if ENABLE(ATTACHMENT_ELEMENT) >- void insertAttachment(const String& identifier, const WebCore::AttachmentDisplayOptions&, const String& filename, std::optional<String> contentType, const IPC::DataReference&, CallbackID); >- void requestAttachmentInfo(const String& identifier, CallbackID); >+ void insertAttachment(const String& identifier, const WebCore::AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String> contentType, CallbackID); > void setAttachmentDisplayOptions(const String& identifier, const WebCore::AttachmentDisplayOptions&, CallbackID); >- void setAttachmentDataAndContentType(const String& identifier, const IPC::DataReference&, std::optional<String> newContentType, std::optional<String> newFilename, CallbackID); >+ void updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String> newContentType, std::optional<String> newFilename, CallbackID); > #endif > > #if ENABLE(APPLICATION_MANIFEST) >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >index 64360768a30c621462ac55d4cb3ace90242878f5..59b2b751f12d6ec41d054c719270a09858be4686 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in >@@ -509,10 +509,9 @@ messages -> WebPage LegacyReceiver { > #endif > > #if ENABLE(ATTACHMENT_ELEMENT) >- InsertAttachment(String identifier, struct WebCore::AttachmentDisplayOptions options, String filename, std::optional<String> contentType, IPC::DataReference data, WebKit::CallbackID callbackID) >- RequestAttachmentInfo(String identifier, WebKit::CallbackID callbackID) >+ InsertAttachment(String identifier, struct WebCore::AttachmentDisplayOptions options, uint64_t fileSize, String fileName, std::optional<String> contentType, WebKit::CallbackID callbackID) > SetAttachmentDisplayOptions(String identifier, struct WebCore::AttachmentDisplayOptions options, WebKit::CallbackID callbackID) >- SetAttachmentDataAndContentType(String identifier, IPC::DataReference data, std::optional<String> newContentType, std::optional<String> newFilename, WebKit::CallbackID callbackID) >+ UpdateAttachmentAttributes(String identifier, uint64_t fileSize, std::optional<String> newContentType, std::optional<String> newFilename, WebKit::CallbackID callbackID) > #endif > > #if ENABLE(APPLICATION_MANIFEST) >diff --git a/Source/WebKitLegacy/win/WebCoreSupport/WebDragClient.cpp b/Source/WebKitLegacy/win/WebCoreSupport/WebDragClient.cpp >index f60091faa45f47043b99f37de687c95dbc8a4599..1bc13526d60d2e4a81b63a8b75ddfdae724e21fa 100644 >--- a/Source/WebKitLegacy/win/WebCoreSupport/WebDragClient.cpp >+++ b/Source/WebKitLegacy/win/WebCoreSupport/WebDragClient.cpp >@@ -39,6 +39,7 @@ > #include <WebCore/Page.h> > #include <WebCore/Pasteboard.h> > #include <WebCore/PlatformMouseEvent.h> >+#include <WebCore/SharedBuffer.h> > #include <shlobj.h> > > using namespace WebCore; >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index aef2524e482848c51c3ea5d2a777e6b5c1638509..22de0f3ef09ba19e0a95769a87caa84a1d58d387 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,42 @@ >+2018-08-18 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ Test bug; please ignore >+ https://bugs.webkit.org/show_bug.cgi?id=188744 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adjusts existing attachment API tests. See below for more detail. >+ >+ * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm: >+ (-[TestWKWebView synchronouslyInsertAttachmentWithFileWrapper:contentType:]): >+ (-[TestWKWebView synchronouslyInsertAttachmentWithFilename:contentType:data:]): >+ (-[_WKAttachment synchronouslySetData:newContentType:newFilename:error:]): >+ (-[_WKAttachment synchronouslySetFileWrapper:newContentType:error:]): >+ >+ Move off of deprecated attachment SPI, and add new helper functions to synchronously insert a new attachment or >+ update an existing attachment with a file wrapper. >+ >+ (-[_WKAttachment expectRequestedDataToBe:]): >+ (TestWebKitAPI::TEST): >+ >+ Add a new test to verify that file-URL-backed NSFileWrappers can be used to insert and update attachment data. >+ Also augment an existing test to check that an attachment element which has been copied and pasted within the >+ same document has a different _WKAttachment wrapper object than its duplicate, but both _WKAttachments are >+ backed by the same NSFileWrapper that was originally used to insert the attachment. >+ >+ Additionally, add another macOS test to verify that dropping promised files in an attachment-element-enabled >+ editable area inserts attachment elements into the document and notifies the UI client with the inserted >+ attachment data. >+ >+ (-[_WKAttachment synchronouslyRequestInfo:]): Deleted. >+ (-[_WKAttachment synchronouslyRequestData:]): Deleted. >+ * TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm: >+ (-[DragAndDropSimulator _webView:didInsertAttachment:withSource:]): >+ >+ Move off of -_webView:didInsertAttachment:. >+ >+ (-[DragAndDropSimulator _webView:didInsertAttachment:]): Deleted. >+ > 2018-08-20 Claudio Saavedra <csaavedra@igalia.com> > > Add WPE Debug configuration to the flakiness dashboard >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm >index 2f7c50369d1f2e9dd8f9803f88f1353c52a33948..20902d22276b344d3fa54afdd990441d70a79fe0 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm >@@ -145,13 +145,17 @@ private: > @interface TestWKWebView (AttachmentTesting) > @end > >+static NSString *attachmentEditingTestMarkup = @"<meta name='viewport' content='width=device-width, initial-scale=1'>" >+ "<script>focus = () => document.body.focus()</script>" >+ "<body onload=focus() contenteditable></body>"; >+ > static RetainPtr<TestWKWebView> webViewForTestingAttachments(CGSize webViewSize, WKWebViewConfiguration *configuration) > { > configuration._attachmentElementEnabled = YES; > WKPreferencesSetCustomPasteboardDataEnabled((WKPreferencesRef)[configuration preferences], YES); > > auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, webViewSize.width, webViewSize.height) configuration:configuration]); >- [webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width, initial-scale=1'><script>focus = () => document.body.focus()</script><body onload=focus() contenteditable></body>"]; >+ [webView synchronouslyLoadHTMLString:attachmentEditingTestMarkup]; > > return webView; > } >@@ -237,10 +241,23 @@ static NSData *testPDFData() > return success; > } > >+- (_WKAttachment *)synchronouslyInsertAttachmentWithFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType >+{ >+ __block bool done = false; >+ RetainPtr<_WKAttachment> attachment = [self _insertAttachmentWithFileWrapper:fileWrapper contentType:contentType options:nil completion:^(BOOL) { >+ done = true; >+ }]; >+ TestWebKitAPI::Util::run(&done); >+ return attachment.autorelease(); >+} >+ > - (_WKAttachment *)synchronouslyInsertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data > { > __block bool done = false; >- RetainPtr<_WKAttachment> attachment = [self _insertAttachmentWithFilename:filename contentType:contentType data:data options:nil completion:^(BOOL) { >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:data]); >+ if (filename) >+ [fileWrapper setPreferredFilename:filename]; >+ RetainPtr<_WKAttachment> attachment = [self _insertAttachmentWithFileWrapper:fileWrapper.get() contentType:contentType options:nil completion:^(BOOL) { > done = true; > }]; > TestWebKitAPI::Util::run(&done); >@@ -312,13 +329,12 @@ static NSData *testPDFData() > *error = resultError.autorelease(); > } > >-- (_WKAttachmentInfo *)synchronouslyRequestInfo:(NSError **)error >+- (void)synchronouslySetFileWrapper:(NSFileWrapper *)fileWrapper newContentType:(NSString *)newContentType error:(NSError **)error > { >- __block RetainPtr<_WKAttachmentInfo> result; > __block RetainPtr<NSError> resultError; > __block bool done = false; >- [self requestInfo:^(_WKAttachmentInfo *info, NSError *error) { >- result = info; >+ >+ [self setFileWrapper:fileWrapper contentType:newContentType completion:^(NSError *error) { > resultError = error; > done = true; > }]; >@@ -327,20 +343,17 @@ static NSData *testPDFData() > > if (error) > *error = resultError.autorelease(); >- >- return result.autorelease(); >-} >- >-- (NSData *)synchronouslyRequestData:(NSError **)error >-{ >- return [self synchronouslyRequestInfo:error].data; > } > > - (void)synchronouslySetData:(NSData *)data newContentType:(NSString *)newContentType newFilename:(NSString *)newFilename error:(NSError **)error > { > __block RetainPtr<NSError> resultError; > __block bool done = false; >- [self setData:data newContentType:newContentType newFilename:newFilename completion:^(NSError *error) { >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:data]); >+ if (newFilename) >+ [fileWrapper setPreferredFilename:newFilename]; >+ >+ [self setFileWrapper:fileWrapper.get() contentType:newContentType completion:^(NSError *error) { > resultError = error; > done = true; > }]; >@@ -354,9 +367,9 @@ static NSData *testPDFData() > - (void)expectRequestedDataToBe:(NSData *)expectedData > { > NSError *requestError = nil; >- _WKAttachmentInfo *info = [self synchronouslyRequestInfo:&requestError]; >+ _WKAttachmentInfo *info = self.info; > >- BOOL observedDataIsEqualToExpectedData = [info.data isEqualToData:expectedData] || info.data == expectedData; >+ BOOL observedDataIsEqualToExpectedData = info.data == expectedData || [info.data isEqualToData:expectedData]; > EXPECT_TRUE(observedDataIsEqualToExpectedData); > if (!observedDataIsEqualToExpectedData) { > NSLog(@"Expected data: %@ but observed: %@ for %@", [expectedData shortDescription], [info.data shortDescription], self); >@@ -499,7 +512,7 @@ TEST(WKAttachmentTests, AttachmentElementInsertion) > observer.expectAttachmentUpdates(@[ ], @[ firstAttachment.get() ]); > } > >- _WKAttachmentInfo *info = [firstAttachment synchronouslyRequestInfo:nil]; >+ _WKAttachmentInfo *info = [firstAttachment info]; > EXPECT_TRUE([info.data isEqualToData:testHTMLData()]); > EXPECT_TRUE([info.contentType isEqualToString:@"text/html"]); > EXPECT_TRUE([info.name isEqualToString:@"foo"]); >@@ -516,7 +529,7 @@ TEST(WKAttachmentTests, AttachmentElementInsertion) > scope.expectAttachmentUpdates(@[ firstAttachment.get() ], @[ secondAttachment.get() ]); > } > >- [firstAttachment expectRequestedDataToBe:nil]; >+ [firstAttachment expectRequestedDataToBe:testHTMLData()]; > [secondAttachment expectRequestedDataToBe:testImageData()]; > EXPECT_FALSE([webView hasAttribute:@"webkitattachmentbloburl" forQuerySelector:@"attachment"]); > EXPECT_FALSE([webView hasAttribute:@"webkitattachmentpath" forQuerySelector:@"attachment"]); >@@ -539,14 +552,14 @@ TEST(WKAttachmentTests, AttachmentUpdatesWhenInsertingAndDeletingNewline) > > [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]]; > >- _WKAttachmentInfo *info = [attachment synchronouslyRequestInfo:nil]; >+ _WKAttachmentInfo *info = [attachment info]; > EXPECT_TRUE([info.data isEqualToData:testHTMLData()]); > EXPECT_TRUE([info.contentType isEqualToString:@"text/plain"]); > EXPECT_TRUE([info.name isEqualToString:@"foo.txt"]); > EXPECT_EQ(info.filePath.length, 0U); > > [webView expectUpdatesAfterCommand:@"DeleteForward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]]; >- [attachment expectRequestedDataToBe:nil]; >+ [attachment expectRequestedDataToBe:testHTMLData()]; > } > > TEST(WKAttachmentTests, AttachmentUpdatesWhenUndoingAndRedoing) >@@ -560,19 +573,19 @@ TEST(WKAttachmentTests, AttachmentUpdatesWhenUndoingAndRedoing) > observer.expectAttachmentUpdates(@[ ], @[attachment.get()]); > } > [webView expectUpdatesAfterCommand:@"Undo" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]]; >- [attachment expectRequestedDataToBe:nil]; >+ [attachment expectRequestedDataToBe:htmlData.get()]; > > [webView expectUpdatesAfterCommand:@"Redo" withArgument:nil expectedRemovals:@[] expectedInsertions:@[attachment.get()]]; > [attachment expectRequestedDataToBe:htmlData.get()]; > > [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]]; >- [attachment expectRequestedDataToBe:nil]; >+ [attachment expectRequestedDataToBe:htmlData.get()]; > > [webView expectUpdatesAfterCommand:@"Undo" withArgument:nil expectedRemovals:@[] expectedInsertions:@[attachment.get()]]; > [attachment expectRequestedDataToBe:htmlData.get()]; > > [webView expectUpdatesAfterCommand:@"Redo" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]]; >- [attachment expectRequestedDataToBe:nil]; >+ [attachment expectRequestedDataToBe:htmlData.get()]; > } > > TEST(WKAttachmentTests, AttachmentUpdatesWhenChangingFontStyles) >@@ -597,7 +610,7 @@ TEST(WKAttachmentTests, AttachmentUpdatesWhenChangingFontStyles) > > // Inserting text should delete the current selection, removing the attachment in the process. > [webView expectUpdatesAfterCommand:@"InsertText" withArgument:@"foo" expectedRemovals:@[attachment.get()] expectedInsertions:@[]]; >- [attachment expectRequestedDataToBe:nil]; >+ [attachment expectRequestedDataToBe:testHTMLData()]; > } > > TEST(WKAttachmentTests, AttachmentUpdatesWhenInsertingLists) >@@ -661,7 +674,7 @@ TEST(WKAttachmentTests, AttachmentUpdatesWhenCuttingAndPasting) > [webView _synchronouslyExecuteEditCommand:@"Cut" argument:nil]; > observer.expectAttachmentUpdates(@[attachment.get()], @[]); > } >- [attachment expectRequestedDataToBe:nil]; >+ [attachment expectRequestedDataToBe:testHTMLData()]; > { > ObserveAttachmentUpdatesForScope observer(webView.get()); > [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil]; >@@ -689,36 +702,7 @@ TEST(WKAttachmentTests, AttachmentDataForEmptyFile) > [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; > scope.expectAttachmentUpdates(@[attachment.get()], @[]); > } >- [attachment expectRequestedDataToBe:nil]; >-} >- >-TEST(WKAttachmentTests, MultipleSimultaneousAttachmentDataRequests) >-{ >- auto webView = webViewForTestingAttachments(); >- RetainPtr<NSData> htmlData = testHTMLData(); >- RetainPtr<_WKAttachment> attachment; >- { >- ObserveAttachmentUpdatesForScope observer(webView.get()); >- attachment = [webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:htmlData.get()]; >- observer.expectAttachmentUpdates(@[], @[attachment.get()]); >- } >- __block RetainPtr<NSData> dataForFirstRequest; >- __block RetainPtr<NSData> dataForSecondRequest; >- __block bool done = false; >- [attachment requestInfo:^(_WKAttachmentInfo *info, NSError *error) { >- EXPECT_TRUE(!error); >- dataForFirstRequest = info.data; >- }]; >- [attachment requestInfo:^(_WKAttachmentInfo *info, NSError *error) { >- EXPECT_TRUE(!error); >- dataForSecondRequest = info.data; >- done = true; >- }]; >- >- Util::run(&done); >- >- EXPECT_TRUE([dataForFirstRequest isEqualToData:htmlData.get()]); >- EXPECT_TRUE([dataForSecondRequest isEqualToData:htmlData.get()]); >+ [attachment expectRequestedDataToBe:[NSData data]]; > } > > TEST(WKAttachmentTests, ChangeAttachmentDataAndFileInformation) >@@ -779,7 +763,7 @@ TEST(WKAttachmentTests, InsertPastedImageAsAttachment) > attachment = observer.observer().inserted[0]; > } > >- auto size = platformImageWithData([attachment synchronouslyRequestData:nil]).size; >+ auto size = platformImageWithData([attachment info].data).size; > EXPECT_EQ(215., size.width); > EXPECT_EQ(174., size.height); > EXPECT_WK_STREQ([attachment uniqueIdentifier], [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').uniqueIdentifier"]); >@@ -833,7 +817,7 @@ TEST(WKAttachmentTests, InsertPastedAttributedStringContainingMultipleAttachment > EXPECT_EQ(0U, observer.observer().removed.count); > EXPECT_EQ(3U, observer.observer().inserted.count); > for (_WKAttachment *attachment in observer.observer().inserted) { >- NSData *data = [attachment synchronouslyRequestData:nil]; >+ NSData *data = attachment.info.data; > if ([data isEqualToData:testZIPData()]) > zipAttachment = attachment; > else if ([data isEqualToData:testPDFData()]) >@@ -894,11 +878,12 @@ TEST(WKAttachmentTests, InsertAndRemoveDuplicateAttachment) > { > auto webView = webViewForTestingAttachments(); > RetainPtr<NSData> data = testHTMLData(); >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:data.get()]); > RetainPtr<_WKAttachment> originalAttachment; > RetainPtr<_WKAttachment> pastedAttachment; > { > ObserveAttachmentUpdatesForScope observer(webView.get()); >- originalAttachment = [webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:data.get()]; >+ originalAttachment = [webView synchronouslyInsertAttachmentWithFileWrapper:fileWrapper.get() contentType:@"text/plain"]; > EXPECT_EQ(0U, observer.observer().removed.count); > observer.expectAttachmentUpdates(@[], @[originalAttachment.get()]); > } >@@ -924,17 +909,22 @@ TEST(WKAttachmentTests, InsertAndRemoveDuplicateAttachment) > [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; > observer.expectAttachmentUpdates(@[originalAttachment.get()], @[]); > } >+ >+ EXPECT_FALSE([originalAttachment isEqual:pastedAttachment.get()]); >+ EXPECT_TRUE([[originalAttachment info].fileWrapper isEqual:[pastedAttachment info].fileWrapper]); >+ EXPECT_TRUE([[originalAttachment info].fileWrapper isEqual:fileWrapper.get()]); > } > > TEST(WKAttachmentTests, InsertDuplicateAttachmentAndUpdateData) > { > auto webView = webViewForTestingAttachments(); >- RetainPtr<NSData> originalData = testHTMLData(); >+ auto originalData = retainPtr(testHTMLData()); >+ auto fileWrapper = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:originalData.get()]); > RetainPtr<_WKAttachment> originalAttachment; > RetainPtr<_WKAttachment> pastedAttachment; > { > ObserveAttachmentUpdatesForScope observer(webView.get()); >- originalAttachment = [webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:originalData.get()]; >+ originalAttachment = [webView synchronouslyInsertAttachmentWithFileWrapper:fileWrapper.get() contentType:@"text/plain"]; > EXPECT_EQ(0U, observer.observer().removed.count); > observer.expectAttachmentUpdates(@[], @[originalAttachment.get()]); > } >@@ -953,6 +943,10 @@ TEST(WKAttachmentTests, InsertDuplicateAttachmentAndUpdateData) > [originalAttachment synchronouslySetData:updatedData.get() newContentType:nil newFilename:nil error:nil]; > [originalAttachment expectRequestedDataToBe:updatedData.get()]; > [pastedAttachment expectRequestedDataToBe:originalData.get()]; >+ >+ EXPECT_FALSE([originalAttachment isEqual:pastedAttachment.get()]); >+ EXPECT_FALSE([[originalAttachment info].fileWrapper isEqual:[pastedAttachment info].fileWrapper]); >+ EXPECT_FALSE([[originalAttachment info].fileWrapper isEqual:fileWrapper.get()]); > } > > TEST(WKAttachmentTests, InjectedBundleReplaceURLsWhenPastingAttributedString) >@@ -987,6 +981,37 @@ TEST(WKAttachmentTests, InjectedBundleReplaceURLWhenPastingImage) > EXPECT_WK_STREQ("cid:foo-bar", [webView valueOfAttribute:@"src" forQuerySelector:@"img"]); > } > >+TEST(WKAttachmentTests, InsertAttachmentUsingFileWrapperWithFilePath) >+{ >+ auto webView = webViewForTestingAttachments(); >+ auto originalFileWrapper = adoptNS([[NSFileWrapper alloc] initWithURL:testImageFileURL() options:0 error:nil]); >+ RetainPtr<_WKAttachment> attachment; >+ { >+ ObserveAttachmentUpdatesForScope observer(webView.get()); >+ attachment = [webView synchronouslyInsertAttachmentWithFileWrapper:originalFileWrapper.get() contentType:nil]; >+ observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]); >+ } >+ >+ _WKAttachmentInfo *infoBeforeUpdate = [attachment info]; >+ EXPECT_WK_STREQ("image/png", infoBeforeUpdate.contentType); >+ EXPECT_WK_STREQ("icon.png", infoBeforeUpdate.name); >+ EXPECT_TRUE([originalFileWrapper isEqual:infoBeforeUpdate.fileWrapper]); >+ [attachment expectRequestedDataToBe:testImageData()]; >+ >+ auto newFileWrapper = adoptNS([[NSFileWrapper alloc] initWithURL:testPDFFileURL() options:0 error:nil]); >+ { >+ ObserveAttachmentUpdatesForScope observer(webView.get()); >+ [attachment synchronouslySetFileWrapper:newFileWrapper.get() newContentType:nil error:nil]; >+ observer.expectAttachmentUpdates(@[ ], @[ ]); >+ } >+ >+ _WKAttachmentInfo *infoAfterUpdate = [attachment info]; >+ EXPECT_WK_STREQ("application/pdf", infoAfterUpdate.contentType); >+ EXPECT_WK_STREQ("test.pdf", infoAfterUpdate.name); >+ EXPECT_TRUE([newFileWrapper isEqual:infoAfterUpdate.fileWrapper]); >+ [attachment expectRequestedDataToBe:testPDFData()]; >+} >+ > #pragma mark - Platform-specific tests > > #if PLATFORM(MAC) >@@ -1008,17 +1033,15 @@ TEST(WKAttachmentTestsMac, InsertPastedFileURLsAsAttachments) > } > > NSArray<NSData *> *expectedAttachmentData = @[ testPDFData(), testImageData() ]; >- EXPECT_TRUE([expectedAttachmentData containsObject:[[insertedAttachments firstObject] synchronouslyRequestData:nil]]); >- EXPECT_TRUE([expectedAttachmentData containsObject:[[insertedAttachments lastObject] synchronouslyRequestData:nil]]); >+ EXPECT_TRUE([expectedAttachmentData containsObject:[insertedAttachments firstObject].info.data]); >+ EXPECT_TRUE([expectedAttachmentData containsObject:[insertedAttachments lastObject].info.data]); > EXPECT_WK_STREQ("application/pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]); > EXPECT_WK_STREQ("test.pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]); > EXPECT_WK_STREQ("image/png", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]); > EXPECT_WK_STREQ("icon.png", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]); > >- for (_WKAttachment *attachment in insertedAttachments.get()) { >- _WKAttachmentInfo *info = [attachment synchronouslyRequestInfo:nil]; >- EXPECT_GT(info.filePath.length, 0U); >- } >+ for (_WKAttachment *attachment in insertedAttachments.get()) >+ EXPECT_GT(attachment.info.filePath.length, 0U); > > { > ObserveAttachmentUpdatesForScope observer(webView.get()); >@@ -1027,8 +1050,42 @@ TEST(WKAttachmentTestsMac, InsertPastedFileURLsAsAttachments) > NSArray<_WKAttachment *> *removedAttachments = [observer.observer() removed]; > EXPECT_EQ(2U, removedAttachments.count); > EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments firstObject]]); >- EXPECT_TRUE([removedAttachments.lastObject isEqual:[insertedAttachments lastObject]]); >+ EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments lastObject]]); >+ } >+} >+ >+TEST(WKAttachmentTestsMac, InsertDroppedFilePromisesAsAttachments) >+{ >+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [configuration _setAttachmentElementEnabled:YES]; >+ auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:NSMakeRect(0, 0, 400, 400) configuration:configuration.get()]); >+ TestWKWebView *webView = [simulator webView]; >+ [webView synchronouslyLoadHTMLString:attachmentEditingTestMarkup]; >+ [simulator writePromisedFiles:@[ testPDFFileURL(), testImageFileURL() ]]; >+ >+ ObserveAttachmentUpdatesForScope observer(webView); >+ [simulator runFrom:CGPointMake(0, 0) to:CGPointMake(50, 50)]; >+ auto insertedAttachments = retainPtr([observer.observer() inserted]); >+ EXPECT_EQ(2U, [insertedAttachments count]); >+ EXPECT_EQ(2, [[webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"] intValue]); >+ >+ NSArray<NSData *> *expectedData = @[ testPDFData(), testImageData() ]; >+ for (_WKAttachment *attachment in insertedAttachments.get()) { >+ EXPECT_GT(attachment.info.filePath.length, 0U); >+ EXPECT_TRUE([expectedData containsObject:attachment.info.data]); >+ if ([testPDFData() isEqualToData:attachment.info.data]) >+ EXPECT_WK_STREQ("application/pdf", attachment.info.contentType); >+ else if ([testImageData() isEqualToData:attachment.info.data]) >+ EXPECT_WK_STREQ("image/png", attachment.info.contentType); > } >+ >+ [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil]; >+ [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil]; >+ NSArray<_WKAttachment *> *removedAttachments = [observer.observer() removed]; >+ EXPECT_EQ(2U, removedAttachments.count); >+ EXPECT_EQ(0, [[webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"] intValue]); >+ EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments firstObject]]); >+ EXPECT_TRUE([removedAttachments containsObject:[insertedAttachments lastObject]]); > } > > #endif // PLATFORM(MAC) >@@ -1073,7 +1130,7 @@ TEST(WKAttachmentTestsIOS, InsertDroppedAttributedStringContainingAttachment) > EXPECT_EQ(0U, [dragAndDropSimulator removedAttachments].count); > auto attachment = retainPtr([dragAndDropSimulator insertedAttachments].firstObject); > >- auto size = platformImageWithData([attachment synchronouslyRequestData:nil]).size; >+ auto size = platformImageWithData([attachment info].data).size; > EXPECT_EQ(215., size.width); > EXPECT_EQ(174., size.height); > EXPECT_WK_STREQ("image/png", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]); >@@ -1111,13 +1168,8 @@ TEST(WKAttachmentTestsIOS, InsertDroppedRichAndPlainTextFilesAsAttachments) > EXPECT_EQ(2U, [dragAndDropSimulator insertedAttachments].count); > EXPECT_EQ(0U, [dragAndDropSimulator removedAttachments].count); > >- for (_WKAttachment *attachment in [dragAndDropSimulator insertedAttachments]) { >- NSError *error = nil; >- EXPECT_GT([attachment synchronouslyRequestData:&error].length, 0U); >- EXPECT_TRUE(!error); >- if (error) >- NSLog(@"Error: %@", error); >- } >+ for (_WKAttachment *attachment in [dragAndDropSimulator insertedAttachments]) >+ EXPECT_GT([attachment info].data.length, 0U); > > EXPECT_EQ(2, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment').length"].intValue); > EXPECT_WK_STREQ("hello.rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]); >@@ -1174,13 +1226,8 @@ TEST(WKAttachmentTestsIOS, InsertDroppedItemProvidersInOrder) > EXPECT_EQ(2U, [dragAndDropSimulator insertedAttachments].count); > EXPECT_EQ(0U, [dragAndDropSimulator removedAttachments].count); > >- for (_WKAttachment *attachment in [dragAndDropSimulator insertedAttachments]) { >- NSError *error = nil; >- EXPECT_GT([attachment synchronouslyRequestData:&error].length, 0U); >- EXPECT_TRUE(!error); >- if (error) >- NSLog(@"Error: %@", error); >- } >+ for (_WKAttachment *attachment in [dragAndDropSimulator insertedAttachments]) >+ EXPECT_GT([attachment info].data.length, 0U); > > [webView expectElementTagsInOrder:@[ @"ATTACHMENT", @"A", @"ATTACHMENT" ]]; > >diff --git a/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm b/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm >index 9e1f21ee1d53bdd46c333810210ed070df132c8a..0f97a39db60ab2902a58834145a7409b231b57e6 100644 >--- a/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm >+++ b/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm >@@ -680,7 +680,7 @@ static NSArray *dragAndDropEventNames() > return self.overridePerformDropBlock ? self.overridePerformDropBlock(session) : session.items; > } > >-- (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment >+- (void)_webView:(WKWebView *)webView didInsertAttachment:(_WKAttachment *)attachment withSource:(NSString *)source > { > [_insertedAttachments addObject:attachment]; > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188744
:
347497
| 347500