Title: [214625] trunk
Revision
214625
Author
[email protected]
Date
2017-03-30 14:33:08 -0700 (Thu, 30 Mar 2017)

Log Message

[WK2] Touches should not cancel when showing a custom action sheet while data interaction is active
https://bugs.webkit.org/show_bug.cgi?id=170291
<rdar://problem/31301388>

Reviewed by Tim Horton.

Source/WebKit2:

Currently, when presenting a custom popover, we will cancel all touches in the application. This makes data
interaction when a custom popover is shown impossible -- to address this, we should only cancel touches when
the view is not an active data interaction source.

New API test: DataInteractionTests.CustomActionSheetPopover.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView actionSheetAssistant:showCustomSheetForElement:]):

Tools:

Adds support for testing how the custom action sheet presentation codepath interacts with data interaction, as
well as a new unit test. In this case, we force data interaction to fail if touches are canceled on the
shared UIApplication, and verify that data interaction completes successfully.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(TestWebKitAPI::TEST):
* TestWebKitAPI/ios/DataInteractionSimulator.h:
* TestWebKitAPI/ios/DataInteractionSimulator.mm:
(-[DataInteractionSimulatorApplication _cancelAllTouches]):
(-[DataInteractionSimulator initWithWebView:]):
(-[DataInteractionSimulator simulateAllTouchesCanceled:]):
(-[DataInteractionSimulator runFrom:to:]):
(-[DataInteractionSimulator _advanceProgress]):
(-[DataInteractionSimulator _webView:showCustomSheetForElement:]):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (214624 => 214625)


--- trunk/Source/WebKit2/ChangeLog	2017-03-30 21:27:09 UTC (rev 214624)
+++ trunk/Source/WebKit2/ChangeLog	2017-03-30 21:33:08 UTC (rev 214625)
@@ -1,3 +1,20 @@
+2017-03-30  Wenson Hsieh  <[email protected]>
+
+        [WK2] Touches should not cancel when showing a custom action sheet while data interaction is active
+        https://bugs.webkit.org/show_bug.cgi?id=170291
+        <rdar://problem/31301388>
+
+        Reviewed by Tim Horton.
+
+        Currently, when presenting a custom popover, we will cancel all touches in the application. This makes data
+        interaction when a custom popover is shown impossible -- to address this, we should only cancel touches when
+        the view is not an active data interaction source.
+
+        New API test: DataInteractionTests.CustomActionSheetPopover.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView actionSheetAssistant:showCustomSheetForElement:]):
+
 2017-03-30  Youenn Fablet  <[email protected]>
 
         NetworkConnectionToWebProcess should stop web sockets when being destroyed

Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (214624 => 214625)


--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2017-03-30 21:27:09 UTC (rev 214624)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2017-03-30 21:33:08 UTC (rev 214625)
@@ -4045,8 +4045,15 @@
     
     if ([uiDelegate respondsToSelector:@selector(_webView:showCustomSheetForElement:)]) {
         if ([uiDelegate _webView:_webView showCustomSheetForElement:element]) {
-            // Prevent tap-and-hold and drag.
-            [UIApp _cancelAllTouches];
+#if ENABLE(DATA_INTERACTION)
+            BOOL shouldCancelAllTouches = !_dataInteractionState.sourceAction;
+#else
+            BOOL shouldCancelAllTouches = YES;
+#endif
+            // Prevent tap-and-hold and panning.
+            if (shouldCancelAllTouches)
+                [UIApp _cancelAllTouches];
+
             return YES;
         }
     }

Modified: trunk/Tools/ChangeLog (214624 => 214625)


--- trunk/Tools/ChangeLog	2017-03-30 21:27:09 UTC (rev 214624)
+++ trunk/Tools/ChangeLog	2017-03-30 21:33:08 UTC (rev 214625)
@@ -1,3 +1,26 @@
+2017-03-30  Wenson Hsieh  <[email protected]>
+
+        [WK2] Touches should not cancel when showing a custom action sheet while data interaction is active
+        https://bugs.webkit.org/show_bug.cgi?id=170291
+        <rdar://problem/31301388>
+
+        Reviewed by Tim Horton.
+
+        Adds support for testing how the custom action sheet presentation codepath interacts with data interaction, as
+        well as a new unit test. In this case, we force data interaction to fail if touches are canceled on the
+        shared UIApplication, and verify that data interaction completes successfully.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/ios/DataInteractionSimulator.h:
+        * TestWebKitAPI/ios/DataInteractionSimulator.mm:
+        (-[DataInteractionSimulatorApplication _cancelAllTouches]):
+        (-[DataInteractionSimulator initWithWebView:]):
+        (-[DataInteractionSimulator simulateAllTouchesCanceled:]):
+        (-[DataInteractionSimulator runFrom:to:]):
+        (-[DataInteractionSimulator _advanceProgress]):
+        (-[DataInteractionSimulator _webView:showCustomSheetForElement:]):
+
 2017-03-30  Per Arne Vollan  <[email protected]>
 
         [Win] Pass close_fds = True in Python popen call.

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm (214624 => 214625)


--- trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-03-30 21:27:09 UTC (rev 214624)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm	2017-03-30 21:33:08 UTC (rev 214625)
@@ -55,6 +55,13 @@
     return [NSValue valueWithCGRect:CGRectMake(x, y, width, height)];
 }
 
+static void checkSelectionRectsWithLogging(NSArray *expected, NSArray *observed)
+{
+    if (![expected isEqualToArray:observed])
+        NSLog(@"Expected selection rects: %@ but observed: %@", expected, observed);
+    EXPECT_TRUE([expected isEqualToArray:observed]);
+}
+
 namespace TestWebKitAPI {
 
 TEST(DataInteractionTests, ImageToContentEditable)
@@ -71,7 +78,7 @@
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ makeCGRectValue(1, 201, 215, 174) ]]);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 215, 174) ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, ImageToTextarea)
@@ -91,7 +98,7 @@
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
 
     NSArray *expectedSelectionRects = [NSArray arrayWithObjects:makeCGRectValue(6, 203, 188, 14), makeCGRectValue(6, 217, 188, 14), makeCGRectValue(6, 231, 66, 14), nil];
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:expectedSelectionRects]);
+    checkSelectionRectsWithLogging(expectedSelectionRects, [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, ContentEditableToContentEditable)
@@ -109,7 +116,7 @@
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ makeCGRectValue(1, 201, 961, 227) ]]);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 961, 227) ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, ContentEditableToTextarea)
@@ -127,7 +134,7 @@
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ makeCGRectValue(6, 203, 990, 232) ]]);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(6, 203, 990, 232) ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, LinkToInput)
@@ -138,13 +145,13 @@
     RetainPtr<DataInteractionSimulator> dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
     [dataInteractionSimulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)];
 
-    EXPECT_WK_STREQ("https://www.daringfireball.net/", [webView editorValue].UTF8String);
+    EXPECT_WK_STREQ("https://www.apple.com/", [webView editorValue].UTF8String);
 
     NSArray *observedEventNames = [dataInteractionSimulator observedEventNames];
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ makeCGRectValue(101, 273, 2613, 232) ]]);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(101, 273, 2057, 232) ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, BackgroundImageLinkToInput)
@@ -155,13 +162,13 @@
     RetainPtr<DataInteractionSimulator> dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
     [dataInteractionSimulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)];
 
-    EXPECT_WK_STREQ("https://www.daringfireball.net/", [webView editorValue].UTF8String);
+    EXPECT_WK_STREQ("https://www.apple.com/", [webView editorValue].UTF8String);
 
     NSArray *observedEventNames = [dataInteractionSimulator observedEventNames];
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ makeCGRectValue(101, 241, 2613, 232) ]]);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(101, 241, 2057, 232) ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, CanPreventStart)
@@ -178,7 +185,7 @@
     NSArray *observedEventNames = [dataInteractionSimulator observedEventNames];
     EXPECT_FALSE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_FALSE([observedEventNames containsObject:DataInteractionOverEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ ]]);
+    checkSelectionRectsWithLogging(@[ ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, CanPreventOperation)
@@ -194,7 +201,7 @@
     NSArray *observedEventNames = [dataInteractionSimulator observedEventNames];
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ ]]);
+    checkSelectionRectsWithLogging(@[ ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, EnterAndLeaveEvents)
@@ -212,7 +219,7 @@
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionLeaveEventName]);
     EXPECT_FALSE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ ]]);
+    checkSelectionRectsWithLogging(@[ ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, ExternalSourceUTF8PlainTextOnly)
@@ -231,7 +238,7 @@
     [dataInteractionSimulator setExternalItemProvider:simulatedItemProvider.get()];
     [dataInteractionSimulator runFrom:CGPointMake(300, 400) to:CGPointMake(100, 300)];
     EXPECT_WK_STREQ(textPayload.UTF8String, [webView stringByEvaluatingJavaScript:@"editor.textContent"].UTF8String);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ makeCGRectValue(1, 201, 1936, 227) ]]);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 1936, 227) ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, ExternalSourceJPEGOnly)
@@ -250,7 +257,7 @@
     [dataInteractionSimulator setExternalItemProvider:simulatedItemProvider.get()];
     [dataInteractionSimulator runFrom:CGPointMake(300, 400) to:CGPointMake(100, 300)];
     EXPECT_TRUE([webView editorContainsImageElement]);
-    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ makeCGRectValue(1, 201, 215, 174) ]]);
+    checkSelectionRectsWithLogging(@[ makeCGRectValue(1, 201, 215, 174) ], [dataInteractionSimulator finalSelectionRects]);
 }
 
 TEST(DataInteractionTests, AttachmentElementItemProviders)
@@ -306,6 +313,27 @@
     EXPECT_WK_STREQ("", [webView editorValue].UTF8String);
 }
 
+TEST(DataInteractionTests, CustomActionSheetPopover)
+{
+    RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [webView synchronouslyLoadTestPageNamed:@"link-and-target-div"];
+
+    auto dataInteractionSimulator = adoptNS([[DataInteractionSimulator alloc] initWithWebView:webView.get()]);
+    [dataInteractionSimulator setShouldEnsureUIApplication:YES];
+
+    __block BOOL didInvokeCustomActionSheet = NO;
+    [dataInteractionSimulator setShowCustomActionSheetBlock:^BOOL(_WKActivatedElementInfo *element)
+    {
+        EXPECT_EQ(_WKActivatedElementTypeLink, element.type);
+        EXPECT_WK_STREQ("Hello world", element.title.UTF8String);
+        didInvokeCustomActionSheet = YES;
+        return YES;
+    }];
+    [dataInteractionSimulator runFrom:CGPointMake(100, 50) to:CGPointMake(100, 300)];
+    EXPECT_TRUE(didInvokeCustomActionSheet);
+    EXPECT_WK_STREQ("PASS", [webView stringByEvaluatingJavaScript:@"target.textContent"].UTF8String);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(DATA_INTERACTION)

Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h (214624 => 214625)


--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-03-30 21:27:09 UTC (rev 214624)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.h	2017-03-30 21:33:08 UTC (rev 214625)
@@ -67,6 +67,8 @@
 - (instancetype)initWithWebView:(TestWKWebView *)webView;
 - (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation;
 
+@property (nonatomic) BOOL shouldEnsureUIApplication;
+@property (nonatomic) BlockPtr<BOOL(_WKActivatedElementInfo *)> showCustomActionSheetBlock;
 @property (nonatomic) BlockPtr<NSArray *(NSArray *)> convertItemProvidersBlock;
 @property (nonatomic, strong) UIItemProvider *externalItemProvider;
 @property (nonatomic, readonly) NSArray *observedEventNames;

Modified: trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm (214624 => 214625)


--- trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm	2017-03-30 21:27:09 UTC (rev 214624)
+++ trunk/Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm	2017-03-30 21:33:08 UTC (rev 214625)
@@ -28,11 +28,16 @@
 
 #if ENABLE(DATA_INTERACTION)
 
+#import "InstanceMethodSwizzler.h"
 #import "PlatformUtilities.h"
 #import <UIKit/UIItemProvider_Private.h>
+#import <WebCore/SoftLinking.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <wtf/RetainPtr.h>
 
+SOFT_LINK_FRAMEWORK(UIKit)
+SOFT_LINK(UIKit, UIApplicationInstantiateSingleton, void, (Class singletonClass), (singletonClass))
+
 using namespace TestWebKitAPI;
 
 #if USE(APPLE_INTERNAL_SDK) && __has_include(<WebKitAdditions/DataInteractionSimulatorAdditions.mm>)
@@ -41,6 +46,7 @@
 
 static double progressIncrementStep = 0.033;
 static double progressTimeStep = 0.016;
+static NSString *TestWebKitAPISimulateCancelAllTouchesNotificationName = @"TestWebKitAPISimulateCancelAllTouchesNotificationName";
 
 static NSArray *dataInteractionEventNames()
 {
@@ -52,6 +58,16 @@
     return eventNames;
 }
 
+@interface DataInteractionSimulatorApplication : UIApplication
+@end
+
+@implementation DataInteractionSimulatorApplication
+- (void)_cancelAllTouches
+{
+    [[NSNotificationCenter defaultCenter] postNotificationName:TestWebKitAPISimulateCancelAllTouchesNotificationName object:nil];
+}
+@end
+
 @implementation DataInteractionSimulator
 
 - (instancetype)initWithWebView:(TestWKWebView *)webView
@@ -58,6 +74,7 @@
 {
     if (self = [super init]) {
         _webView = webView;
+        _shouldEnsureUIApplication = NO;
         [_webView _setTestingDelegate:self];
         [_webView setUIDelegate:self];
     }
@@ -91,8 +108,24 @@
     return _observedEventNames.get();
 }
 
+- (void)simulateAllTouchesCanceled:(NSNotification *)notification
+{
+    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_advanceProgress) object:nil];
+    _phase = DataInteractionCancelled;
+    _currentProgress = 1;
+    _isDoneWithCurrentRun = true;
+    if (_dataInteractionSession)
+        [_webView _simulateDataInteractionSessionDidEnd:_dataInteractionSession.get()];
+}
+
 - (void)runFrom:(CGPoint)startLocation to:(CGPoint)endLocation
 {
+    NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
+    [defaultCenter addObserver:self selector:@selector(simulateAllTouchesCanceled:) name:TestWebKitAPISimulateCancelAllTouchesNotificationName object:nil];
+
+    if (_shouldEnsureUIApplication)
+        UIApplicationInstantiateSingleton([DataInteractionSimulatorApplication class]);
+
     [self _resetSimulatedState];
 
     RetainPtr<DataInteractionSimulator> strongSelf = self;
@@ -115,6 +148,9 @@
         [_dataInteractionSession setMockLocationInWindow:_startLocation];
         [_webView _simulatePrepareForDataInteractionSession:_dataInteractionSession.get() completion:^() {
             DataInteractionSimulator *weakSelf = strongSelf.get();
+            if (weakSelf->_phase == DataInteractionCancelled)
+                return;
+
             weakSelf->_phase = DataInteractionBeginning;
             [weakSelf _advanceProgress];
         }];
@@ -123,6 +159,8 @@
     Util::run(&_isDoneWithCurrentRun);
     [_webView clearMessageHandlers:dataInteractionEventNames()];
     _finalSelectionRects = [_webView selectionRectsAfterPresentationUpdate];
+
+    [defaultCenter removeObserver:self];
 }
 
 - (NSArray *)finalSelectionRects
@@ -159,17 +197,15 @@
             return;
         }
 
-#if HAS_DATA_INTERACTION_ITEMS
         for (WKDataInteractionItem *item in items)
             [itemProviders addObject:item.itemProvider];
-#endif
 
         _dataOperationSession = adoptNS([[MockDataOperationSession alloc] initWithProvider:itemProviders.firstObject location:self._currentLocation window:[_webView window]]);
-#if HAS_DATA_INTERACTION_ITEMS
         [_dataInteractionSession setItems:items];
-#endif
-        [_webView _simulateWillBeginDataInteractionWithSession:_dataInteractionSession.get()];
-        _phase = DataInteractionBegan;
+        if (!self.showCustomActionSheetBlock) {
+            [_webView _simulateWillBeginDataInteractionWithSession:_dataInteractionSession.get()];
+            _phase = DataInteractionBegan;
+        }
         break;
     }
     case DataInteractionBegan:
@@ -228,6 +264,21 @@
     return self.convertItemProvidersBlock ? self.convertItemProvidersBlock(originalItemProviders) : originalItemProviders;
 }
 
+- (BOOL)_webView:(WKWebView *)webView showCustomSheetForElement:(_WKActivatedElementInfo *)element
+{
+    if (!self.showCustomActionSheetBlock)
+        return NO;
+
+    RetainPtr<DataInteractionSimulator> strongSelf = self;
+    dispatch_async(dispatch_get_main_queue(), ^() {
+        DataInteractionSimulator *weakSelf = strongSelf.get();
+        [weakSelf->_webView _simulateWillBeginDataInteractionWithSession:weakSelf->_dataInteractionSession.get()];
+        weakSelf->_phase = DataInteractionBegan;
+    });
+
+    return self.showCustomActionSheetBlock(element);
+}
+
 @end
 
 #endif // ENABLE(DATA_INTERACTION)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to