Title: [238635] trunk
Revision
238635
Author
dba...@webkit.org
Date
2018-11-28 13:55:13 -0800 (Wed, 28 Nov 2018)

Log Message

[iOS] Page not defocused when Find-in-page becomes first responder
https://bugs.webkit.org/show_bug.cgi?id=192084
<rdar://problem/46146777>

Reviewed by Tim Horton.

Source/WebKit:

When -becomeFirstResponder and -resignFirstResponder is called the page should become focused
and defocused, respectively. WebKit adjusts it behavior depending on whether it knows it has
focus. This includes decisions about whether to allow an element to be focused. We need to
ensure that WebKit knows whether the web view is focused for it to make good decisions.

* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::isViewFocused): Check if the content view is the first responder and
hence is accepting keyboard input. Note that picture-in-picture views do not accept keyboard
input.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView becomeFirstResponderForWebView]): Update activity state when the view
becomes focused.
(-[WKContentView resignFirstResponderForWebView]): Update activity state when the view
becomes defocused.

Tools:

Add tests for both Mac and iOS to ensure that when finding a string on the page
that we do not start an input session if a match is found in an <input> and the
WKWebView is not the first responder.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/WKWebViewFindString.mm: Added.
(-[WKWebViewFindStringInputDelegate _webView:didStartInputSession:]):
(-[WKWebViewFindStringFindDelegate findString]):
(-[WKWebViewFindStringFindDelegate _webView:didCountMatches:forString:]):
(-[WKWebViewFindStringFindDelegate _webView:didFindMatches:forString:withMatchIndex:]):
(-[WKWebViewFindStringFindDelegate _webView:didFailToFindString:]):
(returnNo):
(returnYes):
(viewIsFirstResponder):
(TestWebKitAPI::TEST):
* WebKitTestRunner/ios/PlatformWebViewIOS.mm:
(WTR::PlatformWebView::PlatformWebView): Make the view the first responder before the
window key. This matches the ordering used in PlatformWebView::focus(). No behavior change.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (238634 => 238635)


--- trunk/Source/WebKit/ChangeLog	2018-11-28 21:49:07 UTC (rev 238634)
+++ trunk/Source/WebKit/ChangeLog	2018-11-28 21:55:13 UTC (rev 238635)
@@ -1,3 +1,26 @@
+2018-11-28  Daniel Bates  <daba...@apple.com>
+
+        [iOS] Page not defocused when Find-in-page becomes first responder
+        https://bugs.webkit.org/show_bug.cgi?id=192084
+        <rdar://problem/46146777>
+
+        Reviewed by Tim Horton.
+
+        When -becomeFirstResponder and -resignFirstResponder is called the page should become focused
+        and defocused, respectively. WebKit adjusts it behavior depending on whether it knows it has
+        focus. This includes decisions about whether to allow an element to be focused. We need to
+        ensure that WebKit knows whether the web view is focused for it to make good decisions.
+
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::isViewFocused): Check if the content view is the first responder and
+        hence is accepting keyboard input. Note that picture-in-picture views do not accept keyboard
+        input.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView becomeFirstResponderForWebView]): Update activity state when the view
+        becomes focused.
+        (-[WKContentView resignFirstResponderForWebView]): Update activity state when the view
+        becomes defocused.
+
 2018-11-28  Alex Christensen  <achristen...@webkit.org>
 
         Remove dead code from an earlier attempt at implementing safe browsing

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (238634 => 238635)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2018-11-28 21:49:07 UTC (rev 238634)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2018-11-28 21:55:13 UTC (rev 238635)
@@ -166,8 +166,9 @@
 
 bool PageClientImpl::isViewFocused()
 {
-    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=133098
-    return isViewWindowActive() || [m_webView _isRetainingActiveFocusedState];
+    if (isViewInWindow() && ![m_webView _isBackground])
+        return [m_webView _contentViewIsFirstResponder];
+    return [m_webView _isRetainingActiveFocusedState];
 }
 
 bool PageClientImpl::isViewVisible()

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (238634 => 238635)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2018-11-28 21:49:07 UTC (rev 238634)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2018-11-28 21:55:13 UTC (rev 238635)
@@ -1034,6 +1034,9 @@
         didBecomeFirstResponder = [super becomeFirstResponder];
     }
 
+    if (didBecomeFirstResponder)
+        _page->activityStateDidChange(WebCore::ActivityState::IsFocused);
+
     if (didBecomeFirstResponder && [self canShowNonEmptySelectionView])
         [_textSelectionAssistant activateSelection];
 
@@ -1064,6 +1067,9 @@
 
     bool superDidResign = [super resignFirstResponder];
 
+    if (superDidResign)
+        _page->activityStateDidChange(WebCore::ActivityState::IsFocused);
+
     _resigningFirstResponder = NO;
 
     return superDidResign;

Modified: trunk/Tools/ChangeLog (238634 => 238635)


--- trunk/Tools/ChangeLog	2018-11-28 21:49:07 UTC (rev 238634)
+++ trunk/Tools/ChangeLog	2018-11-28 21:55:13 UTC (rev 238635)
@@ -1,3 +1,30 @@
+2018-11-28  Daniel Bates  <daba...@apple.com>
+
+        [iOS] Page not defocused when Find-in-page becomes first responder
+        https://bugs.webkit.org/show_bug.cgi?id=192084
+        <rdar://problem/46146777>
+
+        Reviewed by Tim Horton.
+
+        Add tests for both Mac and iOS to ensure that when finding a string on the page
+        that we do not start an input session if a match is found in an <input> and the
+        WKWebView is not the first responder.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewFindString.mm: Added.
+        (-[WKWebViewFindStringInputDelegate _webView:didStartInputSession:]):
+        (-[WKWebViewFindStringFindDelegate findString]):
+        (-[WKWebViewFindStringFindDelegate _webView:didCountMatches:forString:]):
+        (-[WKWebViewFindStringFindDelegate _webView:didFindMatches:forString:withMatchIndex:]):
+        (-[WKWebViewFindStringFindDelegate _webView:didFailToFindString:]):
+        (returnNo):
+        (returnYes):
+        (viewIsFirstResponder):
+        (TestWebKitAPI::TEST):
+        * WebKitTestRunner/ios/PlatformWebViewIOS.mm:
+        (WTR::PlatformWebView::PlatformWebView): Make the view the first responder before the
+        window key. This matches the ordering used in PlatformWebView::focus(). No behavior change.
+
 2018-11-28  Aakash Jain  <aakash_j...@apple.com>
 
         [ews-app] Add BeautifulSoup

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (238634 => 238635)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-11-28 21:49:07 UTC (rev 238634)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2018-11-28 21:55:13 UTC (rev 238635)
@@ -779,6 +779,7 @@
 		CE3524F81B1431F60028A7C5 /* TextFieldDidBeginAndEndEditing_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE3524F21B142B8D0028A7C5 /* TextFieldDidBeginAndEndEditing_Bundle.cpp */; };
 		CE3524F91B1441C40028A7C5 /* TextFieldDidBeginAndEndEditing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE3524F11B142B8D0028A7C5 /* TextFieldDidBeginAndEndEditing.cpp */; };
 		CE3524FA1B1443890028A7C5 /* input-focus-blur.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CE3524F51B142BBB0028A7C5 /* input-focus-blur.html */; };
+		CE449E1121AE0F7200E7ADA1 /* WKWebViewFindString.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE449E1021AE0F7200E7ADA1 /* WKWebViewFindString.mm */; };
 		CE4D5DE71F6743BA0072CFC6 /* StringWithDirection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CE4D5DE51F6743BA0072CFC6 /* StringWithDirection.cpp */; };
 		CE6E81A020A6935F00E2C80F /* SetTimeoutFunction.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE6E819F20A6935F00E2C80F /* SetTimeoutFunction.mm */; };
 		CE6E81A420A933D500E2C80F /* set-timeout-function.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = CE6E81A320A933B800E2C80F /* set-timeout-function.html */; };
@@ -2053,6 +2054,7 @@
 		CE3524F11B142B8D0028A7C5 /* TextFieldDidBeginAndEndEditing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextFieldDidBeginAndEndEditing.cpp; sourceTree = "<group>"; };
 		CE3524F21B142B8D0028A7C5 /* TextFieldDidBeginAndEndEditing_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextFieldDidBeginAndEndEditing_Bundle.cpp; sourceTree = "<group>"; };
 		CE3524F51B142BBB0028A7C5 /* input-focus-blur.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "input-focus-blur.html"; sourceTree = "<group>"; };
+		CE449E1021AE0F7200E7ADA1 /* WKWebViewFindString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewFindString.mm; sourceTree = "<group>"; };
 		CE4D5DE51F6743BA0072CFC6 /* StringWithDirection.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StringWithDirection.cpp; sourceTree = "<group>"; };
 		CE50D8C81C8665CE0072EA5A /* OptionSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OptionSet.cpp; sourceTree = "<group>"; };
 		CE6E819F20A6935F00E2C80F /* SetTimeoutFunction.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SetTimeoutFunction.mm; sourceTree = "<group>"; };
@@ -2544,6 +2546,7 @@
 				2DB647871F4161F70051A89E /* WKWebViewDoesNotLogDuringInitialization.mm */,
 				F4811E5821940B4400A5E0FD /* WKWebViewEditActions.mm */,
 				0F3B94A51A77266C00DE3272 /* WKWebViewEvaluateJavaScript.mm */,
+				CE449E1021AE0F7200E7ADA1 /* WKWebViewFindString.mm */,
 				D3BE5E341E4CE85E00FD563A /* WKWebViewGetContents.mm */,
 				37A9DBE7213B4C9300D261A2 /* WKWebViewServerTrustKVC.mm */,
 				93F56DA81E5F9181003EDE84 /* WKWebViewSnapshot.mm */,
@@ -4212,6 +4215,7 @@
 				2DB647881F4163D60051A89E /* WKWebViewDoesNotLogDuringInitialization.mm in Sources */,
 				F4811E5921940BDE00A5E0FD /* WKWebViewEditActions.mm in Sources */,
 				0F3B94A71A77267400DE3272 /* WKWebViewEvaluateJavaScript.mm in Sources */,
+				CE449E1121AE0F7200E7ADA1 /* WKWebViewFindString.mm in Sources */,
 				F4106C6921ACBF84004B89A1 /* WKWebViewFirstResponderTests.mm in Sources */,
 				D34E08761E4E42E1005FF14A /* WKWebViewGetContents.mm in Sources */,
 				F4FA91811E61849B007B8C1D /* WKWebViewMacEditingTests.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewFindString.mm (0 => 238635)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewFindString.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewFindString.mm	2018-11-28 21:55:13 UTC (rev 238635)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKFindDelegate.h>
+#import <WebKit/_WKInputDelegate.h>
+
+#if PLATFORM(IOS_FAMILY)
+#import "ClassMethodSwizzler.h"
+#import "UIKitSPI.h"
+#endif
+
+#if WK_API_ENABLED
+
+static bool isDone;
+static bool focusDidStartInputSession;
+static const NSUInteger maxCount = 100;
+
+@interface WKWebViewFindStringInputDelegate : NSObject <_WKInputDelegate>
+@end
+
+@implementation WKWebViewFindStringInputDelegate
+
+- (void)_webView:(WKWebView *)webView didStartInputSession:(id <_WKFormInputSession>)inputSession
+{
+    focusDidStartInputSession = YES;
+}
+
+@end
+
+@interface WKWebViewFindStringFindDelegate : NSObject <_WKFindDelegate>
+@property (nonatomic, readonly) NSString *findString;
+@property (nonatomic, readonly) NSUInteger matchesCount;
+@property (nonatomic, readonly) NSInteger matchIndex;
+@property (nonatomic, readonly) BOOL didFail;
+@end
+
+@implementation WKWebViewFindStringFindDelegate {
+    RetainPtr<NSString> _findString;
+}
+
+- (NSString *)findString
+{
+    return _findString.get();
+}
+
+- (void)_webView:(WKWebView *)webView didCountMatches:(NSUInteger)matches forString:(NSString *)string
+{
+    _findString = string;
+    _matchesCount = matches;
+    _didFail = NO;
+    isDone = YES;
+}
+
+- (void)_webView:(WKWebView *)webView didFindMatches:(NSUInteger)matches forString:(NSString *)string withMatchIndex:(NSInteger)matchIndex
+{
+    _findString = string;
+    _matchesCount = matches;
+    _matchIndex = matchIndex;
+    _didFail = NO;
+    isDone = YES;
+}
+
+- (void)_webView:(WKWebView *)webView didFailToFindString:(NSString *)string
+{
+    _findString = string;
+    _didFail = YES;
+    isDone = YES;
+}
+
+@end
+
+#if PLATFORM(IOS_FAMILY)
+static BOOL returnNo()
+{
+    return NO;
+}
+
+static BOOL returnYes()
+{
+    return YES;
+}
+
+static BOOL viewIsFirstResponder(UIView *view)
+{
+    return [view isFirstResponder];
+}
+#else
+static BOOL viewIsFirstResponder(NSView *view)
+{
+    return view.window.firstResponder == view;
+}
+#endif
+
+namespace TestWebKitAPI {
+
+TEST(WKWebViewFindString, DoNotFocusMatchWhenWebViewResignedAndHardwareKeyboardAttached)
+{
+#if PLATFORM(IOS_FAMILY)
+    ClassMethodSwizzler swizzler([UIKeyboard class], @selector(isInHardwareKeyboardMode), reinterpret_cast<IMP>(returnYes));
+#endif
+
+    auto inputDelegate = adoptNS([[WKWebViewFindStringInputDelegate alloc] init]);
+    auto findDelegate = adoptNS([[WKWebViewFindStringFindDelegate alloc] init]);
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto firstWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 200) configuration:configuration.get() addToWindow:YES]);
+    [firstWebView synchronouslyLoadHTMLString:@"<input type='text' value='hello'>"];
+    [firstWebView _setInputDelegate:inputDelegate.get()];
+    [firstWebView _setFindDelegate:findDelegate.get()];
+
+    auto secondWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(300, 0, 300, 200) configuration:configuration.get() addToWindow:YES]);
+    EXPECT_TRUE([secondWebView becomeFirstResponder]);
+    EXPECT_FALSE(viewIsFirstResponder(firstWebView.get()));
+
+    [firstWebView _findString:@"hello" options:0 maxCount:maxCount];
+    Util::run(&isDone);
+
+    EXPECT_FALSE(viewIsFirstResponder(firstWebView.get()));
+    EXPECT_WK_STREQ("hello", [findDelegate findString]);
+    EXPECT_FALSE(focusDidStartInputSession);
+}
+
+#if PLATFORM(IOS_FAMILY)
+TEST(WKWebViewFindString, DoNotFocusMatchWhenWebViewResigned)
+{
+    ClassMethodSwizzler swizzler([UIKeyboard class], @selector(isInHardwareKeyboardMode), reinterpret_cast<IMP>(returnNo));
+
+    auto inputDelegate = adoptNS([[WKWebViewFindStringInputDelegate alloc] init]);
+    auto findDelegate = adoptNS([[WKWebViewFindStringFindDelegate alloc] init]);
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto firstWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 200) configuration:configuration.get() addToWindow:YES]);
+    [firstWebView synchronouslyLoadHTMLString:@"<input type='text' value='hello'>"];
+    [firstWebView _setInputDelegate:inputDelegate.get()];
+    [firstWebView _setFindDelegate:findDelegate.get()];
+
+    auto secondWebView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(300, 0, 300, 200) configuration:configuration.get() addToWindow:YES]);
+    EXPECT_TRUE([secondWebView becomeFirstResponder]);
+    EXPECT_FALSE([firstWebView isFirstResponder]);
+
+    [firstWebView _findString:@"hello" options:0 maxCount:maxCount];
+    Util::run(&isDone);
+
+    EXPECT_FALSE([firstWebView isFirstResponder]);
+    EXPECT_WK_STREQ("hello", [findDelegate findString]);
+    EXPECT_FALSE(focusDidStartInputSession);
+}
+#endif
+
+} // namespace TestWebKitAPI
+
+#endif

Modified: trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm (238634 => 238635)


--- trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm	2018-11-28 21:49:07 UTC (rev 238634)
+++ trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm	2018-11-28 21:55:13 UTC (rev 238635)
@@ -181,8 +181,8 @@
     m_view = [[TestRunnerWKWebView alloc] initWithFrame:viewRectForWindowRect(rect, WebViewSizingMode::Default) configuration:configuration];
 
     [m_window.rootViewController.view addSubview:m_view];
+    [m_view becomeFirstResponder];
     [m_window makeKeyAndVisible];
-    [m_view becomeFirstResponder];
 }
 
 PlatformWebView::~PlatformWebView()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to