Title: [222991] trunk
Revision
222991
Author
wenson_hs...@apple.com
Date
2017-10-06 11:53:00 -0700 (Fri, 06 Oct 2017)

Log Message

[iOS] Tweak support for classifying form controls (followup to r222487)
https://bugs.webkit.org/show_bug.cgi?id=177917
<rdar://problem/34820122>

Reviewed by Dean Jackson.

Source/WebKit:

This patch follows up with <http://trac.webkit.org/r222487>. It combines the functionality of two SPI hooks
implemented on WKContentView into a single method that vends a context dictionary, and additionally addresses an
issue with the original implementation, wherein some cached state on WebPageProxy is set upon starting node
assistance, but is never unset when stopping node assistance, nor set anywhere else. See per-method comments for
more detail.

* UIProcess/WebPageProxy.h:

Remove members m_acceptsAutofilledLoginCredentials and m_representingPageURL from WebPageProxy. This state is
retrieved from the AssistedNodeInformation struct when starting node assistance, but is never reset anywhere
else. Instead of introducing new members to remember this state, we can just use the WKContentView's current
assisted node information.

This also means that programmatically focusing forms (without user gesture) will no longer cause WKContentView
to accept autofilled login credentials, since we bail out of node assistance and don't begin an input session.

* UIProcess/ios/WKContentView.mm:
(-[WKContentView acceptsAutofilledLoginCredentials]): Deleted.
(-[WKContentView representingPageURL]): Deleted.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _autofillContext]):

Merge functionality of the previous two SPI hooks, such that -_autofillContext will return a non-null dictionary
containing the URL of the focused element's document if and only if WKContentView accepts autofilled login
credentials, and there exists a representing page URL.

When the page stops assisting the focused node, we set the AssistedNodeInformation's element type to None, so we
additionally bail and return nil if the element type is None. As an aside, it seems a more reasonable approach to
resetting state upon stopping node assistance is to just completely reset _assistedNodeInformation to its initial
value, i.e. via _assistedNodeInformation = { }. It's not clear whether there are behaviors relying on the fact
that all members but the element type in the content view's assisted node information could be stale, so this
seems worthy of some investigation.

* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::startAssistingNode):
(WebKit::WebPageProxy::acceptsAutofilledLoginCredentials): Deleted.
(WebKit::WebPageProxy::representingPageURL): Deleted.

Source/WebKitLegacy/mac:

Implement _autofillContext in legacy WebKit, and remove the two previous SPI hooks.

* DOM/DOMHTMLInputElement.mm:
(-[DOMHTMLInputElement _autofillContext]):
(-[DOMHTMLInputElement acceptsAutofilledLoginCredentials]): Deleted.
(-[DOMHTMLInputElement representingPageURL]): Deleted.

Tools:

Minor cleanup around autofill API tests added in r222487. Additionally, augments some of these API tests to
verify that after blurring the focused element, the content view no longer accepts autofill credentials (see
WebKit ChangeLog for more details). Also augments tests to verify that the URL in the autofill context matches
the document URL.

* TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm:

Remove the USE(APPLE_INTERNAL_SDK) guard for these API tests.

(newUIKeyboardLoginCredentialsSuggestion):

Add a stub implementation of UIKeyboardLoginCredentialsSuggestion. This allows
[UIKeyboardLoginCredentialsSuggestion new] to return a nonnull object, which allows these API tests to verify
that the credential filling codepath works as intended without any additional UIKit changes. Currently, tests
for the value of username and password fields are passing even though the fields are not being populated because
the expected string values are null, and the observed value is an empty string. We instead check the literal
string values here instead of credentialSuggestion's properties, so that tests verifying the behavior of
-insertTextSuggestion: will require username and password inputs to be populated.

(-[TestInputDelegate _webView:focusShouldStartInputSession:]):
(-[AutofillTestView initWithFrame:]):
(-[AutofillTestView _autofillInputView]):
(-[AutofillTestView textInputHasAutofillContext]):
(TestWebKitAPI::TEST):

Add an additional API test to verify that programmatic focus without user interaction (and also without testing
overrides) does not activate autofill.

(createUIKeyboardLoginCredentialsSuggestion): Deleted.
(-[WKWebView _privateTextInput]): Deleted.
* TestWebKitAPI/ios/UIKitSPI.h:

Minor gardening to remove iOS version >= 11 guards that are now unnecessary. Additionally, add some more private
header imports (with corresponding interface definitions for building and running with the public SDK).

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (222990 => 222991)


--- trunk/Source/WebKit/ChangeLog	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Source/WebKit/ChangeLog	2017-10-06 18:53:00 UTC (rev 222991)
@@ -1,3 +1,49 @@
+2017-10-06  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Tweak support for classifying form controls (followup to r222487)
+        https://bugs.webkit.org/show_bug.cgi?id=177917
+        <rdar://problem/34820122>
+
+        Reviewed by Dean Jackson.
+
+        This patch follows up with <http://trac.webkit.org/r222487>. It combines the functionality of two SPI hooks
+        implemented on WKContentView into a single method that vends a context dictionary, and additionally addresses an
+        issue with the original implementation, wherein some cached state on WebPageProxy is set upon starting node
+        assistance, but is never unset when stopping node assistance, nor set anywhere else. See per-method comments for
+        more detail.
+
+        * UIProcess/WebPageProxy.h:
+
+        Remove members m_acceptsAutofilledLoginCredentials and m_representingPageURL from WebPageProxy. This state is
+        retrieved from the AssistedNodeInformation struct when starting node assistance, but is never reset anywhere
+        else. Instead of introducing new members to remember this state, we can just use the WKContentView's current
+        assisted node information.
+
+        This also means that programmatically focusing forms (without user gesture) will no longer cause WKContentView
+        to accept autofilled login credentials, since we bail out of node assistance and don't begin an input session.
+
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView acceptsAutofilledLoginCredentials]): Deleted.
+        (-[WKContentView representingPageURL]): Deleted.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _autofillContext]):
+
+        Merge functionality of the previous two SPI hooks, such that -_autofillContext will return a non-null dictionary
+        containing the URL of the focused element's document if and only if WKContentView accepts autofilled login
+        credentials, and there exists a representing page URL.
+
+        When the page stops assisting the focused node, we set the AssistedNodeInformation's element type to None, so we
+        additionally bail and return nil if the element type is None. As an aside, it seems a more reasonable approach to
+        resetting state upon stopping node assistance is to just completely reset _assistedNodeInformation to its initial
+        value, i.e. via _assistedNodeInformation = { }. It's not clear whether there are behaviors relying on the fact
+        that all members but the element type in the content view's assisted node information could be stale, so this
+        seems worthy of some investigation.
+
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::startAssistingNode):
+        (WebKit::WebPageProxy::acceptsAutofilledLoginCredentials): Deleted.
+        (WebKit::WebPageProxy::representingPageURL): Deleted.
+
 2017-10-06  Yousuke Kimoto  <yousuke.kim...@sony.com>
 
         [WinCairo] Add shared curl files

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (222990 => 222991)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-10-06 18:53:00 UTC (rev 222991)
@@ -559,8 +559,6 @@
     void setIsScrollingOrZooming(bool);
     void requestRectsForGranularityWithSelectionOffset(WebCore::TextGranularity, uint32_t offset, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&&);
     void requestRectsAtSelectionOffsetWithText(int32_t offset, const String&, WTF::Function<void(const Vector<WebCore::SelectionRect>&, CallbackBase::Error)>&&);
-    bool acceptsAutofilledLoginCredentials();
-    WebCore::URL representingPageURL();
     void autofillLoginCredentials(const String& username, const String& password);
 #if ENABLE(DATA_INTERACTION)
     void didPerformDataInteractionControllerOperation(bool handled);
@@ -1998,8 +1996,6 @@
     bool m_hasDeferredStartAssistingNode { false };
     std::unique_ptr<NodeAssistanceArguments> m_deferredNodeAssistanceArguments;
     bool m_forceAlwaysUserScalable { false };
-    bool m_acceptsAutofilledLoginCredentials { false };
-    WebCore::URL m_representingPageURL;
 #endif
 
 #if ENABLE(POINTER_LOCK)

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentView.mm (222990 => 222991)


--- trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2017-10-06 18:53:00 UTC (rev 222991)
@@ -257,16 +257,6 @@
     return _page.get();
 }
 
-- (BOOL)acceptsAutofilledLoginCredentials
-{
-    return _page->acceptsAutofilledLoginCredentials();
-}
-
-- (NSURL *)representingPageURL
-{
-    return _page->representingPageURL();
-}
-
 - (void)willMoveToWindow:(UIWindow *)newWindow
 {
     NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (222990 => 222991)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2017-10-06 18:53:00 UTC (rev 222991)
@@ -4518,6 +4518,18 @@
     return dragItems;
 }
 
+- (NSDictionary *)_autofillContext
+{
+    if (_assistedNodeInformation.elementType == InputType::None || !_assistedNodeInformation.acceptsAutofilledLoginCredentials)
+        return nil;
+
+    NSURL *platformURL = _assistedNodeInformation.representingPageURL;
+    if (!platformURL)
+        return nil;
+
+    return @{ @"_WebViewURL" : platformURL };
+}
+
 #pragma mark - UIDragInteractionDelegate
 
 - (BOOL)_dragInteraction:(UIDragInteraction *)interaction shouldDelayCompetingGestureRecognizer:(UIGestureRecognizer *)competingGestureRecognizer

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (222990 => 222991)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2017-10-06 18:53:00 UTC (rev 222991)
@@ -891,8 +891,6 @@
 
 void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, bool blurPreviousNode, const UserData& userData)
 {
-    m_acceptsAutofilledLoginCredentials = information.acceptsAutofilledLoginCredentials;
-    m_representingPageURL = information.representingPageURL;
     API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
     if (m_editorState.isMissingPostLayoutData) {
         m_deferredNodeAssistanceArguments = std::make_unique<NodeAssistanceArguments>(NodeAssistanceArguments { information, userIsInteracting, blurPreviousNode, userDataObject });
@@ -912,16 +910,6 @@
     m_pageClient.stopAssistingNode();
 }
 
-bool WebPageProxy::acceptsAutofilledLoginCredentials()
-{
-    return m_acceptsAutofilledLoginCredentials;
-}
-
-WebCore::URL WebPageProxy::representingPageURL()
-{
-    return m_representingPageURL;
-}
-
 void WebPageProxy::autofillLoginCredentials(const String& username, const String& password)
 {
     m_process->send(Messages::WebPage::AutofillLoginCredentials(username, password), m_pageID);

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (222990 => 222991)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2017-10-06 18:53:00 UTC (rev 222991)
@@ -1,3 +1,18 @@
+2017-10-06  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Tweak support for classifying form controls (followup to r222487)
+        https://bugs.webkit.org/show_bug.cgi?id=177917
+        <rdar://problem/34820122>
+
+        Reviewed by Dean Jackson.
+
+        Implement _autofillContext in legacy WebKit, and remove the two previous SPI hooks.
+
+        * DOM/DOMHTMLInputElement.mm:
+        (-[DOMHTMLInputElement _autofillContext]):
+        (-[DOMHTMLInputElement acceptsAutofilledLoginCredentials]): Deleted.
+        (-[DOMHTMLInputElement representingPageURL]): Deleted.
+
 2017-10-05  Keith Miller  <keith_mil...@apple.com>
 
         Unreviewed, tapi builds without optimization so we should have TAPI passes -DRELEASE_WITHOUT_OPTIMIZATIONS.

Modified: trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.mm (222990 => 222991)


--- trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.mm	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.mm	2017-10-06 18:53:00 UTC (rev 222991)
@@ -34,7 +34,7 @@
 #import "DOMPrivate.h"
 #import "ExceptionHandlers.h"
 
-// FIXME <radar:34583628>: Simplyfy this once the UIKit work is available in the build.
+// FIXME: Simplify this once <rdar://problem/34583628> is available in the build.
 #if USE(APPLE_INTERNAL_SDK) && TARGET_OS_IPHONE
 #if __has_include(<UIKit/UIKeyboardLoginCredentialsSuggestion.h>)
 #import <UIKit/UIKeyboardLoginCredentialsSuggestion.h>
@@ -683,16 +683,17 @@
     IMPL->setValueForUser(inValue);
 }
 
-- (BOOL)acceptsAutofilledLoginCredentials
+- (NSDictionary *)_autofillContext
 {
     WebCore::JSMainThreadNullState state;
-    return !!WebCore::AutofillElements::computeAutofillElements(*IMPL);
-}
+    if (!WebCore::AutofillElements::computeAutofillElements(*IMPL))
+        return nil;
 
-- (NSURL *)representingPageURL
-{
-    WebCore::JSMainThreadNullState state;
-    return [NSURL URLWithString:self.ownerDocument.URL];
+    NSURL *documentURL = [NSURL URLWithString:self.ownerDocument.URL];
+    if (!documentURL)
+        return nil;
+
+    return @{ @"_WebViewURL" : documentURL };
 }
 
 #if USE(APPLE_INTERNAL_SDK) && TARGET_OS_IPHONE

Modified: trunk/Tools/ChangeLog (222990 => 222991)


--- trunk/Tools/ChangeLog	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Tools/ChangeLog	2017-10-06 18:53:00 UTC (rev 222991)
@@ -1,3 +1,46 @@
+2017-10-06  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Tweak support for classifying form controls (followup to r222487)
+        https://bugs.webkit.org/show_bug.cgi?id=177917
+        <rdar://problem/34820122>
+
+        Reviewed by Dean Jackson.
+
+        Minor cleanup around autofill API tests added in r222487. Additionally, augments some of these API tests to
+        verify that after blurring the focused element, the content view no longer accepts autofill credentials (see
+        WebKit ChangeLog for more details). Also augments tests to verify that the URL in the autofill context matches
+        the document URL.
+
+        * TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm:
+
+        Remove the USE(APPLE_INTERNAL_SDK) guard for these API tests.
+
+        (newUIKeyboardLoginCredentialsSuggestion):
+
+        Add a stub implementation of UIKeyboardLoginCredentialsSuggestion. This allows
+        [UIKeyboardLoginCredentialsSuggestion new] to return a nonnull object, which allows these API tests to verify
+        that the credential filling codepath works as intended without any additional UIKit changes. Currently, tests
+        for the value of username and password fields are passing even though the fields are not being populated because
+        the expected string values are null, and the observed value is an empty string. We instead check the literal
+        string values here instead of credentialSuggestion's properties, so that tests verifying the behavior of
+        -insertTextSuggestion: will require username and password inputs to be populated.
+
+        (-[TestInputDelegate _webView:focusShouldStartInputSession:]):
+        (-[AutofillTestView initWithFrame:]):
+        (-[AutofillTestView _autofillInputView]):
+        (-[AutofillTestView textInputHasAutofillContext]):
+        (TestWebKitAPI::TEST):
+
+        Add an additional API test to verify that programmatic focus without user interaction (and also without testing
+        overrides) does not activate autofill.
+
+        (createUIKeyboardLoginCredentialsSuggestion): Deleted.
+        (-[WKWebView _privateTextInput]): Deleted.
+        * TestWebKitAPI/ios/UIKitSPI.h:
+
+        Minor gardening to remove iOS version >= 11 guards that are now unnecessary. Additionally, add some more private
+        header imports (with corresponding interface definitions for building and running with the public SDK).
+
 2017-10-06  Antti Koivisto  <an...@apple.com>
 
         Minor WeakPtr improvements

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm (222990 => 222991)


--- trunk/Tools/TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm	2017-10-06 18:53:00 UTC (rev 222991)
@@ -25,42 +25,86 @@
 
 #include "config.h"
 
-#if WK_API_ENABLED && PLATFORM(IOS) && USE(APPLE_INTERNAL_SDK)
+#if WK_API_ENABLED && PLATFORM(IOS)
 
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
 #import "UIKitSPI.h"
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/_WKFocusedElementInfo.h>
+#import <WebKit/_WKInputDelegate.h>
+#import <wtf/BlockPtr.h>
 
-#import <UIKit/UITextInputTraits_Private.h>
-#import <UIKit/UITextInput_Private.h>
+#if !__has_include(<UIKit/UIKeyboardLoginCredentialsSuggestion.h>)
+// FIXME: This can be safely removed once <rdar://problem/34583628> lands in the SDK.
+@implementation UIKeyboardLoginCredentialsSuggestion
+@end
+#endif
 
-// FIXME 34583628: Simplyfy this once the UIKit work is available in the build.
-#if __has_include(<UIKit/UIKeyboardLoginCredentialsSuggestion.h>)
-#import <UIKit/UIKeyboardLoginCredentialsSuggestion.h>
-#else
-#import <UIKit/UITextSuggestion.h>
-@interface UIKeyboardLoginCredentialsSuggestion : UITextSuggestion
+static UIKeyboardLoginCredentialsSuggestion *newUIKeyboardLoginCredentialsSuggestion(NSString *username, NSString *password)
+{
+    UIKeyboardLoginCredentialsSuggestion *suggestion = [UIKeyboardLoginCredentialsSuggestion new];
+    suggestion.username = username;
+    suggestion.password = password;
+    return suggestion;
+}
 
-@property (nonatomic, assign) NSString *username;
-@property (nonatomic, assign) NSString *password;
+typedef UIView <UITextInputTraits_Private_Proposed_SPI_34583628> AutofillInputView;
 
+@interface TestInputDelegate : NSObject <_WKInputDelegate>
+@property (nonatomic) BOOL inputSessionRequiresUserInteraction;
 @end
-#endif
 
-static UIKeyboardLoginCredentialsSuggestion *createUIKeyboardLoginCredentialsSuggestion()
+@implementation TestInputDelegate
+
+- (instancetype)init
 {
-    return [[NSClassFromString(@"UIKeyboardLoginCredentialsSuggestion") new] autorelease];
+    if (self = [super init])
+        _inputSessionRequiresUserInteraction = NO;
+
+    return self;
 }
 
-typedef UIView <UITextInputPrivate, UITextInputTraits_Private, UITextInputTraits_Private_Staging_34583628>  AutofillCandidateView;
+- (BOOL)_webView:(WKWebView *)webView focusShouldStartInputSession:(id <_WKFocusedElementInfo>)info
+{
+    return !self.inputSessionRequiresUserInteraction || info.userInitiated;
+}
 
-@implementation WKWebView (AutofillTestHelpers)
+@end
 
-- (AutofillCandidateView *)_privateTextInput
+@interface AutofillTestView : TestWKWebView
+@end
+
+@implementation AutofillTestView {
+    RetainPtr<TestInputDelegate> _testDelegate;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame
 {
-    return (AutofillCandidateView *)[self valueForKey:@"_currentContentView"];
+    if (!(self = [super initWithFrame:frame]))
+        return nil;
+
+    _testDelegate = adoptNS([[TestInputDelegate alloc] init]);
+    self._inputDelegate = _testDelegate.get();
+    return self;
 }
 
+- (AutofillInputView *)_autofillInputView
+{
+    return (AutofillInputView *)self.textInputContentView;
+}
+
+- (BOOL)textInputHasAutofillContext
+{
+    [self waitForNextPresentationUpdate];
+    NSURL *url = "" objectForKey:@"_WebViewURL"];
+    if (![url isKindOfClass:[NSURL class]])
+        return NO;
+
+    EXPECT_WK_STREQ([self stringByEvaluatingJavaScript:@"document.URL"], url.absoluteString);
+    return YES;
+}
+
 @end
 
 namespace TestWebKitAPI {
@@ -67,110 +111,102 @@
 
 TEST(WKWebViewAutofillTests, UsernameAndPasswordField)
 {
-    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
-    AutofillCandidateView *contentView = [webView _privateTextInput];
+    auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input id='password' type='password'>"];
     [webView stringByEvaluatingJavaScript:@"user.focus()"];
-    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_TRUE([webView textInputHasAutofillContext]);
 
     [webView stringByEvaluatingJavaScript:@"password.focus()"];
-    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_TRUE([webView textInputHasAutofillContext]);
 
-    UIKeyboardLoginCredentialsSuggestion *credentialSuggestion = createUIKeyboardLoginCredentialsSuggestion();
-    credentialSuggestion.username = @"frederik";
-    credentialSuggestion.password = @"famos";
+    auto credentialSuggestion = adoptNS(newUIKeyboardLoginCredentialsSuggestion(@"frederik", @"famos"));
+    [[webView _autofillInputView] insertTextSuggestion:credentialSuggestion.get()];
 
-    [contentView insertTextSuggestion:credentialSuggestion];
+    EXPECT_WK_STREQ("famos", [webView stringByEvaluatingJavaScript:@"password.value"]);
 
-    EXPECT_WK_STREQ(credentialSuggestion.username, [webView stringByEvaluatingJavaScript:@"user.value"]);
-    EXPECT_WK_STREQ(credentialSuggestion.password, [webView stringByEvaluatingJavaScript:@"password.value"]);
-
-    [webView release];
+    [webView stringByEvaluatingJavaScript:@"document.activeElement.blur()"];
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 }
 
 TEST(WKWebViewAutofillTests, UsernameAndPasswordFieldSeparatedByRadioButton)
 {
-    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
-    AutofillCandidateView *contentView = [webView _privateTextInput];
+    auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input type='radio' name='radio_button' value='radio'><input id='password' type='password'>"];
     [webView stringByEvaluatingJavaScript:@"user.focus()"];
-    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_TRUE([webView textInputHasAutofillContext]);
 
     [webView stringByEvaluatingJavaScript:@"password.focus()"];
-    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_TRUE([webView textInputHasAutofillContext]);
 
-    UIKeyboardLoginCredentialsSuggestion *credentialSuggestion = createUIKeyboardLoginCredentialsSuggestion();
-    credentialSuggestion.username = @"frederik";
-    credentialSuggestion.password = @"famos";
+    auto credentialSuggestion = adoptNS(newUIKeyboardLoginCredentialsSuggestion(@"frederik", @"famos"));
+    [[webView _autofillInputView] insertTextSuggestion:credentialSuggestion.get()];
 
-    [contentView insertTextSuggestion:credentialSuggestion];
+    EXPECT_WK_STREQ("frederik", [webView stringByEvaluatingJavaScript:@"user.value"]);
+    EXPECT_WK_STREQ("famos", [webView stringByEvaluatingJavaScript:@"password.value"]);
 
-    EXPECT_WK_STREQ(credentialSuggestion.username, [webView stringByEvaluatingJavaScript:@"user.value"]);
-    EXPECT_WK_STREQ(credentialSuggestion.password, [webView stringByEvaluatingJavaScript:@"password.value"]);
-
-    [webView release];
+    [webView stringByEvaluatingJavaScript:@"document.activeElement.blur()"];
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 }
 
 TEST(WKWebViewAutofillTests, TwoTextFields)
 {
-    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
-    AutofillCandidateView *contentView = [webView _privateTextInput];
+    auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     [webView synchronouslyLoadHTMLString:@"<input id='text1' type='email'><input id='text2' type='text'>"];
     [webView stringByEvaluatingJavaScript:@"text1.focus()"];
-    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 
     [webView stringByEvaluatingJavaScript:@"text2.focus()"];
-    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 }
 
 TEST(WKWebViewAutofillTests, StandalonePasswordField)
 {
-    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
-    AutofillCandidateView *contentView = [webView _privateTextInput];
+    auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     [webView synchronouslyLoadHTMLString:@"<input id='password' type='password'>"];
     [webView stringByEvaluatingJavaScript:@"password.focus()"];
-    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_TRUE([webView textInputHasAutofillContext]);
 
-    UIKeyboardLoginCredentialsSuggestion *credentialSuggestion = createUIKeyboardLoginCredentialsSuggestion();
-    credentialSuggestion.username = @"frederik";
-    credentialSuggestion.password = @"famos";
+    auto credentialSuggestion = adoptNS(newUIKeyboardLoginCredentialsSuggestion(@"frederik", @"famos"));
+    [[webView _autofillInputView] insertTextSuggestion:credentialSuggestion.get()];
 
-    [contentView insertTextSuggestion:credentialSuggestion];
+    EXPECT_WK_STREQ("famos", [webView stringByEvaluatingJavaScript:@"password.value"]);
 
-    EXPECT_WK_STREQ(credentialSuggestion.password, [webView stringByEvaluatingJavaScript:@"password.value"]);
-
-    [webView release];
+    [webView stringByEvaluatingJavaScript:@"document.activeElement.blur()"];
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 }
 
 TEST(WKWebViewAutofillTests, StandaloneTextField)
 {
-    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
-    AutofillCandidateView *contentView = [webView _privateTextInput];
+    auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     [webView synchronouslyLoadHTMLString:@"<input id='textfield' type='text'>"];
     [webView stringByEvaluatingJavaScript:@"textfield.focus()"];
-    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
-
-    [webView release];
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 }
 
 TEST(WKWebViewAutofillTests, AccountCreationPage)
 {
-    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
-    AutofillCandidateView *contentView = [webView _privateTextInput];
+    auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
     [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input id='password' type='password'><input id='confirm_password' type='password'>"];
     [webView stringByEvaluatingJavaScript:@"user.focus()"];
-    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 
     [webView stringByEvaluatingJavaScript:@"password.focus()"];
-    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 
     [webView stringByEvaluatingJavaScript:@"confirm_password.focus()"];
-    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
+}
 
-    [webView release];
+TEST(WKWebViewAutofillTests, AutofillRequiresInputSession)
+{
+    auto webView = adoptNS([[AutofillTestView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]);
+    [(TestInputDelegate *)[webView _inputDelegate] setInputSessionRequiresUserInteraction:YES];
+    [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input id='password' type='password'>"];
+    [webView stringByEvaluatingJavaScript:@"user.focus()"];
+
+    EXPECT_FALSE([webView textInputHasAutofillContext]);
 }
 
-
 } // namespace TestWebKitAPI
 
-#endif // WK_API_ENABLED && PLATFORM(IOS) && USE(APPLE_INTERNAL_SDK)
+#endif // WK_API_ENABLED && PLATFORM(IOS)

Modified: trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h (222990 => 222991)


--- trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h	2017-10-06 18:47:47 UTC (rev 222990)
+++ trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h	2017-10-06 18:53:00 UTC (rev 222991)
@@ -27,24 +27,17 @@
 
 #import <UIKit/UITextInputTraits.h>
 
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
 @protocol UIDragSession;
 @class UIDragInteraction;
 @class UIDragItem;
-#endif
 
-#if USE(APPLE_INTERNAL_SDK) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+#if USE(APPLE_INTERNAL_SDK)
 
 #import <UIKit/UIApplication_Private.h>
 #import <UIKit/UIDragInteraction_Private.h>
 #import <UIKit/UITextInputTraits_Private.h>
-#import <UIKit/UITextSuggestion.h>
+#import <UIKit/UITextInput_Private.h>
 
-
-@protocol UITextInputTraits_Private_Staging_34583628 <NSObject, UITextInputTraits>
-@property (nonatomic, readonly) BOOL acceptsAutofilledLoginCredentials;
-@end
-
 #else
 
 WTF_EXTERN_C_BEGIN
@@ -53,23 +46,40 @@
 
 WTF_EXTERN_C_END
 
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+@interface UITextSuggestion : NSObject
+
+@end
+
 @protocol UIDragInteractionDelegate_ForWebKitOnly <UIDragInteractionDelegate>
 @optional
 - (void)_dragInteraction:(UIDragInteraction *)interaction prepareForSession:(id<UIDragSession>)session completion:(void(^)(void))completion;
 @end
-#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
 
 @protocol UITextInputTraits_Private <NSObject, UITextInputTraits>
-@property (nonatomic, readonly) BOOL acceptsAutofilledLoginCredentials;
 @end
 
+@protocol UITextInputPrivate <UITextInput, UITextInputTraits_Private>
+- (void)insertTextSuggestion:(UITextSuggestion *)textSuggestion;
+@end
+
 #endif
 
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+@protocol UITextInputTraits_Private_Proposed_SPI_34583628 <UITextInputPrivate>
+- (NSDictionary *)_autofillContext;
+@end
+
 @protocol UIDragInteractionDelegate_Proposed_SPI_33146803 <UIDragInteractionDelegate>
 - (void)_dragInteraction:(UIDragInteraction *)interaction itemsForAddingToSession:(id <UIDragSession>)session withTouchAtPoint:(CGPoint)point completion:(void(^)(NSArray<UIDragItem *> *))completion;
 @end
-#endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
 
+#if __has_include(<UIKit/UIKeyboardLoginCredentialsSuggestion.h>)
+// FIXME: Move this import under USE(APPLE_INTERNAL_SDK) once <rdar://problem/34583628> lands in the SDK.
+#import <UIKit/UIKeyboardLoginCredentialsSuggestion.h>
+#else
+@interface UIKeyboardLoginCredentialsSuggestion : UITextSuggestion
+@property (nonatomic, assign) NSString *username;
+@property (nonatomic, assign) NSString *password;
+@end
+#endif
+
 #endif // PLATFORM(IOS)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to