⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 245839 in webkit


Ignore:
Timestamp:
May 28, 2019, 7:56:09 PM (7 years ago)
Author:
Wenson Hsieh
Message:

[iOS] Respect NSItemProvider's registered types when dropping files that are loaded in-place
https://bugs.webkit.org/show_bug.cgi?id=198315
<rdar://problem/51183762>

Reviewed by Tim Horton.

Source/WebCore:

Currently, logic in PasteboardIOS.mm and WebContentReaderCocoa.mm attempts to deduce the content type from the
file path when dropping attachments on iOS. Instead, we should be plumbing the content type through to the
reader.

Test: WKAttachmentTestsIOS.InsertDroppedImageWithNonImageFileExtension

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

(WebCore::typeForAttachmentElement):

Add a helper method to determine which type to use in attachment elements. This makes the paste
(attachmentForData) and drop (attachmentForFilePaths) behave the same way, with respect to the type attribute
used to represent the attachment.

(WebCore::attachmentForFilePath):

Use the content type, if specified; otherwise, fall back to deducing it from the file path.

(WebCore::attachmentForData):
(WebCore::WebContentReader::readFilePath):

  • platform/Pasteboard.h:

(WebCore::PasteboardWebContentReader::readFilePath):

Pass the highest fidelity representation's content type to the web content reader.

  • platform/ios/PasteboardIOS.mm:

(WebCore::Pasteboard::readRespectingUTIFidelities):

Tools:

Adds a new API test to verify that when dropping a file that is loaded in-place with a file extension that is
not a .png (but was registered to the item provider as "public.png"), the resulting attachment is contained in
an image element, and the resulting attachment info indicates that the dropped attachment is a png file.

Additionally, rebaseline some existing tests.

  • TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:

(runTestWithTemporaryImageFile):
(TestWebKitAPI::TEST):

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r245838 r245839  
     12019-05-28  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Respect NSItemProvider's registered types when dropping files that are loaded in-place
     4        https://bugs.webkit.org/show_bug.cgi?id=198315
     5        <rdar://problem/51183762>
     6
     7        Reviewed by Tim Horton.
     8
     9        Currently, logic in PasteboardIOS.mm and WebContentReaderCocoa.mm attempts to deduce the content type from the
     10        file path when dropping attachments on iOS. Instead, we should be plumbing the content type through to the
     11        reader.
     12
     13        Test: WKAttachmentTestsIOS.InsertDroppedImageWithNonImageFileExtension
     14
     15        * editing/WebContentReader.h:
     16        * editing/cocoa/WebContentReaderCocoa.mm:
     17        (WebCore::typeForAttachmentElement):
     18
     19        Add a helper method to determine which type to use in attachment elements. This makes the paste
     20        (attachmentForData) and drop (attachmentForFilePaths) behave the same way, with respect to the type attribute
     21        used to represent the attachment.
     22
     23        (WebCore::attachmentForFilePath):
     24
     25        Use the content type, if specified; otherwise, fall back to deducing it from the file path.
     26
     27        (WebCore::attachmentForData):
     28        (WebCore::WebContentReader::readFilePath):
     29        * platform/Pasteboard.h:
     30        (WebCore::PasteboardWebContentReader::readFilePath):
     31
     32        Pass the highest fidelity representation's content type to the web content reader.
     33
     34        * platform/ios/PasteboardIOS.mm:
     35        (WebCore::Pasteboard::readRespectingUTIFidelities):
     36
    1372019-05-28  Myles C. Maxfield  <mmaxfield@apple.com>
    238
  • trunk/Source/WebCore/editing/WebContentReader.h

    r245775 r245839  
    7272#if PLATFORM(COCOA)
    7373    bool readWebArchive(SharedBuffer&) override;
    74     bool readFilePath(const String&, Optional<FloatSize> preferredPresentationSize = { }) override;
     74    bool readFilePath(const String&, Optional<FloatSize> preferredPresentationSize = { }, const String& contentType = { }) override;
    7575    bool readFilePaths(const Vector<String>&) override;
    7676    bool readHTML(const String&) override;
     
    9696#if PLATFORM(COCOA)
    9797    bool readWebArchive(SharedBuffer&) override;
    98     bool readFilePath(const String&, Optional<FloatSize> = { }) override { return false; }
     98    bool readFilePath(const String&, Optional<FloatSize> = { }, const String& = { }) override { return false; }
    9999    bool readFilePaths(const Vector<String>&) override { return false; }
    100100    bool readHTML(const String&) override;
  • trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm

    r245775 r245839  
    696696#if ENABLE(ATTACHMENT_ELEMENT)
    697697
    698 static Ref<HTMLElement> attachmentForFilePath(Frame& frame, const String& path, Optional<FloatSize> preferredSize)
     698static String typeForAttachmentElement(const String& contentType)
     699{
     700    if (contentType.isEmpty())
     701        return { };
     702
     703    auto mimeType = mimeTypeFromContentType(contentType);
     704    return mimeType.isEmpty() ? contentType : mimeType;
     705}
     706
     707static Ref<HTMLElement> attachmentForFilePath(Frame& frame, const String& path, Optional<FloatSize> preferredSize, const String& explicitContentType)
    699708{
    700709    auto document = makeRef(*frame.document());
     
    705714    }
    706715
    707     String contentType;
     716    bool isDirectory = FileSystem::fileIsDirectory(path, FileSystem::ShouldFollowSymbolicLinks::Yes);
     717    String contentType = typeForAttachmentElement(explicitContentType);
     718    if (contentType.isEmpty()) {
     719        if (isDirectory)
     720            contentType = kUTTypeDirectory;
     721        else {
     722            contentType = File::contentTypeForFile(path);
     723            if (contentType.isEmpty())
     724                contentType = kUTTypeData;
     725        }
     726    }
     727
    708728    Optional<uint64_t> fileSizeForDisplay;
    709     if (FileSystem::fileIsDirectory(path, FileSystem::ShouldFollowSymbolicLinks::Yes))
    710         contentType = kUTTypeDirectory;
    711     else {
     729    if (!isDirectory) {
    712730        long long fileSize;
    713731        FileSystem::getFileSize(path, fileSize);
    714732        fileSizeForDisplay = fileSize;
    715         contentType = File::contentTypeForFile(path);
    716         if (contentType.isEmpty())
    717             contentType = kUTTypeData;
    718733    }
    719734
     
    739754    auto document = makeRef(*frame.document());
    740755    auto attachment = HTMLAttachmentElement::create(HTMLNames::attachmentTag, document);
    741     auto mimeType = mimeTypeFromContentType(contentType);
    742     auto typeForAttachmentElement = mimeType.isEmpty() ? contentType : mimeType;
     756    auto attachmentType = typeForAttachmentElement(contentType);
    743757
    744758    // FIXME: We should instead ask CoreServices for a preferred name corresponding to the given content type.
     
    752766
    753767    if (!supportsClientSideAttachmentData(frame)) {
    754         attachment->setFile(File::create(Blob::create(buffer, WTFMove(typeForAttachmentElement)), fileName));
     768        attachment->setFile(File::create(Blob::create(buffer, WTFMove(attachmentType)), fileName));
    755769        return attachment;
    756770    }
    757771
    758     frame.editor().registerAttachmentIdentifier(attachment->ensureUniqueIdentifier(), typeForAttachmentElement, fileName, buffer);
    759 
    760     if (contentTypeIsSuitableForInlineImageRepresentation(typeForAttachmentElement)) {
     772    frame.editor().registerAttachmentIdentifier(attachment->ensureUniqueIdentifier(), attachmentType, fileName, buffer);
     773
     774    if (contentTypeIsSuitableForInlineImageRepresentation(attachmentType)) {
    761775        auto image = HTMLImageElement::create(document);
    762         image->setAttributeWithoutSynchronization(HTMLNames::srcAttr, DOMURL::createObjectURL(document, File::create(Blob::create(buffer, WTFMove(typeForAttachmentElement)), WTFMove(fileName))));
     776        image->setAttributeWithoutSynchronization(HTMLNames::srcAttr, DOMURL::createObjectURL(document, File::create(Blob::create(buffer, WTFMove(attachmentType)), WTFMove(fileName))));
    763777        image->setAttachmentElement(WTFMove(attachment));
    764778        if (preferredSize) {
     
    769783    }
    770784
    771     attachment->updateAttributes({ buffer.size() }, WTFMove(typeForAttachmentElement), WTFMove(fileName));
     785    attachment->updateAttributes({ buffer.size() }, WTFMove(attachmentType), WTFMove(fileName));
    772786    return attachment;
    773787}
     
    775789#endif // ENABLE(ATTACHMENT_ELEMENT)
    776790
    777 bool WebContentReader::readFilePath(const String& path, Optional<FloatSize> preferredPresentationSize)
     791bool WebContentReader::readFilePath(const String& path, Optional<FloatSize> preferredPresentationSize, const String& contentType)
    778792{
    779793    if (path.isEmpty() || !frame.document())
     
    786800#if ENABLE(ATTACHMENT_ELEMENT)
    787801    if (RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled())
    788         fragment->appendChild(attachmentForFilePath(frame, path, preferredPresentationSize));
     802        fragment->appendChild(attachmentForFilePath(frame, path, preferredPresentationSize, contentType));
    789803#endif
    790804
  • trunk/Source/WebCore/platform/Pasteboard.h

    r245775 r245839  
    137137#if PLATFORM(COCOA)
    138138    virtual bool readWebArchive(SharedBuffer&) = 0;
    139     virtual bool readFilePath(const String&, Optional<FloatSize> preferredPresentationSize = { }) = 0;
     139    virtual bool readFilePath(const String&, Optional<FloatSize> preferredPresentationSize = { }, const String& contentType = { }) = 0;
    140140    virtual bool readFilePaths(const Vector<String>&) = 0;
    141141    virtual bool readHTML(const String&) = 0;
  • trunk/Source/WebCore/platform/ios/PasteboardIOS.mm

    r245775 r245839  
    346346        auto attachmentFilePath = info.pathForHighestFidelityItem();
    347347        bool canReadAttachment = policy == WebContentReadingPolicy::AnyType && RuntimeEnabledFeatures::sharedFeatures().attachmentElementEnabled() && !attachmentFilePath.isEmpty();
     348        auto contentType = info.contentTypeForHighestFidelityItem();
    348349        if (canReadAttachment && prefersAttachmentRepresentation(info)) {
    349             readURLAlongsideAttachmentIfNecessary(reader, strategy, info.contentTypeForHighestFidelityItem(), m_pasteboardName, index);
    350             reader.readFilePath(WTFMove(attachmentFilePath), info.preferredPresentationSize);
     350            readURLAlongsideAttachmentIfNecessary(reader, strategy, contentType, m_pasteboardName, index);
     351            reader.readFilePath(WTFMove(attachmentFilePath), info.preferredPresentationSize, contentType);
    351352            continue;
    352353        }
     
    367368#if ENABLE(ATTACHMENT_ELEMENT)
    368369        if (canReadAttachment && result == ReaderResult::DidNotReadType)
    369             reader.readFilePath(WTFMove(attachmentFilePath), info.preferredPresentationSize);
     370            reader.readFilePath(WTFMove(attachmentFilePath), info.preferredPresentationSize, contentType);
    370371#endif
    371372    }
  • trunk/Tools/ChangeLog

    r245836 r245839  
     12019-05-28  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] Respect NSItemProvider's registered types when dropping files that are loaded in-place
     4        https://bugs.webkit.org/show_bug.cgi?id=198315
     5        <rdar://problem/51183762>
     6
     7        Reviewed by Tim Horton.
     8
     9        Adds a new API test to verify that when dropping a file that is loaded in-place with a file extension that is
     10        not a .png (but was registered to the item provider as "public.png"), the resulting attachment is contained in
     11        an image element, and the resulting attachment info indicates that the dropped attachment is a png file.
     12
     13        Additionally, rebaseline some existing tests.
     14
     15        * TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm:
     16        (runTestWithTemporaryImageFile):
     17        (TestWebKitAPI::TEST):
     18
    1192019-05-28  Yusuke Suzuki  <ysuzuki@apple.com>
    220
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKAttachmentTests.mm

    r245775 r245839  
    411411}
    412412
     413#if PLATFORM(IOS_FAMILY)
     414
     415static void runTestWithTemporaryImageFile(NSString *fileName, void(^runTest)(NSURL *fileURL))
     416{
     417    NSFileManager *defaultManager = [NSFileManager defaultManager];
     418    auto temporaryFilePath = retainPtr([NSTemporaryDirectory() stringByAppendingPathComponent:fileName]);
     419    auto temporaryFileURL = retainPtr([NSURL fileURLWithPath:temporaryFilePath.get()]);
     420    [defaultManager removeItemAtURL:temporaryFileURL.get() error:nil];
     421    [testImageData() writeToFile:temporaryFilePath.get() atomically:YES];
     422    @try {
     423        runTest(temporaryFileURL.get());
     424    } @finally {
     425        [defaultManager removeItemAtURL:temporaryFileURL.get() error:nil];
     426    }
     427}
     428
     429#endif // PLATFORM(IOS_FAMILY)
     430
    413431static void simulateFolderDragWithURL(DragAndDropSimulator *simulator, NSURL *folderURL)
    414432{
     
    789807        TestWKWebView *webView = [simulator webView];
    790808        auto attachment = retainPtr([simulator insertedAttachments].firstObject);
     809#if PLATFORM(IOS_FAMILY)
     810        NSString *expectedType = (__bridge NSString *)kUTTypeFolder;
     811#else
     812        NSString *expectedType = (__bridge NSString *)kUTTypeDirectory;
     813#endif
    791814        EXPECT_WK_STREQ([attachment uniqueIdentifier], [webView stringByEvaluatingJavaScript:@"document.querySelector('attachment').uniqueIdentifier"]);
    792         EXPECT_WK_STREQ((__bridge NSString *)kUTTypeDirectory, [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
     815        EXPECT_WK_STREQ(expectedType, [webView valueOfAttribute:@"type" forQuerySelector:@"attachment"]);
    793816        EXPECT_WK_STREQ(folderURL.lastPathComponent, [webView valueOfAttribute:@"title" forQuerySelector:@"attachment"]);
    794817
     
    17051728    [webView expectElementCount:2 querySelector:@"ATTACHMENT"];
    17061729    EXPECT_WK_STREQ("hello.rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]);
    1707     EXPECT_WK_STREQ("text/rtf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
     1730    EXPECT_WK_STREQ((__bridge NSString *)kUTTypeFlatRTFD, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
    17081731    EXPECT_WK_STREQ("world.txt", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]);
    1709     EXPECT_WK_STREQ("text/plain", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]);
     1732    EXPECT_WK_STREQ((__bridge NSString *)kUTTypeUTF8PlainText, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('type')"]);
    17101733}
    17111734
     
    17641787
    17651788    EXPECT_WK_STREQ("first.txt", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('title')"]);
    1766     EXPECT_WK_STREQ("text/plain", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
     1789    EXPECT_WK_STREQ((__bridge NSString *)kUTTypeUTF8PlainText, [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[0].getAttribute('type')"]);
    17671790    EXPECT_WK_STREQ([appleURL absoluteString], [webView valueOfAttribute:@"href" forQuerySelector:@"a"]);
    17681791    EXPECT_WK_STREQ("second.pdf", [webView stringByEvaluatingJavaScript:@"document.querySelectorAll('attachment')[1].getAttribute('title')"]);
     
    19671990}
    19681991
     1992TEST(WKAttachmentTestsIOS, InsertDroppedImageWithNonImageFileExtension)
     1993{
     1994    runTestWithTemporaryImageFile(@"image.hello", ^(NSURL *fileURL) {
     1995        auto item = adoptNS([[NSItemProvider alloc] init]);
     1996        [item setSuggestedName:@"image.hello"];
     1997        [item registerFileRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypePNG fileOptions:NSItemProviderFileOptionOpenInPlace visibility:NSItemProviderRepresentationVisibilityAll loadHandler:^NSProgress *(void (^callback)(NSURL *, BOOL, NSError *))
     1998        {
     1999            callback(fileURL, YES, nil);
     2000            return nil;
     2001        }];
     2002
     2003        auto webView = webViewForTestingAttachments();
     2004        auto dragAndDropSimulator = adoptNS([[DragAndDropSimulator alloc] initWithWebView:webView.get()]);
     2005        [dragAndDropSimulator setExternalItemProviders:@[ item.get() ]];
     2006        [dragAndDropSimulator runFrom:CGPointZero to:CGPointMake(50, 50)];
     2007
     2008        EXPECT_EQ(1U, [dragAndDropSimulator insertedAttachments].count);
     2009        _WKAttachment *attachment = [dragAndDropSimulator insertedAttachments].firstObject;
     2010        _WKAttachmentInfo *info = attachment.info;
     2011        EXPECT_WK_STREQ("image/png", info.contentType);
     2012        EXPECT_WK_STREQ("image.hello", info.filePath.lastPathComponent);
     2013        EXPECT_WK_STREQ("image.hello", info.name);
     2014        [webView expectElementCount:1 querySelector:@"IMG"];
     2015    });
     2016}
     2017
    19692018#if HAVE(PENCILKIT)
    19702019static BOOL forEachViewInHierarchy(UIView *view, void(^mapFunction)(UIView *subview, BOOL *stop))
Note: See TracChangeset for help on using the changeset viewer.