Data interaction causes selection to fall out of sync between web/UI processes
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Feb 2017 17:23:51 +0000 (17:23 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Feb 2017 17:23:51 +0000 (17:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=168735
<rdar://problem/30657817>

Reviewed by Tim Horton.

Source/WebKit2:

Fixes a bug with data interaction causing selection state to fall out of sync between the UI and web processes,
and also introduces testing infrastructure and tests for grabbing UI-side selection view rects in TestWebKitAPI.
While performing a data interaction operation, we now lift restrictions for assisting the focused node.

* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView cleanupInteraction]):
(-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:userObject:]):

Tools:

Adds a new method to TestWKWebView for querying selection view rects from the UI process and augments data
interaction unit tests to check for selection rects using this new hook.

* TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
(makeCGRectValue):
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[TestWKWebView selectionRectsAfterPresentationUpdate]):
* TestWebKitAPI/ios/DataInteractionSimulator.h:
* TestWebKitAPI/ios/DataInteractionSimulator.mm:
(-[DataInteractionSimulator _resetSimulatedState]):
(-[DataInteractionSimulator runFrom:to:]):
(-[DataInteractionSimulator finalSelectionRects]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212898 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h
Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/ios/DataInteractionTests.mm
Tools/TestWebKitAPI/cocoa/TestWKWebView.h
Tools/TestWebKitAPI/cocoa/TestWKWebView.mm
Tools/TestWebKitAPI/ios/DataInteractionSimulator.h
Tools/TestWebKitAPI/ios/DataInteractionSimulator.mm

index bc8e773..c9a7978 100644 (file)
@@ -1,3 +1,20 @@
+2017-02-22  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Data interaction causes selection to fall out of sync between web/UI processes
+        https://bugs.webkit.org/show_bug.cgi?id=168735
+        <rdar://problem/30657817>
+
+        Reviewed by Tim Horton.
+
+        Fixes a bug with data interaction causing selection state to fall out of sync between the UI and web processes,
+        and also introduces testing infrastructure and tests for grabbing UI-side selection view rects in TestWebKitAPI.
+        While performing a data interaction operation, we now lift restrictions for assisting the focused node.
+
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView cleanupInteraction]):
+        (-[WKContentView _startAssistingNode:userIsInteracting:blurPreviousNode:userObject:]):
+
 2017-02-23  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK] Crash attempting to load Flash plugin in Wayland
index b6bfc6d..41f191e 100644 (file)
@@ -190,6 +190,7 @@ struct WKAutoCorrectionData {
 
 #if ENABLE(DATA_INTERACTION)
     WebKit::WKDataInteractionState _dataInteractionState;
+    BOOL _isPerformingDataInteractionOperation;
 #endif
 }
 
index f957c6c..6b2c13b 100644 (file)
@@ -645,6 +645,7 @@ static UIWebSelectionMode toUIWebSelectionMode(WKSelectionGranularity granularit
     [_dataInteractionGestureRecognizer setDelegate:nil];
     [self removeGestureRecognizer:_dataInteractionGestureRecognizer.get()];
     [self teardownDataInteractionDelegates];
+    _isPerformingDataInteractionOperation = NO;
 #endif
 
     _inspectorNodeSearchEnabled = NO;
@@ -3773,6 +3774,9 @@ static bool isAssistableInputType(InputType type)
     else {
         // The default behavior is to allow node assistance if the user is interacting or the keyboard is already active.
         shouldShowKeyboard = userIsInteracting || _textSelectionAssistant;
+#if ENABLE(DATA_INTERACTION)
+        shouldShowKeyboard |= _isPerformingDataInteractionOperation;
+#endif
     }
     if (!shouldShowKeyboard)
         return;
index 9403968..7a812ca 100644 (file)
@@ -1,3 +1,26 @@
+2017-02-22  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Data interaction causes selection to fall out of sync between web/UI processes
+        https://bugs.webkit.org/show_bug.cgi?id=168735
+        <rdar://problem/30657817>
+
+        Reviewed by Tim Horton.
+
+        Adds a new method to TestWKWebView for querying selection view rects from the UI process and augments data
+        interaction unit tests to check for selection rects using this new hook.
+
+        * TestWebKitAPI/Tests/ios/DataInteractionTests.mm:
+        (makeCGRectValue):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+        * TestWebKitAPI/cocoa/TestWKWebView.mm:
+        (-[TestWKWebView selectionRectsAfterPresentationUpdate]):
+        * TestWebKitAPI/ios/DataInteractionSimulator.h:
+        * TestWebKitAPI/ios/DataInteractionSimulator.mm:
+        (-[DataInteractionSimulator _resetSimulatedState]):
+        (-[DataInteractionSimulator runFrom:to:]):
+        (-[DataInteractionSimulator finalSelectionRects]):
+
 2017-02-22  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         Better handle Thread and RunLoop initialization
index aed4c8a..4e5d0ef 100644 (file)
 
 @end
 
+static NSValue *makeCGRectValue(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
+{
+    return [NSValue valueWithCGRect:CGRectMake(x, y, width, height)];
+}
+
 namespace TestWebKitAPI {
 
 TEST(DataInteractionTests, ImageToContentEditable)
@@ -63,6 +68,7 @@ TEST(DataInteractionTests, ImageToContentEditable)
     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) ]]);
 }
 
 TEST(DataInteractionTests, ImageToTextarea)
@@ -81,6 +87,9 @@ TEST(DataInteractionTests, ImageToTextarea)
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     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]);
 }
 
 TEST(DataInteractionTests, ContentEditableToContentEditable)
@@ -99,6 +108,7 @@ TEST(DataInteractionTests, ContentEditableToContentEditable)
     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) ]]);
 }
 
 TEST(DataInteractionTests, ContentEditableToTextarea)
@@ -117,6 +127,7 @@ TEST(DataInteractionTests, ContentEditableToTextarea)
     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) ]]);
 }
 
 TEST(DataInteractionTests, LinkToInput)
@@ -134,6 +145,7 @@ TEST(DataInteractionTests, LinkToInput)
     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) ]]);
 }
 
 TEST(DataInteractionTests, BackgroundImageLinkToInput)
@@ -151,6 +163,7 @@ TEST(DataInteractionTests, BackgroundImageLinkToInput)
     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) ]]);
 }
 
 TEST(DataInteractionTests, CanPreventStart)
@@ -167,6 +180,7 @@ TEST(DataInteractionTests, CanPreventStart)
     NSArray *observedEventNames = [dataInteractionSimulator observedEventNames];
     EXPECT_FALSE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_FALSE([observedEventNames containsObject:DataInteractionOverEventName]);
+    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ ]]);
 }
 
 TEST(DataInteractionTests, CanPreventOperation)
@@ -183,6 +197,7 @@ TEST(DataInteractionTests, CanPreventOperation)
     NSArray *observedEventNames = [dataInteractionSimulator observedEventNames];
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionEnterEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
+    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ ]]);
 }
 
 TEST(DataInteractionTests, EnterAndLeaveEvents)
@@ -201,6 +216,7 @@ TEST(DataInteractionTests, EnterAndLeaveEvents)
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionOverEventName]);
     EXPECT_TRUE([observedEventNames containsObject:DataInteractionLeaveEventName]);
     EXPECT_FALSE([observedEventNames containsObject:DataInteractionPerformOperationEventName]);
+    EXPECT_TRUE([[dataInteractionSimulator finalSelectionRects] isEqualToArray:@[ ]]);
 }
 
 TEST(DataInteractionTests, HandlesDataInteractionFailureGracefully)
@@ -235,6 +251,7 @@ TEST(DataInteractionTests, ExternalSourceUTF8PlainTextOnly)
     [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) ]]);
 }
 
 TEST(DataInteractionTests, ExternalSourceJPEGOnly)
@@ -253,6 +270,7 @@ TEST(DataInteractionTests, ExternalSourceJPEGOnly)
     [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) ]]);
 }
 
 } // namespace TestWebKitAPI
index b5f1347..def0166 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #import <WebKit/WebKit.h>
+#import <wtf/RetainPtr.h>
 
 #if WK_API_ENABLED
 
 - (void)performAfterLoading:(dispatch_block_t)actions;
 @end
 
+#if PLATFORM(IOS)
+@interface TestWKWebView (IOSOnly)
+@property (nonatomic, readonly) RetainPtr<NSArray> selectionRectsAfterPresentationUpdate;
+@end
+#endif
+
 #if PLATFORM(MAC)
 @interface TestWKWebView (MacOnly)
 // Simulates clicking with a pressure-sensitive device, if possible.
index 5202152..f751e56 100644 (file)
@@ -259,6 +259,29 @@ NSEventMask __simulated_forceClickAssociatedEventsMask(id self, SEL _cmd)
 
 @end
 
+#if PLATFORM(IOS)
+
+@implementation TestWKWebView (IOSOnly)
+
+- (RetainPtr<NSArray>)selectionRectsAfterPresentationUpdate
+{
+    RetainPtr<TestWKWebView> retainedSelf = self;
+
+    __block bool isDone = false;
+    __block RetainPtr<NSArray> selectionRects;
+    [self _doAfterNextPresentationUpdate:^() {
+        selectionRects = adoptNS([[retainedSelf _uiTextSelectionRects] retain]);
+        isDone = true;
+    }];
+
+    TestWebKitAPI::Util::run(&isDone);
+    return selectionRects;
+}
+
+@end
+
+#endif
+
 #if PLATFORM(MAC)
 @implementation TestWKWebView (MacOnly)
 - (void)mouseDownAtPoint:(NSPoint)point simulatePressure:(BOOL)simulatePressure
index 7494e76..81dda4f 100644 (file)
@@ -53,6 +53,7 @@ typedef NS_ENUM(NSInteger, DataInteractionPhase) {
     RetainPtr<MockDataInteractionInfo> _dataInteractionInfo;
     RetainPtr<NSMutableArray> _observedEventNames;
     RetainPtr<UIItemProvider> _externalItemProvider;
+    RetainPtr<NSArray *> _finalSelectionRects;
     CGPoint _startLocation;
     CGPoint _endLocation;
 
@@ -68,6 +69,7 @@ typedef NS_ENUM(NSInteger, DataInteractionPhase) {
 @property (nonatomic, strong) UIItemProvider *externalItemProvider;
 @property (nonatomic, readonly) BOOL didTryToBeginDataInteraction;
 @property (nonatomic, readonly) NSArray *observedEventNames;
+@property (nonatomic, readonly) NSArray *finalSelectionRects;
 
 @end
 
index e6b581d..fb8c7fb 100644 (file)
@@ -121,6 +121,7 @@ static NSArray *dataInteractionEventNames()
     _isDoneWithCurrentRun = false;
     _didTryToBeginDataInteraction = NO;
     _observedEventNames = adoptNS([[NSMutableArray alloc] init]);
+    _finalSelectionRects = @[ ];
 }
 
 - (NSArray *)observedEventNames
@@ -155,6 +156,12 @@ static NSArray *dataInteractionEventNames()
     Util::run(&_isDoneWithCurrentRun);
     [_gestureRecognizer setMockNumberOfTouches:0];
     [_webView clearMessageHandlers:dataInteractionEventNames()];
+    _finalSelectionRects = [_webView selectionRectsAfterPresentationUpdate];
+}
+
+- (NSArray *)finalSelectionRects
+{
+    return _finalSelectionRects.get();
 }
 
 - (void)_advanceProgress