Title: [218125] trunk
Revision
218125
Author
wenson_hs...@apple.com
Date
2017-06-12 12:34:37 -0700 (Mon, 12 Jun 2017)

Log Message

WebItemProviderPasteboard should call its completion block immediately after a synchronous load
https://bugs.webkit.org/show_bug.cgi?id=173225
<rdar://problem/32713144>

Reviewed by Tim Horton.

Source/WebCore:

Ensures that a completion block passed to doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout: will be
invoked immediately, if a synchronous timeout is specified and loading finishes before the synchronous timeout
is reached. To do this, we first factor out the completion logic into a new block. If the synchronous timeout
exists and dispatch_group_wait returns 0 (indicating that the dispatch group finished without hitting the
wait timeout) we simply invoke the block and return early; otherwise, we will register the completion block
using dispatch_group_notify.

Test: DataInteractionTests.WebItemProviderPasteboardLoading

* platform/ios/WebItemProviderPasteboard.mm:
(-[WebItemProviderPasteboard doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout:]):

Tools:

Adds a new unit test to verify whether the completion block is called synchronously or asynchronously, in both
cases where the synchronous timeout is very large, and the synchronous timeout is not used (0).

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (218124 => 218125)


--- trunk/Source/WebCore/ChangeLog	2017-06-12 19:19:38 UTC (rev 218124)
+++ trunk/Source/WebCore/ChangeLog	2017-06-12 19:34:37 UTC (rev 218125)
@@ -1,3 +1,23 @@
+2017-06-12  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        WebItemProviderPasteboard should call its completion block immediately after a synchronous load
+        https://bugs.webkit.org/show_bug.cgi?id=173225
+        <rdar://problem/32713144>
+
+        Reviewed by Tim Horton.
+
+        Ensures that a completion block passed to doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout: will be
+        invoked immediately, if a synchronous timeout is specified and loading finishes before the synchronous timeout
+        is reached. To do this, we first factor out the completion logic into a new block. If the synchronous timeout
+        exists and dispatch_group_wait returns 0 (indicating that the dispatch group finished without hitting the
+        wait timeout) we simply invoke the block and return early; otherwise, we will register the completion block
+        using dispatch_group_notify.
+
+        Test: DataInteractionTests.WebItemProviderPasteboardLoading
+
+        * platform/ios/WebItemProviderPasteboard.mm:
+        (-[WebItemProviderPasteboard doAfterLoadingProvidedContentIntoFileURLs:synchronousTimeout:]):
+
 2017-06-12  Jeremy Jones  <jere...@apple.com>
 
         WebAVPlayerController minTime and maxTime should be calculated properties to provide correct values when streaming.

Modified: trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm (218124 => 218125)


--- trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm	2017-06-12 19:19:38 UTC (rev 218124)
+++ trunk/Source/WebCore/platform/ios/WebItemProviderPasteboard.mm	2017-06-12 19:34:37 UTC (rev 218125)
@@ -484,15 +484,19 @@
     }
 
     RetainPtr<WebItemProviderPasteboard> retainedSelf = self;
-    dispatch_group_notify(fileLoadingGroup.get(), dispatch_get_main_queue(), [retainedSelf, fileLoadingGroup, typeToFileURLMaps, completionBlock = makeBlockPtr(action), changeCountBeforeLoading] {
+    auto itemLoadCompletion = [retainedSelf, synchronousFileLoadingGroup, fileLoadingGroup, typeToFileURLMaps, completionBlock = makeBlockPtr(action), changeCountBeforeLoading] {
         if (changeCountBeforeLoading == retainedSelf->_changeCount)
             retainedSelf->_typeToFileURLMaps = typeToFileURLMaps;
 
         completionBlock([retainedSelf fileURLsForDataInteraction]);
-    });
+    };
 
-    if (synchronousTimeout > 0)
-        dispatch_group_wait(synchronousFileLoadingGroup.get(), dispatch_time(DISPATCH_TIME_NOW, synchronousTimeout * NSEC_PER_SEC));
+    if (synchronousTimeout > 0 && !dispatch_group_wait(synchronousFileLoadingGroup.get(), dispatch_time(DISPATCH_TIME_NOW, synchronousTimeout * NSEC_PER_SEC))) {
+        itemLoadCompletion();
+        return;
+    }
+
+    dispatch_group_notify(fileLoadingGroup.get(), dispatch_get_main_queue(), itemLoadCompletion);
 }
 
 - (WebItemProviderRegistrationInfoList *)registrationInfoAtIndex:(NSUInteger)index

Modified: trunk/Tools/ChangeLog (218124 => 218125)


--- trunk/Tools/ChangeLog	2017-06-12 19:19:38 UTC (rev 218124)
+++ trunk/Tools/ChangeLog	2017-06-12 19:34:37 UTC (rev 218125)
@@ -1,3 +1,17 @@
+2017-06-12  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        WebItemProviderPasteboard should call its completion block immediately after a synchronous load
+        https://bugs.webkit.org/show_bug.cgi?id=173225
+        <rdar://problem/32713144>
+
+        Reviewed by Tim Horton.
+
+        Adds a new unit test to verify whether the completion block is called synchronously or asynchronously, in both
+        cases where the synchronous timeout is very large, and the synchronous timeout is not used (0).
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (TestWebKitAPI::TEST):
+
 2017-06-12  Jonathan Bedard  <jbed...@apple.com>
 
         Return correct process names for iOS on-device testing

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (218124 => 218125)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-06-12 19:19:38 UTC (rev 218124)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-06-12 19:34:37 UTC (rev 218125)
@@ -39,6 +39,7 @@
 #import <WebKit/WKPreferencesPrivate.h>
 #import <WebKit/WKProcessPoolPrivate.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WebItemProviderPasteboard.h>
 #import <WebKit/_WKProcessPoolConfiguration.h>
 
 typedef void (^FileLoadCompletionBlock)(NSURL *, BOOL, NSError *);
@@ -848,6 +849,52 @@
     [webView _simulatePrepareForDataInteractionSession:nil completion:^() { }];
 }
 
+TEST(DataInteractionTests, WebItemProviderPasteboardLoading)
+{
+    static NSString *fastString = @"This data loads quickly";
+    static NSString *slowString = @"This data loads slowly";
+
+    WebItemProviderPasteboard *pasteboard = [WebItemProviderPasteboard sharedInstance];
+    auto fastItem = adoptNS([[UIItemProvider alloc] init]);
+    [fastItem registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeUTF8PlainText options:nil loadHandler:^NSProgress *(UIItemProviderDataLoadCompletionBlock completionBlock)
+    {
+        completionBlock([fastString dataUsingEncoding:NSUTF8StringEncoding], nil);
+        return nil;
+    }];
+
+    auto slowItem = adoptNS([[UIItemProvider alloc] init]);
+    [slowItem registerDataRepresentationForTypeIdentifier:(NSString *)kUTTypeUTF8PlainText options:nil loadHandler:^NSProgress *(UIItemProviderDataLoadCompletionBlock completionBlock)
+    {
+        sleep(2);
+        completionBlock([slowString dataUsingEncoding:NSUTF8StringEncoding], nil);
+        return nil;
+    }];
+
+    __block bool hasRunFirstCompletionBlock = false;
+    pasteboard.itemProviders = @[ fastItem.get(), slowItem.get() ];
+    [pasteboard doAfterLoadingProvidedContentIntoFileURLs:^(NSArray<NSURL *> *urls) {
+        EXPECT_EQ(2UL, urls.count);
+        auto firstString = adoptNS([[NSString alloc] initWithContentsOfURL:urls[0] encoding:NSUTF8StringEncoding error:nil]);
+        auto secondString = adoptNS([[NSString alloc] initWithContentsOfURL:urls[1] encoding:NSUTF8StringEncoding error:nil]);
+        EXPECT_WK_STREQ(fastString, [firstString UTF8String]);
+        EXPECT_WK_STREQ(slowString, [secondString UTF8String]);
+        hasRunFirstCompletionBlock = true;
+    } synchronousTimeout:600];
+    EXPECT_TRUE(hasRunFirstCompletionBlock);
+
+    __block bool hasRunSecondCompletionBlock = false;
+    [pasteboard doAfterLoadingProvidedContentIntoFileURLs:^(NSArray<NSURL *> *urls) {
+        EXPECT_EQ(2UL, urls.count);
+        auto firstString = adoptNS([[NSString alloc] initWithContentsOfURL:urls[0] encoding:NSUTF8StringEncoding error:nil]);
+        auto secondString = adoptNS([[NSString alloc] initWithContentsOfURL:urls[1] encoding:NSUTF8StringEncoding error:nil]);
+        EXPECT_WK_STREQ(fastString, [firstString UTF8String]);
+        EXPECT_WK_STREQ(slowString, [secondString UTF8String]);
+        hasRunSecondCompletionBlock = true;
+    } synchronousTimeout:0];
+    EXPECT_FALSE(hasRunSecondCompletionBlock);
+    TestWebKitAPI::Util::run(&hasRunSecondCompletionBlock);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(DATA_INTERACTION)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to