Changeset 235392 in webkit


Ignore:
Timestamp:
Aug 27, 2018 1:14:21 PM (6 years ago)
Author:
Wenson Hsieh
Message:

[Cocoa] Exception (fileType 'dyn.agq8u' is not a valid UTI) raised when dragging an attachment whose file wrapper is a directory
https://bugs.webkit.org/show_bug.cgi?id=188903
<rdar://problem/43702993>

Reviewed by Tim Horton.

Source/WebCore:

Fixes the exception for attachments that are created when dropping files with extensions that don't map to any
known UTIs, and when dropping folders. See below for more detail.

Tests: WKAttachmentTests.InsertFolderAndFileWithUnknownExtension

WKAttachmentTests.DropFolderAsAttachmentAndMoveByDragging
WKAttachmentTests.ChangeAttachmentDataAndFileInformation

  • editing/Editor.cpp:

(WebCore::Editor::insertAttachment):

  • editing/Editor.h:
  • editing/cocoa/WebContentReaderCocoa.mm:

(WebCore::WebContentReader::readFilePaths):

When creating an attachment by dropping or pasting a file backed by a file path, handle the cases where…
(1) the dropped path is a directory, by setting the UTI to "public.directory". This allows us to show a

folder icon for the dropped attachment element on macOS.

(2) the dropped path is a file whose UTI is unknown, by defaulting to "public.data".

By ensuring that the UTI of a dropped file-backed attachment is set to a concrete type in any case, we avoid an
exception when dragging the attachment on macOS, and on iOS, avoid silently failing to drag an attachment.

  • html/HTMLAttachmentElement.cpp:

(WebCore::HTMLAttachmentElement::updateAttributes):

Change this method to take an optional file size (the subtitle attribute will only be set if the file size is
not std::nullopt). Furthermore, allow callers of this method to clear attributes on the attachment element by
passing in std::nullopt for any of the three arguments. This allows us to handle the case where an
attachment's file wrapper is changed from a regular file to a folder whose total size is currently unknown.
Instead of showing "0 bytes", we'll simply refrain from showing a subtitle at all (in the future, this should
be improved by implementing a way to estimate the size of the files in the folder, or perhaps show the number of
items in the folder as the subtitle).

  • html/HTMLAttachmentElement.h:

Source/WebKit:

Fixes the bug by supporting NSFileWrappers of type directory, as well as NSFileWrappers with file that do not
map to concrete type identifiers. Among other things, this patch ensures that:

  • Inserting a directory file wrapper (or using -setFileWrapper:…: to change an existing _WKAttachment's

file wrapper to a directory) does not cause the attachment element to show "0 bytes" as the subtitle.

  • In the above scenario, we also won't end up with a missing "type" attribute for the attachment element,

as well as a corresponding API::Attachment::contentType() that's an empty string.

  • Dropping or pasting attachments backed by paths on disk also doesn't trigger these problems, if the path

is a directory or of unknown file type.

Changes are verified by 2 new API tests.

  • UIProcess/API/APIAttachment.cpp:

(API::Attachment::updateAttributes):
(API::Attachment::fileSizeForDisplay const):

  • UIProcess/API/APIAttachment.h:
  • UIProcess/API/Cocoa/APIAttachmentCocoa.mm:

(API::Attachment::setFileWrapperAndUpdateContentType):

Add a helper that sets the file wrapper to the given NSFileWrapper, and either sets the content type to the
given content type if it's specified, or infers it from the file extension of the new NSFileWrapper. Invoked
whenever an NSFileWrapper and content type combination is set on an API attachment via WebKit SPI.

(API::Attachment::fileSizeForDisplay const):

Returns a file size to be displayed in the attachment element's subtitle. This returns an optional file size,
where std::nullopt indicates that there should not be a file size shown. For now, this returns std::nullopt
for directory file wrappers, though in the future, this should be done only in cases where we don't immediately
have a size estimate for the file wrapper.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _insertAttachmentWithFileWrapper:contentType:options:completion:]):

Use API::Attachment::setFileWrapperAndUpdateContentType() instead of trying to come up with a fallback UTI.

  • UIProcess/API/Cocoa/_WKAttachment.mm:

(-[_WKAttachment setFileWrapper:contentType:completion:]):

Use API::Attachment::setFileWrapperAndUpdateContentType() instead of trying to come up with a fallback UTI.

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::insertAttachment):

Remove the separate arguments for file size, content type, and file name, and instead get them from the given
API Attachment object.

(WebKit::WebPageProxy::updateAttachmentAttributes):

Remove separate arguments for file size, content type and file name and just take an API::Attachment instead.
These separate pieces of information can simply be asked from the Attachment itself.

  • UIProcess/WebPageProxy.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::insertAttachment):
(WebKit::WebPage::updateAttachmentAttributes):

Adjust some interfaces here to allow the displayed file size to be optional.

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:

Tools:

Add two API tests and adjust existing WKAttachment API tests. The new tests exercise the following scenarios, in
both iOS and macOS:

  • Dropping a folder as an attachment element, and then moving that attachment element in the document by

dragging and dropping.

  • Using WKWebView SPI to insert a folder and a file with an unknown extension, and then using more

_WKAttachment SPI to swap the attachments' backing file wrappers.

  • TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:

(runTestWithTemporaryFolder):

Add a helper function to run a test with a new folder path, created in the temporary directory and populated
with some sample content. This folder is deleted after running the test.

(simulateFolderDragWithURL):

Add a helper function to prepare a given DragAndDropSimulator for simulating a dragged folder from a source
external to the web view.

(platformCopyRichTextWithMultipleAttachments):
(platformCopyRichTextWithImage):
(platformCopyPNG):
(TestWebKitAPI::TEST):

Add new API tests, and adjust existing tests to reflect new -setFileWrapper:…: behavior. Specifically,
ChangeAttachmentDataAndFileInformation previously required that changing a _WKAttachment's NSFileWrapper would
preserve the previous NSFileWrapper's preferred name if the new file wrapper does not have a preferred name, but
this quirk is no longer supported.

Also add a few bridging casts for the eventual transition of TestWebKitAPI to ARC.

  • TestWebKitAPI/cocoa/DragAndDropSimulator.h:

Add a new hook to clear any external drag information on an existing DragAndDropSimulator. This is convenient
when using the same DragAndDropSimulator to perform multiple drags in a single test.

  • TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm:

(-[DragAndDropSimulator clearExternalDragInformation]):

  • TestWebKitAPI/mac/DragAndDropSimulatorMac.mm:

(-[DragAndDropSimulator clearExternalDragInformation]):

Location:
trunk
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r235389 r235392  
     12018-08-27  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Cocoa] Exception (fileType 'dyn.agq8u' is not a valid UTI) raised when dragging an attachment whose file wrapper is a directory
     4        https://bugs.webkit.org/show_bug.cgi?id=188903
     5        <rdar://problem/43702993>
     6
     7        Reviewed by Tim Horton.
     8
     9        Fixes the exception for attachments that are created when dropping files with extensions that don't map to any
     10        known UTIs, and when dropping folders. See below for more detail.
     11
     12        Tests:  WKAttachmentTests.InsertFolderAndFileWithUnknownExtension
     13                WKAttachmentTests.DropFolderAsAttachmentAndMoveByDragging
     14                WKAttachmentTests.ChangeAttachmentDataAndFileInformation
     15
     16        * editing/Editor.cpp:
     17        (WebCore::Editor::insertAttachment):
     18        * editing/Editor.h:
     19        * editing/cocoa/WebContentReaderCocoa.mm:
     20        (WebCore::WebContentReader::readFilePaths):
     21
     22        When creating an attachment by dropping or pasting a file backed by a file path, handle the cases where…
     23        (1)     the dropped path is a directory, by setting the UTI to "public.directory". This allows us to show a
     24                folder icon for the dropped attachment element on macOS.
     25        (2)     the dropped path is a file whose UTI is unknown, by defaulting to "public.data".
     26
     27        By ensuring that the UTI of a dropped file-backed attachment is set to a concrete type in any case, we avoid an
     28        exception when dragging the attachment on macOS, and on iOS, avoid silently failing to drag an attachment.
     29
     30        * html/HTMLAttachmentElement.cpp:
     31        (WebCore::HTMLAttachmentElement::updateAttributes):
     32
     33        Change this method to take an optional file size (the subtitle attribute will only be set if the file size is
     34        not `std::nullopt`). Furthermore, allow callers of this method to clear attributes on the attachment element by
     35        passing in `std::nullopt` for any of the three arguments. This allows us to handle the case where an
     36        attachment's file wrapper is changed from a regular file to a folder whose total size is currently unknown.
     37        Instead of showing "0 bytes", we'll simply refrain from showing a subtitle at all (in the future, this should
     38        be improved by implementing a way to estimate the size of the files in the folder, or perhaps show the number of
     39        items in the folder as the subtitle).
     40
     41        * html/HTMLAttachmentElement.h:
     42
    1432018-08-27  Devin Rousso  <drousso@apple.com>
    244
  • trunk/Source/WebCore/editing/Editor.cpp

    r235331 r235392  
    38773877}
    38783878
    3879 void Editor::insertAttachment(const String& identifier, const AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String>&& explicitContentType)
     3879void Editor::insertAttachment(const String& identifier, const AttachmentDisplayOptions&, std::optional<uint64_t>&& fileSize, const String& fileName, const String& contentType)
    38803880{
    38813881    auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document());
    38823882    attachment->setUniqueIdentifier(identifier);
    3883     attachment->updateAttributes(fileSize, WTFMove(explicitContentType), fileName);
     3883    attachment->updateAttributes(WTFMove(fileSize), contentType, fileName);
    38843884
    38853885    auto fragmentToInsert = document().createDocumentFragment();
  • trunk/Source/WebCore/editing/Editor.h

    r235343 r235392  
    504504
    505505#if ENABLE(ATTACHMENT_ELEMENT)
    506     WEBCORE_EXPORT void insertAttachment(const String& identifier, const AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String>&& explicitContentType = std::nullopt);
     506    WEBCORE_EXPORT void insertAttachment(const String& identifier, const AttachmentDisplayOptions&, std::optional<uint64_t>&& fileSize, const String& fileName, const String& contentType);
    507507    void registerAttachmentIdentifier(const String&, const String& /* contentType */, const String& /* preferredFileName */, Ref<SharedBuffer>&&);
    508508    void registerAttachmentIdentifier(const String&, const String& /* contentType */, const String& /* filePath */);
  • trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm

    r235375 r235392  
    704704            auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document);
    705705            if (supportsClientSideAttachmentData(frame)) {
    706                 long long fileSize { 0 };
    707                 FileSystem::getFileSize(path, fileSize);
    708                 auto contentType = File::contentTypeForFile(path);
     706                String contentType;
     707                std::optional<uint64_t> fileSizeForDisplay;
     708                if (FileSystem::fileIsDirectory(path, FileSystem::ShouldFollowSymbolicLinks::Yes))
     709                    contentType = kUTTypeDirectory;
     710                else {
     711                    long long fileSize;
     712                    FileSystem::getFileSize(path, fileSize);
     713                    fileSizeForDisplay = fileSize;
     714                    contentType = File::contentTypeForFile(path);
     715                    if (contentType.isEmpty())
     716                        contentType = kUTTypeData;
     717                }
    709718                frame.editor().registerAttachmentIdentifier(attachment->ensureUniqueIdentifier(), contentType, path);
    710719                if (contentTypeIsSuitableForInlineImageRepresentation(contentType)) {
     
    714723                    fragment->appendChild(image);
    715724                } else {
    716                     attachment->updateAttributes(fileSize, contentType, FileSystem::pathGetFileName(path));
     725                    attachment->updateAttributes(WTFMove(fileSizeForDisplay), contentType, FileSystem::pathGetFileName(path));
    717726                    fragment->appendChild(attachment);
    718727                }
  • trunk/Source/WebCore/html/HTMLAttachmentElement.cpp

    r235137 r235392  
    145145}
    146146
    147 void HTMLAttachmentElement::updateAttributes(uint64_t fileSize, std::optional<String>&& newContentType, std::optional<String>&& newFilename)
     147void HTMLAttachmentElement::updateAttributes(std::optional<uint64_t>&& newFileSize, std::optional<String>&& newContentType, std::optional<String>&& newFilename)
    148148{
    149149    if (newFilename)
    150150        setAttributeWithoutSynchronization(HTMLNames::titleAttr, *newFilename);
     151    else
     152        removeAttribute(HTMLNames::titleAttr);
    151153
    152154    if (newContentType)
    153155        setAttributeWithoutSynchronization(HTMLNames::typeAttr, *newContentType);
     156    else
     157        removeAttribute(HTMLNames::typeAttr);
    154158
    155     setAttributeWithoutSynchronization(HTMLNames::subtitleAttr, fileSizeDescription(fileSize));
     159    if (newFileSize)
     160        setAttributeWithoutSynchronization(HTMLNames::subtitleAttr, fileSizeDescription(*newFileSize));
     161    else
     162        removeAttribute(HTMLNames::subtitleAttr);
     163
    156164    if (auto* renderer = this->renderer())
    157165        renderer->invalidate();
  • trunk/Source/WebCore/html/HTMLAttachmentElement.h

    r235343 r235392  
    5050    void setUniqueIdentifier(const String& uniqueIdentifier) { m_uniqueIdentifier = uniqueIdentifier; }
    5151
    52     WEBCORE_EXPORT void updateAttributes(uint64_t fileSize, std::optional<String>&& newContentType = std::nullopt, std::optional<String>&& newFilename = std::nullopt);
     52    WEBCORE_EXPORT void updateAttributes(std::optional<uint64_t>&& newFileSize = std::nullopt, std::optional<String>&& newContentType = std::nullopt, std::optional<String>&& newFilename = std::nullopt);
    5353
    5454    InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final;
  • trunk/Source/WebKit/ChangeLog

    r235385 r235392  
     12018-08-27  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Cocoa] Exception (fileType 'dyn.agq8u' is not a valid UTI) raised when dragging an attachment whose file wrapper is a directory
     4        https://bugs.webkit.org/show_bug.cgi?id=188903
     5        <rdar://problem/43702993>
     6
     7        Reviewed by Tim Horton.
     8
     9        Fixes the bug by supporting NSFileWrappers of type directory, as well as NSFileWrappers with file that do not
     10        map to concrete type identifiers. Among other things, this patch ensures that:
     11        -       Inserting a directory file wrapper (or using -setFileWrapper:…: to change an existing _WKAttachment's
     12                file wrapper to a directory) does not cause the attachment element to show "0 bytes" as the subtitle.
     13        -       In the above scenario, we also won't end up with a missing "type" attribute for the attachment element,
     14                as well as a corresponding API::Attachment::contentType() that's an empty string.
     15        -       Dropping or pasting attachments backed by paths on disk also doesn't trigger these problems, if the path
     16                is a directory or of unknown file type.
     17
     18        Changes are verified by 2 new API tests.
     19
     20        * UIProcess/API/APIAttachment.cpp:
     21        (API::Attachment::updateAttributes):
     22        (API::Attachment::fileSizeForDisplay const):
     23        * UIProcess/API/APIAttachment.h:
     24        * UIProcess/API/Cocoa/APIAttachmentCocoa.mm:
     25        (API::Attachment::setFileWrapperAndUpdateContentType):
     26
     27        Add a helper that sets the file wrapper to the given NSFileWrapper, and either sets the content type to the
     28        given content type if it's specified, or infers it from the file extension of the new NSFileWrapper. Invoked
     29        whenever an NSFileWrapper and content type combination is set on an API attachment via WebKit SPI.
     30
     31        (API::Attachment::fileSizeForDisplay const):
     32
     33        Returns a file size to be displayed in the attachment element's subtitle. This returns an optional file size,
     34        where `std::nullopt` indicates that there should not be a file size shown. For now, this returns `std::nullopt`
     35        for directory file wrappers, though in the future, this should be done only in cases where we don't immediately
     36        have a size estimate for the file wrapper.
     37
     38        * UIProcess/API/Cocoa/WKWebView.mm:
     39        (-[WKWebView _insertAttachmentWithFileWrapper:contentType:options:completion:]):
     40
     41        Use API::Attachment::setFileWrapperAndUpdateContentType() instead of trying to come up with a fallback UTI.
     42
     43        * UIProcess/API/Cocoa/_WKAttachment.mm:
     44        (-[_WKAttachment setFileWrapper:contentType:completion:]):
     45
     46        Use API::Attachment::setFileWrapperAndUpdateContentType() instead of trying to come up with a fallback UTI.
     47
     48        * UIProcess/WebPageProxy.cpp:
     49        (WebKit::WebPageProxy::insertAttachment):
     50
     51        Remove the separate arguments for file size, content type, and file name, and instead get them from the given
     52        API Attachment object.
     53
     54        (WebKit::WebPageProxy::updateAttachmentAttributes):
     55
     56        Remove separate arguments for file size, content type and file name and just take an API::Attachment instead.
     57        These separate pieces of information can simply be asked from the Attachment itself.
     58
     59        * UIProcess/WebPageProxy.h:
     60        * WebProcess/WebPage/WebPage.cpp:
     61        (WebKit::WebPage::insertAttachment):
     62        (WebKit::WebPage::updateAttachmentAttributes):
     63
     64        Adjust some interfaces here to allow the displayed file size to be optional.
     65
     66        * WebProcess/WebPage/WebPage.h:
     67        * WebProcess/WebPage/WebPage.messages.in:
     68
    1692018-08-27  Alex Christensen  <achristensen@webkit.org>
    270
  • trunk/Source/WebKit/UIProcess/API/APIAttachment.cpp

    r235343 r235392  
    5858}
    5959
    60 void Attachment::updateAttributes(uint64_t fileSize, const WTF::String& newContentType, const WTF::String& newFilename, Function<void(WebKit::CallbackBase::Error)>&& callback)
     60void Attachment::updateAttributes(Function<void(WebKit::CallbackBase::Error)>&& callback)
    6161{
    62     setContentType(newContentType);
    63     setFilePath({ });
     62    if (!m_webPage) {
     63        callback(WebKit::CallbackBase::Error::OwnerWasInvalidated);
     64        return;
     65    }
    6466
    65     auto optionalNewContentType = newContentType.isNull() ? std::nullopt : std::optional<WTF::String> { newContentType };
    66     auto optionalNewFilename = newFilename.isNull() ? std::nullopt : std::optional<WTF::String> { newFilename };
    67     if (m_webPage)
    68         m_webPage->updateAttachmentAttributes(m_identifier, fileSize, WTFMove(optionalNewContentType), WTFMove(optionalNewFilename), WTFMove(callback));
    69     else
    70         callback(WebKit::CallbackBase::Error::OwnerWasInvalidated);
     67    m_webPage->updateAttachmentAttributes(*this, WTFMove(callback));
    7168}
    7269
     
    9491}
    9592
     93std::optional<uint64_t> Attachment::fileSizeForDisplay() const
     94{
     95    return std::nullopt;
     96}
     97
    9698#endif // !PLATFORM(COCOA)
    9799
  • trunk/Source/WebKit/UIProcess/API/APIAttachment.h

    r235343 r235392  
    5757    const WTF::String& identifier() const { return m_identifier; }
    5858    void setDisplayOptions(WebCore::AttachmentDisplayOptions, Function<void(WebKit::CallbackBase::Error)>&&);
    59     void updateAttributes(uint64_t fileSize, const WTF::String& newContentType, const WTF::String& newFilename, Function<void(WebKit::CallbackBase::Error)>&&);
     59    void updateAttributes(Function<void(WebKit::CallbackBase::Error)>&&);
    6060
    6161    void invalidate();
     
    6565    NSFileWrapper *fileWrapper() const { return m_fileWrapper.get(); }
    6666    void setFileWrapper(NSFileWrapper *fileWrapper) { m_fileWrapper = fileWrapper; }
     67    void setFileWrapperAndUpdateContentType(NSFileWrapper *, NSString *contentType);
    6768    WTF::String utiType() const;
    6869#endif
     
    7879    InsertionState insertionState() const { return m_insertionState; }
    7980    void setInsertionState(InsertionState state) { m_insertionState = state; }
     81
     82    std::optional<uint64_t> fileSizeForDisplay() const;
    8083
    8184private:
  • trunk/Source/WebKit/UIProcess/API/Cocoa/APIAttachmentCocoa.mm

    r235343 r235392  
    7575}
    7676
     77void Attachment::setFileWrapperAndUpdateContentType(NSFileWrapper *fileWrapper, NSString *contentType)
     78{
     79    if (!contentType.length) {
     80        if (fileWrapper.directory)
     81            contentType = (NSString *)kUTTypeDirectory;
     82        else if (fileWrapper.regularFile) {
     83            if (NSString *pathExtension = (fileWrapper.filename.length ? fileWrapper.filename : fileWrapper.preferredFilename).pathExtension)
     84                contentType = WebCore::MIMETypeRegistry::getMIMETypeForExtension(pathExtension);
     85            if (!contentType.length)
     86                contentType = (NSString *)kUTTypeData;
     87        }
     88    }
     89
     90    setContentType(contentType);
     91    setFileWrapper(fileWrapper);
     92}
     93
     94std::optional<uint64_t> Attachment::fileSizeForDisplay() const
     95{
     96    if (![m_fileWrapper isRegularFile]) {
     97        // FIXME: We should display a size estimate for directory-type file wrappers.
     98        return std::nullopt;
     99    }
     100
     101    if (auto fileSize = [[m_fileWrapper fileAttributes][NSFileSize] unsignedLongLongValue])
     102        return fileSize;
     103
     104    return [m_fileWrapper regularFileContents].length;
     105}
     106
    77107} // namespace API
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r235365 r235392  
    44554455    auto coreOptions = options ? options.coreDisplayOptions : WebCore::AttachmentDisplayOptions { };
    44564456    auto attachment = API::Attachment::create(identifier, *_page);
    4457     attachment->setFileWrapper(fileWrapper);
    4458 
    4459     if (!contentType.length) {
    4460         if (NSString *pathExtension = (fileWrapper.filename.length ? fileWrapper.filename : fileWrapper.preferredFilename).pathExtension)
    4461             contentType = WebCore::MIMETypeRegistry::getMIMETypeForExtension(pathExtension);
    4462     }
    4463 
    4464     auto fileSize = [[[fileWrapper fileAttributes] objectForKey:NSFileSize] unsignedLongLongValue];
    4465     if (!fileSize && fileWrapper.regularFile)
    4466         fileSize = fileWrapper.regularFileContents.length;
    4467 
    4468     _page->insertAttachment(attachment.copyRef(), coreOptions, fileSize, [fileWrapper preferredFilename], contentType.length ? std::optional<String> { contentType } : std::nullopt, [capturedHandler = makeBlockPtr(completionHandler)] (WebKit::CallbackBase::Error error) {
     4457    attachment->setFileWrapperAndUpdateContentType(fileWrapper, contentType);
     4458    _page->insertAttachment(attachment.copyRef(), coreOptions, [capturedHandler = makeBlockPtr(completionHandler)] (WebKit::CallbackBase::Error error) {
    44694459        if (capturedHandler)
    44704460            capturedHandler(error == WebKit::CallbackBase::Error::None);
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKAttachment.mm

    r235343 r235392  
    158158    }
    159159
    160     auto fileSize = [fileWrapper.fileAttributes[NSFileSize] unsignedLongLongValue];
    161     if (!fileSize && fileWrapper.regularFile)
    162         fileSize = fileWrapper.regularFileContents.length;
    163 
    164     if (!contentType.length) {
    165         if (NSString *pathExtension = (fileWrapper.filename.length ? fileWrapper.filename : fileWrapper.preferredFilename).pathExtension)
    166             contentType = WebCore::MIMETypeRegistry::getMIMETypeForExtension(pathExtension);
    167     }
    168 
    169     _attachment->setFileWrapper(fileWrapper);
    170     _attachment->updateAttributes(fileSize, contentType, fileWrapper.preferredFilename, [capturedBlock = makeBlockPtr(completionHandler)] (auto error) {
     160    // This file path member is only populated when the attachment is generated upon dropping files. When data is specified via NSFileWrapper
     161    // from the SPI client, the corresponding file path of the data is unknown, if it even exists at all.
     162    _attachment->setFilePath({ });
     163    _attachment->setFileWrapperAndUpdateContentType(fileWrapper, contentType);
     164    _attachment->updateAttributes([capturedBlock = makeBlockPtr(completionHandler)] (auto error) {
    171165        if (!capturedBlock)
    172166            return;
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r235365 r235392  
    77527752}
    77537753
    7754 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)
     7754void WebPageProxy::insertAttachment(Ref<API::Attachment>&& attachment, const AttachmentDisplayOptions& options, Function<void(CallbackBase::Error)>&& callback)
    77557755{
    77567756    if (!isValid()) {
     
    77597759    }
    77607760
    7761     if (contentType)
    7762         attachment->setContentType(*contentType);
    7763 
    77647761    auto attachmentIdentifier = attachment->identifier();
     7762    auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
     7763    m_process->send(Messages::WebPage::InsertAttachment(attachmentIdentifier, options, attachment->fileSizeForDisplay(), attachment->fileName(), attachment->contentType(), callbackID), m_pageID);
    77657764    m_attachmentIdentifierToAttachmentMap.set(attachmentIdentifier, WTFMove(attachment));
    7766 
    7767     auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
    7768     m_process->send(Messages::WebPage::InsertAttachment(attachmentIdentifier, options, fileSize, filename, contentType, callbackID), m_pageID);
    77697765}
    77707766
     
    77807776}
    77817777
    7782 void WebPageProxy::updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String>&& newContentType, std::optional<String>&& newFilename, Function<void(CallbackBase::Error)>&& callback)
     7778void WebPageProxy::updateAttachmentAttributes(const API::Attachment& attachment, Function<void(CallbackBase::Error)>&& callback)
    77837779{
    77847780    if (!isValid()) {
     
    77887784
    77897785    auto callbackID = m_callbacks.put(WTFMove(callback), m_process->throttler().backgroundActivityToken());
    7790     m_process->send(Messages::WebPage::UpdateAttachmentAttributes(identifier, fileSize, WTFMove(newContentType), WTFMove(newFilename), callbackID), m_pageID);
     7786    auto name = attachment.fileName();
     7787    auto optionalName = name.isNull() ? std::nullopt : std::optional<WTF::String> { name };
     7788    m_process->send(Messages::WebPage::UpdateAttachmentAttributes(attachment.identifier(), attachment.fileSizeForDisplay(), attachment.contentType(), WTFMove(optionalName), callbackID), m_pageID);
    77917789}
    77927790
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r235365 r235392  
    13201320#if ENABLE(ATTACHMENT_ELEMENT)
    13211321    RefPtr<API::Attachment> attachmentForIdentifier(const String& identifier) const;
    1322     void insertAttachment(Ref<API::Attachment>&&, const WebCore::AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String> contentType, Function<void(CallbackBase::Error)>&&);
     1322    void insertAttachment(Ref<API::Attachment>&&, const WebCore::AttachmentDisplayOptions&, Function<void(CallbackBase::Error)>&&);
    13231323    void setAttachmentDisplayOptions(const String& identifier, WebCore::AttachmentDisplayOptions, Function<void(CallbackBase::Error)>&&);
    1324     void updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String>&& newContentType, std::optional<String>&& newFilename, Function<void(CallbackBase::Error)>&&);
     1324    void updateAttachmentAttributes(const API::Attachment&, Function<void(CallbackBase::Error)>&&);
    13251325#endif
    13261326
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r235343 r235392  
    60676067#if ENABLE(ATTACHMENT_ELEMENT)
    60686068
    6069 void WebPage::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, uint64_t fileSize, const String& fileName, std::optional<String> contentType, CallbackID callbackID)
     6069void WebPage::insertAttachment(const String& identifier, const AttachmentDisplayOptions& options, std::optional<uint64_t>&& fileSize, const String& fileName, const String& contentType, CallbackID callbackID)
    60706070{
    60716071    auto& frame = m_page->focusController().focusedOrMainFrame();
    6072     frame.editor().insertAttachment(identifier, options, fileSize, fileName, WTFMove(contentType));
     6072    frame.editor().insertAttachment(identifier, options, WTFMove(fileSize), fileName, contentType);
    60736073    send(Messages::WebPageProxy::VoidCallback(callbackID));
    60746074}
     
    60796079}
    60806080
    6081 void WebPage::updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String> newContentType, std::optional<String> newFilename, CallbackID callbackID)
     6081void WebPage::updateAttachmentAttributes(const String& identifier, std::optional<uint64_t>&& fileSize, const String& contentType, std::optional<String>&& newFilename, CallbackID callbackID)
    60826082{
    60836083    if (auto attachment = attachmentElementWithIdentifier(identifier)) {
    60846084        attachment->document().updateLayout();
    6085         attachment->updateAttributes(fileSize, WTFMove(newContentType), WTFMove(newFilename));
     6085        attachment->updateAttributes(WTFMove(fileSize), contentType, WTFMove(newFilename));
    60866086    }
    60876087    send(Messages::WebPageProxy::VoidCallback(callbackID));
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r235137 r235392  
    10761076
    10771077#if ENABLE(ATTACHMENT_ELEMENT)
    1078     void insertAttachment(const String& identifier, const WebCore::AttachmentDisplayOptions&, uint64_t fileSize, const String& fileName, std::optional<String> contentType, CallbackID);
     1078    void insertAttachment(const String& identifier, const WebCore::AttachmentDisplayOptions&, std::optional<uint64_t>&& fileSize, const String& fileName, const String& contentType, CallbackID);
    10791079    void setAttachmentDisplayOptions(const String& identifier, const WebCore::AttachmentDisplayOptions&, CallbackID);
    1080     void updateAttachmentAttributes(const String& identifier, uint64_t fileSize, std::optional<String> newContentType, std::optional<String> newFilename, CallbackID);
     1080    void updateAttachmentAttributes(const String& identifier, std::optional<uint64_t>&& fileSize, const String& contentType, std::optional<String>&& newFilename, CallbackID);
    10811081#endif
    10821082
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r235137 r235392  
    511511
    512512#if ENABLE(ATTACHMENT_ELEMENT)
    513     InsertAttachment(String identifier, struct WebCore::AttachmentDisplayOptions options, uint64_t fileSize, String fileName, std::optional<String> contentType, WebKit::CallbackID callbackID)
     513    InsertAttachment(String identifier, struct WebCore::AttachmentDisplayOptions options, std::optional<uint64_t> fileSize, String fileName, String contentType, WebKit::CallbackID callbackID)
    514514    SetAttachmentDisplayOptions(String identifier, struct WebCore::AttachmentDisplayOptions options, WebKit::CallbackID callbackID)
    515     UpdateAttachmentAttributes(String identifier, uint64_t fileSize, std::optional<String> newContentType, std::optional<String> newFilename, WebKit::CallbackID callbackID)
     515    UpdateAttachmentAttributes(String identifier, std::optional<uint64_t> fileSize, String newContentType, std::optional<String> newFilename, WebKit::CallbackID callbackID)
    516516#endif
    517517
  • trunk/Tools/ChangeLog

    r235391 r235392  
     12018-08-27  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Cocoa] Exception (fileType 'dyn.agq8u' is not a valid UTI) raised when dragging an attachment whose file wrapper is a directory
     4        https://bugs.webkit.org/show_bug.cgi?id=188903
     5        <rdar://problem/43702993>
     6
     7        Reviewed by Tim Horton.
     8
     9        Add two API tests and adjust existing WKAttachment API tests. The new tests exercise the following scenarios, in
     10        both iOS and macOS:
     11        •       Dropping a folder as an attachment element, and then moving that attachment element in the document by
     12                dragging and dropping.
     13        •       Using WKWebView SPI to insert a folder and a file with an unknown extension, and then using more
     14                _WKAttachment SPI to swap the attachments' backing file wrappers.
     15
     16        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
     17        (runTestWithTemporaryFolder):
     18
     19        Add a helper function to run a test with a new folder path, created in the temporary directory and populated
     20        with some sample content. This folder is deleted after running the test.
     21
     22        (simulateFolderDragWithURL):
     23
     24        Add a helper function to prepare a given DragAndDropSimulator for simulating a dragged folder from a source
     25        external to the web view.
     26
     27        (platformCopyRichTextWithMultipleAttachments):
     28        (platformCopyRichTextWithImage):
     29        (platformCopyPNG):
     30        (TestWebKitAPI::TEST):
     31
     32        Add new API tests, and adjust existing tests to reflect new -setFileWrapper:…: behavior. Specifically,
     33        ChangeAttachmentDataAndFileInformation previously required that changing a _WKAttachment's NSFileWrapper would
     34        preserve the previous NSFileWrapper's preferred name if the new file wrapper does not have a preferred name, but
     35        this quirk is no longer supported.
     36
     37        Also add a few bridging casts for the eventual transition of TestWebKitAPI to ARC.
     38
     39        * TestWebKitAPI/cocoa/DragAndDropSimulator.h:
     40
     41        Add a new hook to clear any external drag information on an existing DragAndDropSimulator. This is convenient
     42        when using the same DragAndDropSimulator to perform multiple drags in a single test.
     43
     44        * TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm:
     45        (-[DragAndDropSimulator clearExternalDragInformation]):
     46        * TestWebKitAPI/mac/DragAndDropSimulatorMac.mm:
     47        (-[DragAndDropSimulator clearExternalDragInformation]):
     48
    1492018-08-27  Alex Christensen  <achristensen@webkit.org>
    250
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm

    r235375 r235392  
    409409@end
    410410
     411static void runTestWithTemporaryFolder(void(^runTest)(NSURL *folderURL))
     412{
     413    NSFileManager *defaultManager = [NSFileManager defaultManager];
     414    auto temporaryFolder = retainPtr([NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"folder-%@", NSUUID.UUID]] isDirectory:YES]);
     415    [defaultManager removeItemAtURL:temporaryFolder.get() error:nil];
     416    [defaultManager createDirectoryAtURL:temporaryFolder.get() withIntermediateDirectories:NO attributes:nil error:nil];
     417    [testImageData() writeToURL:[temporaryFolder.get() URLByAppendingPathComponent:@"image.png" isDirectory:NO] atomically:YES];
     418    [testZIPData() writeToURL:[temporaryFolder.get() URLByAppendingPathComponent:@"archive.zip" isDirectory:NO] atomically:YES];
     419    @try {
     420        runTest(temporaryFolder.get());
     421    } @finally {
     422        [[NSFileManager defaultManager] removeItemAtURL:temporaryFolder.get() error:nil];
     423    }
     424}
     425
     426static void simulateFolderDragWithURL(DragAndDropSimulator *simulator, NSURL *folderURL)
     427{
     428#if PLATFORM(MAC)
     429    [simulator writePromisedFiles:@[ folderURL ]];
     430#else
     431    auto folderProvider = adoptNS([[NSItemProvider alloc] init]);
     432    [folderProvider setSuggestedName:folderURL.lastPathComponent];
     433    [folderProvider setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
     434    [folderProvider registerFileRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypeFolder fileOptions:0 visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[&] (void(^completion)(NSURL *, BOOL, NSError *)) -> NSProgress * {
     435        completion(folderURL, NO, nil);
     436        return nil;
     437    }];
     438    simulator.externalItemProviders = @[ folderProvider.get() ];
     439#endif
     440}
     441
    411442#pragma mark - Platform testing helper functions
    412443
     
    469500void platformCopyRichTextWithMultipleAttachments()
    470501{
    471     auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(NSString *)kUTTypePNG]);
    472     auto pdf = adoptNS([[NSTextAttachment alloc] initWithData:testPDFData() ofType:(NSString *)kUTTypePDF]);
    473     auto zip = adoptNS([[NSTextAttachment alloc] initWithData:testZIPData() ofType:(NSString *)kUTTypeZipArchive]);
     502    auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(__bridge NSString *)kUTTypePNG]);
     503    auto pdf = adoptNS([[NSTextAttachment alloc] initWithData:testPDFData() ofType:(__bridge NSString *)kUTTypePDF]);
     504    auto zip = adoptNS([[NSTextAttachment alloc] initWithData:testZIPData() ofType:(__bridge NSString *)kUTTypeZipArchive]);
    474505
    475506    auto richText = adoptNS([[NSMutableAttributedString alloc] init]);
     
    492523{
    493524    auto richText = adoptNS([[NSMutableAttributedString alloc] init]);
    494     auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(NSString *)kUTTypePNG]);
     525    auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(__bridge NSString *)kUTTypePNG]);
    495526
    496527    [richText appendAttributedString:[[[NSAttributedString alloc] initWithString:@"Lorem ipsum "] autorelease]];
     
    519550    auto item = adoptNS([[UIItemProvider alloc] init]);
    520551    [item setPreferredPresentationStyle:UIPreferredPresentationStyleAttachment];
    521     [item registerData:testImageData() type:(NSString *)kUTTypePNG];
     552    [item registerData:testImageData() type:(__bridge NSString *)kUTTypePNG];
    522553    pasteboard.itemProviders = @[ item.get() ];
    523554#endif
     
    642673        ObserveAttachmentUpdatesForScope observer(webView.get());
    643674        attachment = [webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:testHTMLData()];
    644         observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
     675        observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]);
    645676    }
    646677    [webView expectUpdatesAfterCommand:@"InsertText" withArgument:@"World" expectedRemovals:@[] expectedInsertions:@[]];
     
    666697        ObserveAttachmentUpdatesForScope observer(webView.get());
    667698        attachment = [webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:testHTMLData()];
    668         observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
     699        observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]);
    669700    }
    670701    [webView expectUpdatesAfterCommand:@"InsertOrderedList" withArgument:nil expectedRemovals:@[] expectedInsertions:@[]];
     
    687718        [webView _synchronouslyExecuteEditCommand:@"InsertHTML" argument:@"<div><strong><attachment src='cid:123-4567' title='a'></attachment></strong></div>"];
    688719        attachment = observer.observer().inserted[0];
    689         observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
     720        observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]);
    690721        observer.expectSourceForIdentifier(@"cid:123-4567", [attachment uniqueIdentifier]);
    691722    }
     
    698729        [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').remove()"];
    699730        [webView waitForNextPresentationUpdate];
    700         observer.expectAttachmentUpdates(@[attachment.get()], @[ ]);
     731        observer.expectAttachmentUpdates(@[ attachment.get() ], @[ ]);
    701732    }
    702733    [attachment expectRequestedDataToBe:nil];
     
    710741        ObserveAttachmentUpdatesForScope observer(webView.get());
    711742        attachment = [webView synchronouslyInsertAttachmentWithFilename:@"foo.txt" contentType:@"text/plain" data:testHTMLData()];
    712         observer.expectAttachmentUpdates(@[], @[attachment.get()]);
     743        observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]);
    713744    }
    714745    [attachment expectRequestedDataToBe:testHTMLData()];
     
    718749        ObserveAttachmentUpdatesForScope observer(webView.get());
    719750        [webView _synchronouslyExecuteEditCommand:@"Cut" argument:nil];
    720         observer.expectAttachmentUpdates(@[attachment.get()], @[]);
     751        observer.expectAttachmentUpdates(@[ attachment.get() ], @[ ]);
    721752    }
    722753    [attachment expectRequestedDataToBe:testHTMLData()];
     
    724755        ObserveAttachmentUpdatesForScope observer(webView.get());
    725756        [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil];
    726         observer.expectAttachmentUpdates(@[], @[attachment.get()]);
     757        observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]);
    727758    }
    728759    [attachment expectRequestedDataToBe:testHTMLData()];
     
    739770        ObserveAttachmentUpdatesForScope observer(webView.get());
    740771        attachment = [webView synchronouslyInsertAttachmentWithFilename:@"empty.txt" contentType:@"text/plain" data:[NSData data]];
    741         observer.expectAttachmentUpdates(@[], @[attachment.get()]);
     772        observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]);
    742773    }
    743774    [attachment expectRequestedDataToBe:[NSData data]];
     
    746777        ObserveAttachmentUpdatesForScope scope(webView.get());
    747778        [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
    748         scope.expectAttachmentUpdates(@[attachment.get()], @[]);
     779        scope.expectAttachmentUpdates(@[ attachment.get() ], @[ ]);
    749780    }
    750781    [attachment expectRequestedDataToBe:[NSData data]];
     782}
     783
     784TEST(WKAttachmentTests, DropFolderAsAttachmentAndMoveByDragging)
     785{
     786    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     787    [configuration _setAttachmentElementEnabled:YES];
     788
     789    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:NSMakeRect(0, 0, 400, 400) configuration:configuration.get()]);
     790    [[simulator webView] synchronouslyLoadHTMLString:attachmentEditingTestMarkup];
     791
     792    runTestWithTemporaryFolder([simulator] (NSURL *folderURL) {
     793        simulateFolderDragWithURL(simulator.get(), folderURL);
     794        [simulator runFrom:CGPointMake(0, 0) to:CGPointMake(50, 50)];
     795
     796        TestWKWebView *webView = [simulator webView];
     797        auto attachment = retainPtr([simulator insertedAttachments].firstObject);
     798        EXPECT_WK_STREQ([attachment uniqueIdentifier], [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').uniqueIdentifier"]);
     799        EXPECT_WK_STREQ((__bridge NSString *)kUTTypeDirectory, [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
     800        EXPECT_WK_STREQ(folderURL.lastPathComponent, [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
     801
     802        NSFileWrapper *image = [attachment info].fileWrapper.fileWrappers[@"image.png"];
     803        NSFileWrapper *archive = [attachment info].fileWrapper.fileWrappers[@"archive.zip"];
     804        EXPECT_TRUE([image.regularFileContents isEqualToData:testImageData()]);
     805        EXPECT_TRUE([archive.regularFileContents isEqualToData:testZIPData()]);
     806
     807        [webView evaluateJavaScript:@"getSelection().collapseToEnd()" completionHandler:nil];
     808        [webView _executeEditCommand:@"InsertParagraph" argument:nil completion:nil];
     809        [webView _executeEditCommand:@"InsertHTML" argument:@"<em>foo</em>" completion:nil];
     810        [webView _executeEditCommand:@"InsertParagraph" argument:nil completion:nil];
     811
     812        [webView expectElementTag:@"ATTACHMENT" toComeBefore:@"EM"];
     813        [simulator clearExternalDragInformation];
     814        [simulator runFrom:webView.attachmentElementMidPoint to:CGPointMake(300, 300)];
     815        [webView expectElementTag:@"EM" toComeBefore:@"ATTACHMENT"];
     816    });
     817}
     818
     819TEST(WKAttachmentTests, InsertFolderAndFileWithUnknownExtension)
     820{
     821    auto webView = webViewForTestingAttachments();
     822    auto file = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testHTMLData()]);
     823    [file setPreferredFilename:@"test.foobar"];
     824    auto image = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testImageData()]);
     825    auto document = adoptNS([[NSFileWrapper alloc] initRegularFileWithContents:testPDFData()]);
     826    auto folder = adoptNS([[NSFileWrapper alloc] initDirectoryWithFileWrappers:@{ @"image.png": image.get(), @"document.pdf": document.get() }]);
     827    [folder setPreferredFilename:@"folder"];
     828
     829    RetainPtr<_WKAttachment> firstAttachment;
     830    RetainPtr<_WKAttachment> secondAttachment;
     831    {
     832        ObserveAttachmentUpdatesForScope observer(webView.get());
     833        firstAttachment = [webView synchronouslyInsertAttachmentWithFileWrapper:file.get() contentType:nil];
     834        observer.expectAttachmentUpdates(@[ ], @[ firstAttachment.get() ]);
     835    }
     836    {
     837        ObserveAttachmentUpdatesForScope observer(webView.get());
     838        secondAttachment = [webView synchronouslyInsertAttachmentWithFileWrapper:folder.get() contentType:nil];
     839        observer.expectAttachmentUpdates(@[ ], @[ secondAttachment.get() ]);
     840    }
     841
     842    auto checkAttachmentConsistency = [webView, file, folder] (_WKAttachment *expectedFileAttachment, _WKAttachment *expectedFolderAttachment) {
     843        [webView expectElementCount:2 tagName:@"ATTACHMENT"];
     844        EXPECT_TRUE(UTTypeConformsTo((__bridge CFStringRef)[webView valueOfAttribute:@"type" forQuerySelector:@"attachment[title=folder]"], kUTTypeDirectory));
     845        EXPECT_TRUE(UTTypeConformsTo((__bridge CFStringRef)[webView valueOfAttribute:@"type" forQuerySelector:@"attachment[title^=test]"], kUTTypeData));
     846        EXPECT_WK_STREQ(expectedFileAttachment.uniqueIdentifier, [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment[title^=test]').uniqueIdentifier"]);
     847        EXPECT_WK_STREQ(expectedFolderAttachment.uniqueIdentifier, [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment[title=folder]').uniqueIdentifier"]);
     848        EXPECT_TRUE([expectedFileAttachment.info.fileWrapper isEqual:file.get()]);
     849        EXPECT_TRUE([expectedFolderAttachment.info.fileWrapper isEqual:folder.get()]);
     850    };
     851
     852    checkAttachmentConsistency(firstAttachment.get(), secondAttachment.get());
     853
     854    {
     855        // Swap the two attachments' file wrappers without creating or destroying attachment elements.
     856        ObserveAttachmentUpdatesForScope observer(webView.get());
     857        [firstAttachment synchronouslySetFileWrapper:folder.get() newContentType:nil error:nil];
     858        [secondAttachment synchronouslySetFileWrapper:file.get() newContentType:nil error:nil];
     859        observer.expectAttachmentUpdates(@[ ], @[ ]);
     860    }
     861
     862    checkAttachmentConsistency(secondAttachment.get(), firstAttachment.get());
    751863}
    752864
     
    762874        EXPECT_WK_STREQ(@"test.pdf", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
    763875        EXPECT_WK_STREQ(@"application/pdf", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
    764         observer.expectAttachmentUpdates(@[], @[attachment.get()]);
     876        observer.expectAttachmentUpdates(@[ ], @[attachment.get()]);
    765877    }
    766878    {
     
    771883        EXPECT_WK_STREQ(@"icon.png", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
    772884        EXPECT_WK_STREQ(@"image/png", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
    773         observer.expectAttachmentUpdates(@[], @[]);
    774     }
    775     {
    776         RetainPtr<NSData> textData = testHTMLData();
     885        observer.expectAttachmentUpdates(@[ ], @[ ]);
     886    }
     887    {
     888        RetainPtr<NSData> textData = [@"Hello world" dataUsingEncoding:NSUTF8StringEncoding];
    777889        ObserveAttachmentUpdatesForScope observer(webView.get());
    778890        // The new content type should be inferred from the file name.
     
    781893        EXPECT_WK_STREQ(@"foo.txt", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
    782894        EXPECT_WK_STREQ(@"text/plain", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
    783         observer.expectAttachmentUpdates(@[], @[]);
    784     }
    785     {
    786         RetainPtr<NSData> secondTextData = [@"Hello world" dataUsingEncoding:NSUTF8StringEncoding];
    787         ObserveAttachmentUpdatesForScope observer(webView.get());
    788         // Both the previous file name and type should be inferred.
    789         [attachment synchronouslySetData:secondTextData.get() newContentType:nil newFilename:nil error:nil];
    790         [attachment expectRequestedDataToBe:secondTextData.get()];
    791         EXPECT_WK_STREQ(@"foo.txt", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
    792         EXPECT_WK_STREQ(@"text/plain", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
    793         observer.expectAttachmentUpdates(@[], @[]);
    794     }
    795     [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[]];
     895        observer.expectAttachmentUpdates(@[ ], @[ ]);
     896    }
     897    {
     898        RetainPtr<NSData> htmlData = testHTMLData();
     899        ObserveAttachmentUpdatesForScope observer(webView.get());
     900        [attachment synchronouslySetData:htmlData.get() newContentType:@"text/html" newFilename:@"bar" error:nil];
     901        [attachment expectRequestedDataToBe:htmlData.get()];
     902        EXPECT_WK_STREQ(@"bar", [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
     903        EXPECT_WK_STREQ(@"text/html", [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
     904        observer.expectAttachmentUpdates(@[ ], @[ ]);
     905    }
     906    [webView expectUpdatesAfterCommand:@"DeleteBackward" withArgument:nil expectedRemovals:@[attachment.get()] expectedInsertions:@[ ]];
    796907}
    797908
     
    9041015        [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil];
    9051016        [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
    906         observer.expectAttachmentUpdates(@[attachment.get()], @[]);
     1017        observer.expectAttachmentUpdates(@[ attachment.get() ], @[ ]);
    9071018    }
    9081019}
     
    9901101        originalAttachment = [webView synchronouslyInsertAttachmentWithFileWrapper:fileWrapper.get() contentType:@"text/plain"];
    9911102        EXPECT_EQ(0U, observer.observer().removed.count);
    992         observer.expectAttachmentUpdates(@[], @[originalAttachment.get()]);
     1103        observer.expectAttachmentUpdates(@[ ], @[ originalAttachment.get() ]);
    9931104    }
    9941105    [webView selectAll:nil];
     
    10061117        ObserveAttachmentUpdatesForScope observer(webView.get());
    10071118        [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
    1008         observer.expectAttachmentUpdates(@[pastedAttachment.get()], @[]);
     1119        observer.expectAttachmentUpdates(@[ pastedAttachment.get() ], @[ ]);
    10091120        [originalAttachment expectRequestedDataToBe:data.get()];
    10101121    }
     
    10121123        ObserveAttachmentUpdatesForScope observer(webView.get());
    10131124        [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
    1014         observer.expectAttachmentUpdates(@[originalAttachment.get()], @[]);
     1125        observer.expectAttachmentUpdates(@[ originalAttachment.get() ], @[ ]);
    10151126    }
    10161127
     
    10311142        originalAttachment = [webView synchronouslyInsertAttachmentWithFileWrapper:fileWrapper.get() contentType:@"text/plain"];
    10321143        EXPECT_EQ(0U, observer.observer().removed.count);
    1033         observer.expectAttachmentUpdates(@[], @[originalAttachment.get()]);
     1144        observer.expectAttachmentUpdates(@[ ], @[ originalAttachment.get() ]);
    10341145    }
    10351146    [webView selectAll:nil];
     
    12201331    auto pngResource = adoptNS([[WebResource alloc] initWithData:testImageData() URL:[NSURL URLWithString:@"1.png"] MIMEType:@"image/png" textEncodingName:nil frameName:nil]);
    12211332    auto gifResource = adoptNS([[WebResource alloc] initWithData:testGIFData() URL:[NSURL URLWithString:@"2.gif"] MIMEType:@"image/gif" textEncodingName:nil frameName:nil]);
    1222     auto archive = adoptNS([[WebArchive alloc] initWithMainResource:(__bridge WebResource *)mainResource.get() subresources:@[ (__bridge WebResource *)pngResource.get(), (__bridge WebResource *)gifResource.get() ] subframeArchives:@[ ]]);
     1333    auto archive = adoptNS([[WebArchive alloc] initWithMainResource:mainResource.get() subresources:@[ pngResource.get(), gifResource.get() ] subframeArchives:@[ ]]);
    12231334
    12241335#if PLATFORM(MAC)
     
    12351346    auto webView = webViewForTestingAttachments();
    12361347
    1237     ObserveAttachmentUpdatesForScope observer((__bridge TestWKWebView *)webView.get());
     1348    ObserveAttachmentUpdatesForScope observer(webView.get());
    12381349    [webView _synchronouslyExecuteEditCommand:@"Paste" argument:nil];
    12391350    [webView expectElementCount:2 tagName:@"IMG"];
     
    12501361    [pngAttachment expectRequestedDataToBe:testImageData()];
    12511362    [gifAttachment expectRequestedDataToBe:testGIFData()];
    1252     observer.expectAttachmentUpdates(@[ ], @[ (__bridge _WKAttachment *)pngAttachment.get(), (__bridge _WKAttachment *)gifAttachment.get() ]);
     1363    observer.expectAttachmentUpdates(@[ ], @[ pngAttachment.get(), gifAttachment.get() ]);
    12531364}
    12541365
     
    13641475    auto dragAndDropSimulator = adoptNS([[DragAndDropSimulator alloc] initWithWebView:webView.get()]);
    13651476    auto item = adoptNS([[NSItemProvider alloc] init]);
    1366     [item registerData:testImageData() type:(NSString *)kUTTypePNG];
     1477    [item registerData:testImageData() type:(__bridge NSString *)kUTTypePNG];
    13671478    [dragAndDropSimulator setExternalItemProviders:@[ item.get() ]];
    13681479    [dragAndDropSimulator runFrom:CGPointZero to:CGPointMake(50, 50)];
     
    13781489        [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil];
    13791490        [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
    1380         observer.expectAttachmentUpdates(@[attachment.get()], @[]);
     1491        observer.expectAttachmentUpdates(@[ attachment.get() ], @[ ]);
    13811492    }
    13821493}
     
    13861497    auto webView = webViewForTestingAttachments();
    13871498    auto dragAndDropSimulator = adoptNS([[DragAndDropSimulator alloc] initWithWebView:webView.get()]);
    1388     auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(NSString *)kUTTypePNG]);
     1499    auto image = adoptNS([[NSTextAttachment alloc] initWithData:testImageData() ofType:(__bridge NSString *)kUTTypePNG]);
    13891500    auto item = adoptNS([[NSItemProvider alloc] init]);
    13901501    [item registerObject:[NSAttributedString attributedStringWithAttachment:image.get()] visibility:NSItemProviderRepresentationVisibilityAll];
     
    14061517        [webView _synchronouslyExecuteEditCommand:@"SelectAll" argument:nil];
    14071518        [webView _synchronouslyExecuteEditCommand:@"DeleteBackward" argument:nil];
    1408         observer.expectAttachmentUpdates(@[attachment.get()], @[]);
     1519        observer.expectAttachmentUpdates(@[ attachment.get() ], @[ ]);
    14091520    }
    14101521}
     
    14521563    auto item = adoptNS([[NSItemProvider alloc] init]);
    14531564    NSData *data = testZIPData();
    1454     [item registerData:data type:(NSString *)kUTTypeZipArchive];
     1565    [item registerData:data type:(__bridge NSString *)kUTTypeZipArchive];
    14551566    [item setSuggestedName:@"archive.zip"];
    14561567
     
    14821593
    14831594    auto secondAttachmentItem = adoptNS([[NSItemProvider alloc] init]);
    1484     [secondAttachmentItem registerData:testPDFData() type:(NSString *)kUTTypePDF];
     1595    [secondAttachmentItem registerData:testPDFData() type:(__bridge NSString *)kUTTypePDF];
    14851596    [secondAttachmentItem setSuggestedName:@"second.pdf"];
    14861597
     
    15091620    auto item = adoptNS([[NSItemProvider alloc] init]);
    15101621    auto data = retainPtr(testPDFData());
    1511     [item registerData:data.get() type:(NSString *)kUTTypePDF];
     1622    [item registerData:data.get() type:(__bridge NSString *)kUTTypePDF];
    15121623    [item setSuggestedName:@"document.pdf"];
    15131624
     
    15321643    NSItemProvider *itemProvider = [dragAndDropSimulator sourceItemProviders].firstObject;
    15331644    EXPECT_EQ(UIPreferredPresentationStyleAttachment, itemProvider.preferredPresentationStyle);
    1534     [itemProvider expectType:(NSString *)kUTTypePDF withData:data.get()];
     1645    [itemProvider expectType:(__bridge NSString *)kUTTypePDF withData:data.get()];
    15351646    EXPECT_WK_STREQ("document.pdf", [itemProvider suggestedName]);
    15361647    [dragAndDropSimulator endDataTransfer];
     
    15451656        ObserveAttachmentUpdatesForScope observer(webView.get());
    15461657        attachment = [webView synchronouslyInsertAttachmentWithFilename:@"document.pdf" contentType:@"application/pdf" data:data.get()];
    1547         observer.expectAttachmentUpdates(@[], @[attachment.get()]);
     1658        observer.expectAttachmentUpdates(@[ ], @[ attachment.get() ]);
    15481659    }
    15491660
     
    15611672    NSItemProvider *itemProvider = [dragAndDropSimulator sourceItemProviders].firstObject;
    15621673    EXPECT_EQ(UIPreferredPresentationStyleAttachment, itemProvider.preferredPresentationStyle);
    1563     [itemProvider expectType:(NSString *)kUTTypePDF withData:data.get()];
     1674    [itemProvider expectType:(__bridge NSString *)kUTTypePDF withData:data.get()];
    15641675    EXPECT_WK_STREQ("document.pdf", [itemProvider suggestedName]);
    15651676    [dragAndDropSimulator endDataTransfer];
  • trunk/Tools/TestWebKitAPI/cocoa/DragAndDropSimulator.h

    r235202 r235392  
    8181- (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation;
    8282- (void)endDataTransfer;
     83- (void)clearExternalDragInformation;
    8384@property (nonatomic, readonly) NSArray<_WKAttachment *> *insertedAttachments;
    8485@property (nonatomic, readonly) NSArray<_WKAttachment *> *removedAttachments;
  • trunk/Tools/TestWebKitAPI/ios/DragAndDropSimulatorIOS.mm

    r235137 r235392  
    569569}
    570570
     571- (void)clearExternalDragInformation
     572{
     573    _externalItemProviders = nil;
     574}
     575
    571576- (CGPoint)_currentLocation
    572577{
  • trunk/Tools/TestWebKitAPI/mac/DragAndDropSimulatorMac.mm

    r235343 r235392  
    359359}
    360360
     361- (void)clearExternalDragInformation
     362{
     363    _externalPromisedFiles = nil;
     364    _externalDragImage = nil;
     365    _externalDragPasteboard = nil;
     366}
     367
    361368static BOOL getFilePathsAndTypeIdentifiers(NSArray<NSURL *> *fileURLs, NSArray<NSString *> **outFilePaths, NSArray<NSString *> **outTypeIdentifiers)
    362369{
Note: See TracChangeset for help on using the changeset viewer.