Title: [238661] trunk
Revision
238661
Author
wenson_hs...@apple.com
Date
2018-11-28 21:25:07 -0800 (Wed, 28 Nov 2018)

Log Message

[iOSMac] Dropping text selections from web content into editable elements crashes the web process
https://bugs.webkit.org/show_bug.cgi?id=192113
<rdar://problem/46323701>

Reviewed by Ryosuke Niwa.

Source/WebCore:

In iOSMac, registering invalid UTIs on NSItemProvider when starting a drag or handling a drop does not work.
Since iOS writes and reads only "Apple Web Archive pasteboard type" (a.k.a. `WebArchivePboardType`) during drag
and drop as well as copy and paste, we fail to read or write any web archive data, and subsequently fall back to
reading RTF or flat RTFD, both of which are not supported in iOSMac, since UIFoundation links against the
system's macOS WebKit stack.

To fix this, we add support for reading and writing com.apple.webarchive (`kUTTypeWebArchive`) on iOS, so that
WebKit-based iOSMac applications can understand web archive data from the host running macOS, and the host can
also understand web archive data written by the iOSMac app. Additionally, don't allow reading RTF and flat RTFD
as web content in iOSMac. (Note that writing RTF and flat RTFD is still safe, since it does not depend on
UIFoundation.framework but rather `WebCore::HTMLConverter`).

Test: DragAndDropTests.ModernWebArchiveType

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

Additionally make sure that we never call into UIFoundation's NSAttributedString to markup conversion codepath
by making `createFragment` an empty stub on iOSMac.

* platform/ios/PasteboardIOS.mm:
(WebCore::supportedImageTypes):
(WebCore::isTypeAllowedByReadingPolicy):
(WebCore::Pasteboard::readPasteboardWebContentDataForType):
(WebCore::Pasteboard::supportedWebContentPasteboardTypes):
* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::PlatformPasteboard::write):

Tools:

Add a test to verify that, when dropping an item with both "com.apple.webarchive" and "public.utf8-plain-text"
representations, the higher fidelity web archive data is used when handling the drop.

* TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (238660 => 238661)


--- trunk/Source/WebCore/ChangeLog	2018-11-29 04:39:45 UTC (rev 238660)
+++ trunk/Source/WebCore/ChangeLog	2018-11-29 05:25:07 UTC (rev 238661)
@@ -1,3 +1,39 @@
+2018-11-28  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOSMac] Dropping text selections from web content into editable elements crashes the web process
+        https://bugs.webkit.org/show_bug.cgi?id=192113
+        <rdar://problem/46323701>
+
+        Reviewed by Ryosuke Niwa.
+
+        In iOSMac, registering invalid UTIs on NSItemProvider when starting a drag or handling a drop does not work.
+        Since iOS writes and reads only "Apple Web Archive pasteboard type" (a.k.a. `WebArchivePboardType`) during drag
+        and drop as well as copy and paste, we fail to read or write any web archive data, and subsequently fall back to
+        reading RTF or flat RTFD, both of which are not supported in iOSMac, since UIFoundation links against the
+        system's macOS WebKit stack.
+
+        To fix this, we add support for reading and writing com.apple.webarchive (`kUTTypeWebArchive`) on iOS, so that
+        WebKit-based iOSMac applications can understand web archive data from the host running macOS, and the host can
+        also understand web archive data written by the iOSMac app. Additionally, don't allow reading RTF and flat RTFD
+        as web content in iOSMac. (Note that writing RTF and flat RTFD is still safe, since it does not depend on
+        UIFoundation.framework but rather `WebCore::HTMLConverter`).
+
+        Test: DragAndDropTests.ModernWebArchiveType
+
+        * editing/cocoa/WebContentReaderCocoa.mm:
+        (WebCore::createFragment):
+
+        Additionally make sure that we never call into UIFoundation's NSAttributedString to markup conversion codepath
+        by making `createFragment` an empty stub on iOSMac.
+
+        * platform/ios/PasteboardIOS.mm:
+        (WebCore::supportedImageTypes):
+        (WebCore::isTypeAllowedByReadingPolicy):
+        (WebCore::Pasteboard::readPasteboardWebContentDataForType):
+        (WebCore::Pasteboard::supportedWebContentPasteboardTypes):
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::PlatformPasteboard::write):
+
 2018-11-28  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, rolling out r238653 and r238656.

Modified: trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm (238660 => 238661)


--- trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-11-29 04:39:45 UTC (rev 238660)
+++ trunk/Source/WebCore/editing/cocoa/WebContentReaderCocoa.mm	2018-11-29 05:25:07 UTC (rev 238661)
@@ -85,8 +85,15 @@
 
 namespace WebCore {
 
-#if (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300)
+#if PLATFORM(IOSMAC)
 
+static FragmentAndResources createFragment(Frame&, NSAttributedString *)
+{
+    return { };
+}
+
+#elif (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300)
+
 static NSDictionary *attributesForAttributedStringConversion()
 {
     // This function needs to be kept in sync with identically named one in WebKitLegacy, which is used on older OS versions.

Modified: trunk/Source/WebCore/platform/ios/PasteboardIOS.mm (238660 => 238661)


--- trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-11-29 04:39:45 UTC (rev 238660)
+++ trunk/Source/WebCore/platform/ios/PasteboardIOS.mm	2018-11-29 05:25:07 UTC (rev 238661)
@@ -168,7 +168,7 @@
 
 static NSArray* supportedImageTypes()
 {
-    return @[(id)kUTTypePNG, (id)kUTTypeTIFF, (id)kUTTypeJPEG, (id)kUTTypeGIF];
+    return @[(__bridge NSString *)kUTTypePNG, (__bridge NSString *)kUTTypeTIFF, (__bridge NSString *)kUTTypeJPEG, (__bridge NSString *)kUTTypeGIF];
 }
 
 static bool isTypeAllowedByReadingPolicy(NSString *type, WebContentReadingPolicy policy)
@@ -175,21 +175,22 @@
 {
     return policy == WebContentReadingPolicy::AnyType
         || [type isEqualToString:WebArchivePboardType]
-        || [type isEqualToString:(NSString *)kUTTypeHTML]
-        || [type isEqualToString:(NSString *)kUTTypeRTF]
-        || [type isEqualToString:(NSString *)kUTTypeFlatRTFD];
+        || [type isEqualToString:(__bridge NSString *)kUTTypeWebArchive]
+        || [type isEqualToString:(__bridge NSString *)kUTTypeHTML]
+        || [type isEqualToString:(__bridge NSString *)kUTTypeRTF]
+        || [type isEqualToString:(__bridge NSString *)kUTTypeFlatRTFD];
 }
 
 Pasteboard::ReaderResult Pasteboard::readPasteboardWebContentDataForType(PasteboardWebContentReader& reader, PasteboardStrategy& strategy, NSString *type, int itemIndex)
 {
-    if ([type isEqualToString:WebArchivePboardType]) {
-        auto buffer = strategy.readBufferFromPasteboard(itemIndex, WebArchivePboardType, m_pasteboardName);
+    if ([type isEqualToString:WebArchivePboardType] || [type isEqualToString:(__bridge NSString *)kUTTypeWebArchive]) {
+        auto buffer = strategy.readBufferFromPasteboard(itemIndex, type, m_pasteboardName);
         if (m_changeCount != changeCount())
             return ReaderResult::PasteboardWasChangedExternally;
         return buffer && reader.readWebArchive(*buffer) ? ReaderResult::ReadType : ReaderResult::DidNotReadType;
     }
 
-    if ([type isEqualToString:(NSString *)kUTTypeHTML]) {
+    if ([type isEqualToString:(__bridge NSString *)kUTTypeHTML]) {
         String htmlString = strategy.readStringFromPasteboard(itemIndex, kUTTypeHTML, m_pasteboardName);
         if (m_changeCount != changeCount())
             return ReaderResult::PasteboardWasChangedExternally;
@@ -196,7 +197,8 @@
         return !htmlString.isNull() && reader.readHTML(htmlString) ? ReaderResult::ReadType : ReaderResult::DidNotReadType;
     }
 
-    if ([type isEqualToString:(NSString *)kUTTypeFlatRTFD]) {
+#if !PLATFORM(IOSMAC)
+    if ([type isEqualToString:(__bridge NSString *)kUTTypeFlatRTFD]) {
         RefPtr<SharedBuffer> buffer = strategy.readBufferFromPasteboard(itemIndex, kUTTypeFlatRTFD, m_pasteboardName);
         if (m_changeCount != changeCount())
             return ReaderResult::PasteboardWasChangedExternally;
@@ -203,12 +205,13 @@
         return buffer && reader.readRTFD(*buffer) ? ReaderResult::ReadType : ReaderResult::DidNotReadType;
     }
 
-    if ([type isEqualToString:(NSString *)kUTTypeRTF]) {
+    if ([type isEqualToString:(__bridge NSString *)kUTTypeRTF]) {
         RefPtr<SharedBuffer> buffer = strategy.readBufferFromPasteboard(itemIndex, kUTTypeRTF, m_pasteboardName);
         if (m_changeCount != changeCount())
             return ReaderResult::PasteboardWasChangedExternally;
         return buffer && reader.readRTF(*buffer) ? ReaderResult::ReadType : ReaderResult::DidNotReadType;
     }
+#endif // !PLATFORM(IOSMAC)
 
     if ([supportedImageTypes() containsObject:type]) {
         RefPtr<SharedBuffer> buffer = strategy.readBufferFromPasteboard(itemIndex, type, m_pasteboardName);
@@ -217,7 +220,7 @@
         return buffer && reader.readImage(buffer.releaseNonNull(), type) ? ReaderResult::ReadType : ReaderResult::DidNotReadType;
     }
 
-    if ([type isEqualToString:(NSString *)kUTTypeURL]) {
+    if ([type isEqualToString:(__bridge NSString *)kUTTypeURL]) {
         String title;
         URL url = "" m_pasteboardName, title);
         if (m_changeCount != changeCount())
@@ -225,7 +228,7 @@
         return !url.isNull() && reader.readURL(url, title) ? ReaderResult::ReadType : ReaderResult::DidNotReadType;
     }
 
-    if (UTTypeConformsTo((CFStringRef)type, kUTTypePlainText)) {
+    if (UTTypeConformsTo((__bridge CFStringRef)type, kUTTypePlainText)) {
         String string = strategy.readStringFromPasteboard(itemIndex, kUTTypePlainText, m_pasteboardName);
         if (m_changeCount != changeCount())
             return ReaderResult::PasteboardWasChangedExternally;
@@ -232,7 +235,7 @@
         return !string.isNull() && reader.readPlainText(string) ? ReaderResult::ReadType : ReaderResult::DidNotReadType;
     }
 
-    if (UTTypeConformsTo((CFStringRef)type, kUTTypeText)) {
+    if (UTTypeConformsTo((__bridge CFStringRef)type, kUTTypeText)) {
         String string = strategy.readStringFromPasteboard(itemIndex, kUTTypeText, m_pasteboardName);
         if (m_changeCount != changeCount())
             return ReaderResult::PasteboardWasChangedExternally;
@@ -321,7 +324,23 @@
 
 NSArray *Pasteboard::supportedWebContentPasteboardTypes()
 {
-    return @[(id)WebArchivePboardType, (id)kUTTypeFlatRTFD, (id)kUTTypeRTF, (id)kUTTypeHTML, (id)kUTTypePNG, (id)kUTTypeTIFF, (id)kUTTypeJPEG, (id)kUTTypeGIF, (id)kUTTypeURL, (id)kUTTypeText];
+    return @[
+#if !PLATFORM(IOSMAC)
+        WebArchivePboardType,
+#endif
+        (__bridge NSString *)kUTTypeWebArchive,
+#if !PLATFORM(IOSMAC)
+        (__bridge NSString *)kUTTypeFlatRTFD,
+        (__bridge NSString *)kUTTypeRTF,
+#endif
+        (__bridge NSString *)kUTTypeHTML,
+        (__bridge NSString *)kUTTypePNG,
+        (__bridge NSString *)kUTTypeTIFF,
+        (__bridge NSString *)kUTTypeJPEG,
+        (__bridge NSString *)kUTTypeGIF,
+        (__bridge NSString *)kUTTypeURL,
+        (__bridge NSString *)kUTTypeText
+    ];
 }
 
 NSArray *Pasteboard::supportedFileUploadPasteboardTypes()

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (238660 => 238661)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2018-11-29 04:39:45 UTC (rev 238660)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2018-11-29 05:25:07 UTC (rev 238661)
@@ -350,14 +350,21 @@
 {
     auto representationsToRegister = adoptNS([[WebItemProviderRegistrationInfoList alloc] init]);
 
+#if !PLATFORM(IOSMAC)
     [representationsToRegister addData:[webIOSPastePboardType dataUsingEncoding:NSUTF8StringEncoding] forType:webIOSPastePboardType];
+#endif
 
     ASSERT(content.clientTypes.size() == content.clientData.size());
     for (size_t i = 0, size = content.clientTypes.size(); i < size; ++i)
         [representationsToRegister addData:content.clientData[i]->createNSData().get() forType:content.clientTypes[i]];
 
-    if (content.dataInWebArchiveFormat)
-        [representationsToRegister addData:content.dataInWebArchiveFormat->createNSData().get() forType:WebArchivePboardType];
+    if (content.dataInWebArchiveFormat) {
+        auto webArchiveData = content.dataInWebArchiveFormat->createNSData();
+#if !PLATFORM(IOSMAC)
+        [representationsToRegister addData:webArchiveData.get() forType:WebArchivePboardType];
+#endif
+        [representationsToRegister addData:webArchiveData.get() forType:(__bridge NSString *)kUTTypeWebArchive];
+    }
 
     if (content.dataInAttributedStringFormat) {
         NSAttributedString *attributedString = unarchivedObjectOfClassesFromData([NSSet setWithObject:[NSAttributedString class]], content.dataInAttributedStringFormat->createNSData().get());

Modified: trunk/Tools/ChangeLog (238660 => 238661)


--- trunk/Tools/ChangeLog	2018-11-29 04:39:45 UTC (rev 238660)
+++ trunk/Tools/ChangeLog	2018-11-29 05:25:07 UTC (rev 238661)
@@ -1,3 +1,16 @@
+2018-11-28  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOSMac] Dropping text selections from web content into editable elements crashes the web process
+        https://bugs.webkit.org/show_bug.cgi?id=192113
+        <rdar://problem/46323701>
+
+        Reviewed by Ryosuke Niwa.
+
+        Add a test to verify that, when dropping an item with both "com.apple.webarchive" and "public.utf8-plain-text"
+        representations, the higher fidelity web archive data is used when handling the drop.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm:
+
 2018-11-28  Aakash Jain  <aakash_j...@apple.com>
 
         [ews-app] Fetch bugs from Bugzilla and submit to Buildbot

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm (238660 => 238661)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm	2018-11-29 04:39:45 UTC (rev 238660)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/DragAndDropTests.mm	2018-11-29 05:25:07 UTC (rev 238661)
@@ -25,12 +25,52 @@
 
 #import "config.h"
 
+#if WK_API_ENABLED && ENABLE(DRAG_SUPPORT)
+
 #import "DragAndDropSimulator.h"
 #import "PlatformUtilities.h"
 #import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WebArchive.h>
 
-#if WK_API_ENABLED && ENABLE(DRAG_SUPPORT)
+#if PLATFORM(IOS_FAMILY)
+#import <MobileCoreServices/MobileCoreServices.h>
+#endif
 
+TEST(DragAndDropTests, ModernWebArchiveType)
+{
+    NSData *markupData = [@"<strong><i>Hello world</i></strong>" dataUsingEncoding:NSUTF8StringEncoding];
+    auto mainResource = adoptNS([[WebResource alloc] initWithData:markupData URL:[NSURL URLWithString:@"foo.html"] MIMEType:@"text/html" textEncodingName:@"utf-8" frameName:nil]);
+    auto archive = adoptNS([[WebArchive alloc] initWithMainResource:mainResource.get() subresources:@[ ] subframeArchives:@[ ]]);
+    NSString *webArchiveType = (__bridge NSString *)kUTTypeWebArchive;
+
+    auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 320, 500)]);
+    auto webView = [simulator webView];
+    [webView synchronouslyLoadHTMLString:@"<meta name='viewport' content='width=device-width'><body style='width: 100%; height: 100%;' contenteditable>"];
+#if PLATFORM(MAC)
+    NSPasteboard *pasteboard = [NSPasteboard pasteboardWithUniqueName];
+    [pasteboard declareTypes:@[webArchiveType, (__bridge NSString *)kUTTypeUTF8PlainText] owner:nil];
+    [pasteboard setData:[archive data] forType:webArchiveType];
+    [pasteboard setData:[@"Hello world" dataUsingEncoding:NSUTF8StringEncoding] forType:(__bridge NSString *)kUTTypeUTF8PlainText];
+    [simulator setExternalDragPasteboard:pasteboard];
+#else
+    auto item = adoptNS([[NSItemProvider alloc] init]);
+    [item registerDataRepresentationForTypeIdentifier:webArchiveType visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[&] (void (^completionHandler)(NSData *, NSError *)) -> NSProgress * {
+        completionHandler([archive data], nil);
+        return nil;
+    }];
+    [item registerDataRepresentationForTypeIdentifier:(__bridge NSString *)kUTTypeUTF8PlainText visibility:NSItemProviderRepresentationVisibilityAll loadHandler:[&] (void (^completionHandler)(NSData *, NSError *)) -> NSProgress * {
+        completionHandler([@"Hello world" dataUsingEncoding:NSUTF8StringEncoding], nil);
+        return nil;
+    }];
+    [simulator setExternalItemProviders:@[ item.get() ]];
+#endif
+    [simulator runFrom:CGPointMake(0, 0) to:CGPointMake(50, 50)];
+    [webView stringByEvaluatingJavaScript:@"document.body.focus(); getSelection().setBaseAndExtent(document.body, 0, document.body, 1)"];
+    EXPECT_WK_STREQ("Hello world", [webView stringByEvaluatingJavaScript:@"document.body.textContent"]);
+    EXPECT_TRUE([webView stringByEvaluatingJavaScript:@"document.queryCommandState('bold')"].boolValue);
+    EXPECT_TRUE([webView stringByEvaluatingJavaScript:@"document.queryCommandState('italic')"].boolValue);
+}
+
 TEST(DragAndDropTests, DragImageLocationForLinkInSubframe)
 {
     auto simulator = adoptNS([[DragAndDropSimulator alloc] initWithWebViewFrame:CGRectMake(0, 0, 400, 400)]);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to