Title: [222487] trunk
Revision
222487
Author
[email protected]
Date
2017-09-25 19:33:43 -0700 (Mon, 25 Sep 2017)

Log Message

Expose way to set values of classified form controls as {Legacy WebKit, WebKit} SPI
https://bugs.webkit.org/show_bug.cgi?id=174394
<rdar://problem/33183504>

Patch by Frederik Riedel <[email protected]> on 2017-09-25
Reviewed by Ryosuke Niwa.

Source/WebCore:

* WebCore.xcodeproj/project.pbxproj:
* editing/ios/AutofillElements.cpp: Added.
(WebCore::isAutofillableElement): Returns true if the element is of type text or email.
(WebCore::nextAutofillableElement): Returns the next focusable element that is autofillable.
(WebCore::previousAutofillableElement): Returns the previous focusable element that is autofillable.
(WebCore::AutofillElements::computeAutofillElements): Computes the autofill elements (username & password)
for a given input element.
(WebCore::AutofillElements::autofill): Fills the credentials into the pair of username/password elements.
* editing/ios/AutofillElements.h: Added.

Source/WebKit:

* Platform/spi/ios/UIKitSPI.h:
* Shared/AssistedNodeInformation.cpp:
(WebKit::AssistedNodeInformation::encode const):
Encodes additional node information, including if the node is part of a login screen.
(WebKit::AssistedNodeInformation::decode):
Decodes the additional assisted node information.
* Shared/AssistedNodeInformation.h:
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView acceptsAutofilledLoginCredentials]):
Determines if the WKContentView shows a login screen.
(-[WKContentView representingPageUrl]):
Returns the URL of the currently displayed web page.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView insertTextSuggestion:]):
Inserts the login credentials into the Web View.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::startAssistingNode):
Transfer the additional assistednode information (acceptsAutofilledLoginCredentials and representingPageUrl).
(WebKit::WebPageProxy::acceptsAutofilledLoginCredentials):
Returns if the Web View shows a login screen.
(WebKit::WebPageProxy::representingPageUrl):
Returns the Web View's URL.
(WebKit::WebPageProxy::autofillLoginCredentials):
Insert the credentials into the Web View.
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getAssistedNodeInformation): Transports the information if the currently
highlighted node accepts autofilled login credentials.
(WebKit::WebPage::autofillLoginCredentials): Fills the login credentials into the
WebPage.

Source/WebKitLegacy/mac:

* DOM/DOMHTMLInputElement.h:
* DOM/DOMHTMLInputElement.mm:
(-[DOMHTMLInputElement acceptsAutofilledLoginCredentials]):
Determines if this HTMLInputElement is part of a login screen.
(-[DOMHTMLInputElement representingPageUrl]):
Returns the webpage's URL that is currently displayed in the Web View.
(-[DOMHTMLInputElement insertTextSuggestion:]):
Inserts login credentials into the Web View.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm: Added.
(-[WKWebView _privateTextInput]): Testing helpers.
(TestWebKitAPI::TEST): Added test cases to test AutoFill for web views.
* TestWebKitAPI/ios/UIKitSPI.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (222486 => 222487)


--- trunk/Source/WebCore/ChangeLog	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebCore/ChangeLog	2017-09-26 02:33:43 UTC (rev 222487)
@@ -1,3 +1,21 @@
+2017-09-25  Frederik Riedel  <[email protected]>
+
+        Expose way to set values of classified form controls as {Legacy WebKit, WebKit} SPI
+        https://bugs.webkit.org/show_bug.cgi?id=174394
+        <rdar://problem/33183504>
+
+        Reviewed by Ryosuke Niwa.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/ios/AutofillElements.cpp: Added.
+        (WebCore::isAutofillableElement): Returns true if the element is of type text or email.
+        (WebCore::nextAutofillableElement): Returns the next focusable element that is autofillable.
+        (WebCore::previousAutofillableElement): Returns the previous focusable element that is autofillable.
+        (WebCore::AutofillElements::computeAutofillElements): Computes the autofill elements (username & password)
+        for a given input element.
+        (WebCore::AutofillElements::autofill): Fills the credentials into the pair of username/password elements.
+        * editing/ios/AutofillElements.h: Added.
+
 2017-09-25  Devin Rousso  <[email protected]>
 
         Web Inspector: move Console.addInspectedNode to DOM.setInspectedNode

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (222486 => 222487)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-09-26 02:33:43 UTC (rev 222487)
@@ -2297,6 +2297,8 @@
 		5162C7F411F77EFB00612EFE /* SchemeRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5162C7F211F77EFA00612EFE /* SchemeRegistry.cpp */; };
 		5162C7F511F77EFB00612EFE /* SchemeRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 5162C7F311F77EFB00612EFE /* SchemeRegistry.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		5166D3CD1E8ED48F00AD62E3 /* StorageType.h in Headers */ = {isa = PBXBuildFile; fileRef = 5166D3CC1E8ED41100AD62E3 /* StorageType.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		51699EE31F608CD500D57D06 /* AutofillElements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51699EE11F608CD500D57D06 /* AutofillElements.cpp */; };
+		51699EE41F608CD500D57D06 /* AutofillElements.h in Headers */ = {isa = PBXBuildFile; fileRef = 51699EE21F608CD500D57D06 /* AutofillElements.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		516BB7940CE91E6800512F79 /* JSTreeWalkerCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 516BB7920CE91E6800512F79 /* JSTreeWalkerCustom.cpp */; };
 		516C62201950D48700337E75 /* GamepadEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 516C621D1950D48700337E75 /* GamepadEvent.cpp */; };
 		516C62211950D48700337E75 /* GamepadEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 516C621E1950D48700337E75 /* GamepadEvent.h */; };
@@ -10197,6 +10199,8 @@
 		51645B531B9F889B00F789CE /* IDBVersionChangeEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBVersionChangeEvent.h; sourceTree = "<group>"; };
 		51645B541B9F88E800F789CE /* IDBCursor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBCursor.cpp; sourceTree = "<group>"; };
 		5166D3CC1E8ED41100AD62E3 /* StorageType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageType.h; sourceTree = "<group>"; };
+		51699EE11F608CD500D57D06 /* AutofillElements.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AutofillElements.cpp; sourceTree = "<group>"; };
+		51699EE21F608CD500D57D06 /* AutofillElements.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AutofillElements.h; sourceTree = "<group>"; };
 		516BB7920CE91E6800512F79 /* JSTreeWalkerCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTreeWalkerCustom.cpp; sourceTree = "<group>"; };
 		516C621D1950D48700337E75 /* GamepadEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GamepadEvent.cpp; sourceTree = "<group>"; };
 		516C621E1950D48700337E75 /* GamepadEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GamepadEvent.h; sourceTree = "<group>"; };
@@ -18389,6 +18393,8 @@
 		443292C10EBA6D7300E62016 /* ios */ = {
 			isa = PBXGroup;
 			children = (
+				51699EE11F608CD500D57D06 /* AutofillElements.cpp */,
+				51699EE21F608CD500D57D06 /* AutofillElements.h */,
 				D0BD4F5A1408850F006839B6 /* DictationCommandIOS.cpp */,
 				D0BD4F5B1408850F006839B6 /* DictationCommandIOS.h */,
 				FED13D390CEA934600D89466 /* EditorIOS.mm */,
@@ -27161,6 +27167,7 @@
 				A5A7AA43132F0ECC00D3A3C2 /* AutocapitalizeTypes.h in Headers */,
 				7C1843FE1C8B7283002EB973 /* Autofill.h in Headers */,
 				7C1E97281A9F9834007BF0FB /* AutoFillButtonElement.h in Headers */,
+				51699EE41F608CD500D57D06 /* AutofillElements.h in Headers */,
 				C9D467051E60C465008195FB /* AutoplayEvent.h in Headers */,
 				45830D4E1679B4F800ACF8C3 /* AutoscrollController.h in Headers */,
 				A8CFF04E0A154F09000A4234 /* AutoTableLayout.h in Headers */,
@@ -27830,6 +27837,7 @@
 				84730D891248F0B300D3A9C9 /* FESpecularLighting.h in Headers */,
 				4129C9971F59B963009D7403 /* FetchBodySource.h in Headers */,
 				41D129DB1F3D143800D15E47 /* FetchHeaders.h in Headers */,
+				416E6FE81BBD12DF000A6023 /* FetchInternalsBuiltins.h in Headers */,
 				41AD753A1CEF6BD100A31486 /* FetchOptions.h in Headers */,
 				7CE1914D1F2A9AFB00272F78 /* FetchReferrerPolicy.h in Headers */,
 				7CE1915A1F2A9B3400272F78 /* FetchRequestCache.h in Headers */,
@@ -31325,6 +31333,7 @@
 				A5F6E16B132ED46E008EDAE3 /* Autocapitalize.cpp in Sources */,
 				7C1843FD1C8B7283002EB973 /* Autofill.cpp in Sources */,
 				7C1E97271A9F9834007BF0FB /* AutoFillButtonElement.cpp in Sources */,
+				51699EE31F608CD500D57D06 /* AutofillElements.cpp in Sources */,
 				45830D4D1679B4F800ACF8C3 /* AutoscrollController.cpp in Sources */,
 				A8CFF0500A154F09000A4234 /* AutoTableLayout.cpp in Sources */,
 				CDECA89A1EDF447D00DCB08B /* AVAssetTrackUtilities.mm in Sources */,

Added: trunk/Source/WebCore/editing/ios/AutofillElements.cpp (0 => 222487)


--- trunk/Source/WebCore/editing/ios/AutofillElements.cpp	                        (rev 0)
+++ trunk/Source/WebCore/editing/ios/AutofillElements.cpp	2017-09-26 02:33:43 UTC (rev 222487)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 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"
+#include "AutofillElements.h"
+
+#include "FocusController.h"
+#include "Page.h"
+
+namespace WebCore {
+
+static inline bool isAutofillableElement(Element& node)
+{
+    if (!is<HTMLInputElement>(node))
+        return false;
+
+    auto inputElement = &downcast<HTMLInputElement>(node);
+    return inputElement->isTextField() || inputElement->isEmailField();
+}
+
+static inline RefPtr<HTMLInputElement> nextAutofillableElement(Node* startNode, FocusController& focusController)
+{
+    if (!is<Element>(startNode))
+        return nullptr;
+
+    RefPtr<Element> nextElement = downcast<Element>(startNode);
+    do {
+        nextElement = focusController.nextFocusableElement(*nextElement.get());
+    } while (nextElement && !isAutofillableElement(*nextElement.get()));
+
+    if (!nextElement)
+        return nullptr;
+
+    return &downcast<HTMLInputElement>(*nextElement);
+}
+
+static inline RefPtr<HTMLInputElement> previousAutofillableElement(Node* startNode, FocusController& focusController)
+{
+    if (!is<Element>(startNode))
+        return nullptr;
+
+    RefPtr<Element> previousElement = downcast<Element>(startNode);
+    do {
+        previousElement = focusController.previousFocusableElement(*previousElement.get());
+    } while (previousElement && !isAutofillableElement(*previousElement.get()));
+
+    if (!previousElement)
+        return nullptr;
+    
+    return &downcast<HTMLInputElement>(*previousElement);
+}
+
+AutofillElements::AutofillElements(RefPtr<HTMLInputElement>&& username, RefPtr<HTMLInputElement>&& password)
+    : m_username(username)
+    , m_password(password)
+{
+}
+
+std::optional<AutofillElements> AutofillElements::computeAutofillElements(Ref<HTMLInputElement> start)
+{
+    if (!start->document().page())
+        return std::nullopt;
+    FocusController& focusController = start->document().page()->focusController();
+    if (start->isPasswordField()) {
+        RefPtr<HTMLInputElement> previousElement = previousAutofillableElement(start.ptr(), focusController);
+        RefPtr<HTMLInputElement> nextElement = nextAutofillableElement(start.ptr(), focusController);
+        bool hasDuplicatePasswordElements = (nextElement && nextElement->isPasswordField()) || (previousElement && previousElement->isPasswordField());
+        if (hasDuplicatePasswordElements)
+            return std::nullopt;
+
+        if (previousElement && is<HTMLInputElement>(*previousElement)) {
+            if (previousElement->isTextField())
+                return AutofillElements(WTFMove(previousElement), WTFMove(start));
+        }
+    } else {
+        RefPtr<HTMLInputElement> nextElement = nextAutofillableElement(start.ptr(), focusController);
+        if (nextElement && is<HTMLInputElement>(*nextElement)) {
+            if (nextElement->isPasswordField()) {
+                RefPtr<HTMLInputElement> elementAfternextElement = nextAutofillableElement(nextElement.get(), focusController);
+                bool hasDuplicatePasswordElements = elementAfternextElement && elementAfternextElement->isPasswordField();
+                if (hasDuplicatePasswordElements)
+                    return std::nullopt;
+
+                return AutofillElements(WTFMove(start), WTFMove(nextElement));
+            }
+        }
+    }
+
+    if (start->isPasswordField()) {
+        RefPtr<HTMLInputElement> previousElement = previousAutofillableElement(start.ptr(), focusController);
+        RefPtr<HTMLInputElement> nextElement = nextAutofillableElement(start.ptr(), focusController);
+        if (!previousElement && !nextElement)
+            return AutofillElements(nullptr, start.ptr());
+    }
+    return std::nullopt;
+}
+
+void AutofillElements::autofill(String username, String password)
+{
+    if (m_username) {
+        m_username->setValueForUser(username);
+        m_username->setAutoFilled();
+    }
+    if (m_password) {
+        m_password->setValueForUser(password);
+        m_password->setAutoFilled();
+    }
+}
+
+} // namespace WebCore

Copied: trunk/Source/WebCore/editing/ios/AutofillElements.h (from rev 222486, trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h) (0 => 222487)


--- trunk/Source/WebCore/editing/ios/AutofillElements.h	                        (rev 0)
+++ trunk/Source/WebCore/editing/ios/AutofillElements.h	2017-09-26 02:33:43 UTC (rev 222487)
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 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 "HTMLInputElement.h"
+
+namespace WebCore {
+
+class AutofillElements {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    WEBCORE_EXPORT static std::optional<AutofillElements> computeAutofillElements(Ref<HTMLInputElement>);
+    WEBCORE_EXPORT void autofill(String, String);
+private:
+    AutofillElements(RefPtr<HTMLInputElement>&&, RefPtr<HTMLInputElement>&&);
+    RefPtr<HTMLInputElement> m_username;
+    RefPtr<HTMLInputElement> m_password;
+};
+} // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (222486 => 222487)


--- trunk/Source/WebKit/ChangeLog	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/ChangeLog	2017-09-26 02:33:43 UTC (rev 222487)
@@ -1,3 +1,44 @@
+2017-09-25  Frederik Riedel  <[email protected]>
+
+        Expose way to set values of classified form controls as {Legacy WebKit, WebKit} SPI
+        https://bugs.webkit.org/show_bug.cgi?id=174394
+        <rdar://problem/33183504>
+
+        Reviewed by Ryosuke Niwa.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        * Shared/AssistedNodeInformation.cpp:
+        (WebKit::AssistedNodeInformation::encode const):
+        Encodes additional node information, including if the node is part of a login screen.
+        (WebKit::AssistedNodeInformation::decode):
+        Decodes the additional assisted node information.
+        * Shared/AssistedNodeInformation.h:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView acceptsAutofilledLoginCredentials]):
+        Determines if the WKContentView shows a login screen.
+        (-[WKContentView representingPageUrl]):
+        Returns the URL of the currently displayed web page.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView insertTextSuggestion:]):
+        Inserts the login credentials into the Web View.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::startAssistingNode):
+        Transfer the additional assistednode information (acceptsAutofilledLoginCredentials and representingPageUrl).
+        (WebKit::WebPageProxy::acceptsAutofilledLoginCredentials):
+        Returns if the Web View shows a login screen.
+        (WebKit::WebPageProxy::representingPageUrl):
+        Returns the Web View's URL.
+        (WebKit::WebPageProxy::autofillLoginCredentials):
+        Insert the credentials into the Web View.
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::getAssistedNodeInformation): Transports the information if the currently
+        highlighted node accepts autofilled login credentials.
+        (WebKit::WebPage::autofillLoginCredentials): Fills the login credentials into the
+        WebPage.
+
 2017-09-25  Youenn Fablet  <[email protected]>
 
         WebRTC video does not resume receiving when switching back to Safari 11 on iOS

Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (222486 => 222487)


--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2017-09-26 02:33:43 UTC (rev 222487)
@@ -43,6 +43,17 @@
 #import <UIKit/UIInterface_Private.h>
 #import <UIKit/UIKeyboardImpl.h>
 #import <UIKit/UIKeyboardIntl.h>
+#if __has_include(<UIKit/UIKeyboardLoginCredentialsSuggestion.h>)
+#import <UIKit/UIKeyboardLoginCredentialsSuggestion.h>
+#else
+#import <UIKit/UITextInput_Private.h>
+@interface UIKeyboardLoginCredentialsSuggestion : UITextSuggestion
+
+@property (nonatomic, assign) NSString *username;
+@property (nonatomic, assign) NSString *password;
+
+@end
+#endif
 #import <UIKit/UIKeyboard_Private.h>
 #import <UIKit/UILongPressGestureRecognizer_Private.h>
 #import <UIKit/UIPeripheralHost.h>

Modified: trunk/Source/WebKit/Shared/AssistedNodeInformation.cpp (222486 => 222487)


--- trunk/Source/WebKit/Shared/AssistedNodeInformation.cpp	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/Shared/AssistedNodeInformation.cpp	2017-09-26 02:33:43 UTC (rev 222487)
@@ -86,6 +86,8 @@
     encoder << value;
     encoder << valueAsNumber;
     encoder << title;
+    encoder << acceptsAutofilledLoginCredentials;
+    encoder << representingPageURL;
     encoder.encodeEnum(autofillFieldName);
 }
 
@@ -160,6 +162,12 @@
     if (!decoder.decode(result.title))
         return false;
 
+    if (!decoder.decode(result.acceptsAutofilledLoginCredentials))
+        return false;
+
+    if (!decoder.decode(result.representingPageURL))
+        return false;
+
     if (!decoder.decodeEnum(result.autofillFieldName))
         return false;
 

Modified: trunk/Source/WebKit/Shared/AssistedNodeInformation.h (222486 => 222487)


--- trunk/Source/WebKit/Shared/AssistedNodeInformation.h	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/Shared/AssistedNodeInformation.h	2017-09-26 02:33:43 UTC (rev 222487)
@@ -29,6 +29,7 @@
 #include <WebCore/AutocapitalizeTypes.h>
 #include <WebCore/Autofill.h>
 #include <WebCore/IntRect.h>
+#include <WebCore/URL.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebKit {
@@ -109,6 +110,8 @@
     String value;
     double valueAsNumber { 0 };
     String title;
+    bool acceptsAutofilledLoginCredentials { false };
+    WebCore::URL representingPageURL;
     WebCore::AutofillFieldName autofillFieldName { WebCore::AutofillFieldName::None };
 
     void encode(IPC::Encoder&) const;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (222486 => 222487)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2017-09-26 02:33:43 UTC (rev 222487)
@@ -79,6 +79,7 @@
 #include <WebCore/SearchPopupMenu.h>
 #include <WebCore/TextChecking.h>
 #include <WebCore/TextGranularity.h>
+#include <WebCore/URL.h>
 #include <WebCore/UserInterfaceLayoutDirection.h>
 #include <memory>
 #include <wtf/HashMap.h>
@@ -559,6 +560,9 @@
     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);
     void didHandleStartDataInteractionRequest(bool started);
@@ -1988,6 +1992,8 @@
     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 (222486 => 222487)


--- trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentView.mm	2017-09-26 02:33:43 UTC (rev 222487)
@@ -258,6 +258,16 @@
     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 (222486 => 222487)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2017-09-26 02:33:43 UTC (rev 222487)
@@ -2976,13 +2976,20 @@
 {
     [self.inputDelegate selectionDidChange:self];
 }
-    
+
+#if USE(APPLE_INTERNAL_SDK)
 - (void)insertTextSuggestion:(UITextSuggestion *)textSuggestion
 {
+    // FIXME: Replace NSClassFromString with actual class as soon as UIKit submitted the new class into the iOS SDK.
+    if ([textSuggestion isKindOfClass:NSClassFromString(@"UIKeyboardLoginCredentialsSuggestion")]) {
+        _page->autofillLoginCredentials([(UIKeyboardLoginCredentialsSuggestion *)textSuggestion username], [(UIKeyboardLoginCredentialsSuggestion *)textSuggestion password]);
+        return;
+    }
     id <_WKInputDelegate> inputDelegate = [_webView _inputDelegate];
     if ([inputDelegate respondsToSelector:@selector(_webView:insertTextSuggestion:inInputSession:)])
         [inputDelegate _webView:_webView insertTextSuggestion:textSuggestion inInputSession:_formInputSession.get()];
 }
+#endif // USE(APPLE_INTERNAL_SDK)
 
 - (NSString *)textInRange:(UITextRange *)range
 {

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (222486 => 222487)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2017-09-26 02:33:43 UTC (rev 222487)
@@ -891,6 +891,8 @@
 
 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 });
@@ -910,6 +912,21 @@
     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);
+}
+
 void WebPageProxy::showInspectorHighlight(const WebCore::Highlight& highlight)
 {
     m_pageClient.showInspectorHighlight(highlight);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (222486 => 222487)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2017-09-26 02:33:43 UTC (rev 222487)
@@ -576,6 +576,7 @@
     void stopInteraction();
     void performActionOnElement(uint32_t action);
     void focusNextAssistedNode(bool isForward, CallbackID);
+    void autofillLoginCredentials(const String&, const String&);
     void setAssistedNodeValue(const String&);
     void setAssistedNodeValueAsNumber(double);
     void setAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (222486 => 222487)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2017-09-26 02:33:43 UTC (rev 222487)
@@ -84,6 +84,7 @@
     PerformActionOnElement(uint32_t action)
     FocusNextAssistedNode(bool isForward, WebKit::CallbackID callbackID)
     SetAssistedNodeValue(String value)
+    AutofillLoginCredentials(String username, String password)
     SetAssistedNodeValueAsNumber(double value)
     SetAssistedNodeSelectedIndex(uint32_t index, bool allowMultipleSelection)
     ApplicationWillResignActive()

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (222486 => 222487)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2017-09-26 02:33:43 UTC (rev 222487)
@@ -53,6 +53,7 @@
 #import "WebProcess.h"
 #import <CoreText/CTFont.h>
 #import <WebCore/Autofill.h>
+#import <WebCore/AutofillElements.h>
 #import <WebCore/Chrome.h>
 #import <WebCore/DataDetection.h>
 #import <WebCore/DiagnosticLoggingClient.h>
@@ -2750,6 +2751,8 @@
         HTMLFormElement* form = element.form();
         if (form)
             information.formAction = form->getURLAttribute(WebCore::HTMLNames::actionAttr);
+        information.acceptsAutofilledLoginCredentials = !!WebCore::AutofillElements::computeAutofillElements(element);
+        information.representingPageURL = element.document().urlForBindings();
         information.autocapitalizeType = element.autocapitalizeType();
         information.isAutocorrect = element.shouldAutocorrect();
         if (element.isPasswordField())
@@ -2807,6 +2810,14 @@
     }
 }
 
+void WebPage::autofillLoginCredentials(const String& username, const String& password)
+{
+    if (is<HTMLInputElement>(*m_assistedNode)) {
+        if (auto autofillElements = AutofillElements::computeAutofillElements(downcast<HTMLInputElement>(*m_assistedNode)))
+            autofillElements->autofill(username, password);
+    }
+}
+
 void WebPage::setViewportConfigurationMinimumLayoutSize(const FloatSize& size)
 {
     if (m_viewportConfiguration.setMinimumLayoutSize(size))

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (222486 => 222487)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2017-09-26 02:33:43 UTC (rev 222487)
@@ -1,3 +1,20 @@
+2017-09-25  Frederik Riedel  <[email protected]>
+
+        Expose way to set values of classified form controls as {Legacy WebKit, WebKit} SPI
+        https://bugs.webkit.org/show_bug.cgi?id=174394
+        <rdar://problem/33183504>
+
+        Reviewed by Ryosuke Niwa.
+
+        * DOM/DOMHTMLInputElement.h:
+        * DOM/DOMHTMLInputElement.mm:
+        (-[DOMHTMLInputElement acceptsAutofilledLoginCredentials]):
+        Determines if this HTMLInputElement is part of a login screen.
+        (-[DOMHTMLInputElement representingPageUrl]):
+        Returns the webpage's URL that is currently displayed in the Web View.
+        (-[DOMHTMLInputElement insertTextSuggestion:]):
+        Inserts login credentials into the Web View.
+
 2017-09-25  Sam Weinig  <[email protected]>
 
         Remove unused EditorClient functions

Modified: trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.h (222486 => 222487)


--- trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.h	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.h	2017-09-26 02:33:43 UTC (rev 222487)
@@ -24,6 +24,9 @@
  */
 
 #import <WebKitLegacy/DOMHTMLElement.h>
+#if TARGET_OS_IPHONE
+#import <UIKit/UITextInputTraits.h>
+#endif
 
 @class DOMFileList;
 @class DOMHTMLFormElement;
@@ -31,7 +34,11 @@
 @class NSURL;
 
 WEBKIT_CLASS_AVAILABLE_MAC(10_4)
+#if TARGET_OS_IPHONE
+@interface DOMHTMLInputElement : DOMHTMLElement<UITextInputTraits>
+#else
 @interface DOMHTMLInputElement : DOMHTMLElement
+#endif
 @property (copy) NSString *accept;
 @property (copy) NSString *alt;
 @property BOOL autofocus WEBKIT_AVAILABLE_MAC(10_6);

Modified: trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.mm (222486 => 222487)


--- trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.mm	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Source/WebKitLegacy/mac/DOM/DOMHTMLInputElement.mm	2017-09-26 02:33:43 UTC (rev 222487)
@@ -33,6 +33,23 @@
 #import "DOMInternal.h"
 #import "DOMPrivate.h"
 #import "ExceptionHandlers.h"
+
+// FIXME <radar:34583628>: Simplyfy this once the UIKit work is available in the build.
+#if USE(APPLE_INTERNAL_SDK) && TARGET_OS_IPHONE
+#if __has_include(<UIKit/UIKeyboardLoginCredentialsSuggestion.h>)
+#import <UIKit/UIKeyboardLoginCredentialsSuggestion.h>
+#else
+#import <UIKit/UITextInput_Private.h>
+@interface UIKeyboardLoginCredentialsSuggestion : UITextSuggestion
+
+@property (nonatomic, assign) NSString *username;
+@property (nonatomic, assign) NSString *password;
+
+@end
+#endif // __has_include(<UIKit/UIKeyboardLoginCredentialsSuggestion.h>)
+#endif // USE(APPLE_INTERNAL_SDK) && TARGET_OS_IPHONE
+
+#import <WebCore/AutofillElements.h>
 #import <WebCore/FileList.h>
 #import <WebCore/HTMLElement.h>
 #import <WebCore/HTMLFormElement.h>
@@ -666,6 +683,29 @@
     IMPL->setValueForUser(inValue);
 }
 
+- (BOOL)acceptsAutofilledLoginCredentials
+{
+    WebCore::JSMainThreadNullState state;
+    return !!WebCore::AutofillElements::computeAutofillElements(*IMPL);
+}
+
+- (NSURL *)representingPageURL
+{
+    WebCore::JSMainThreadNullState state;
+    return [NSURL URLWithString:self.ownerDocument.URL];
+}
+
+#if USE(APPLE_INTERNAL_SDK) && TARGET_OS_IPHONE
+- (void)insertTextSuggestion:(UIKeyboardLoginCredentialsSuggestion *)credentialsSuggestion
+{
+    WebCore::JSMainThreadNullState state;
+    if (is<WebCore::HTMLInputElement>(IMPL)) {
+        if (auto autofillElements = WebCore::AutofillElements::computeAutofillElements(*IMPL))
+            autofillElements->autofill(credentialsSuggestion.username, credentialsSuggestion.password);
+    }
+}
+#endif // USE(APPLE_INTERNAL_SDK) && TARGET_OS_IPHONE
+
 @end
 
 WebCore::HTMLInputElement* core(DOMHTMLInputElement *wrapper)

Modified: trunk/Tools/ChangeLog (222486 => 222487)


--- trunk/Tools/ChangeLog	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Tools/ChangeLog	2017-09-26 02:33:43 UTC (rev 222487)
@@ -1,3 +1,17 @@
+2017-09-25  Frederik Riedel  <[email protected]>
+
+        Expose way to set values of classified form controls as {Legacy WebKit, WebKit} SPI
+        https://bugs.webkit.org/show_bug.cgi?id=174394
+        <rdar://problem/33183504>
+
+        Reviewed by Ryosuke Niwa.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm: Added.
+        (-[WKWebView _privateTextInput]): Testing helpers.
+        (TestWebKitAPI::TEST): Added test cases to test AutoFill for web views.
+        * TestWebKitAPI/ios/UIKitSPI.h:
+
 2017-09-25  Frederic Wang  <[email protected]>
 
         Change my status to reviewer and reformat with validate-committer-lists

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (222486 => 222487)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2017-09-26 02:33:43 UTC (rev 222487)
@@ -161,6 +161,7 @@
 		5120C83E1E67678F0025B250 /* WebsiteDataStoreCustomPaths.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5120C83B1E674E350025B250 /* WebsiteDataStoreCustomPaths.html */; };
 		51393E221523952D005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51393E1D1523944A005F39C5 /* DOMWindowExtensionBasic_Bundle.cpp */; };
 		5142B2731517C8C800C32B19 /* ContextMenuCanCopyURL.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5142B2721517C89100C32B19 /* ContextMenuCanCopyURL.html */; };
+		514958BE1F7427AC00E87BAD /* WKWebViewAutofillTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 514958BD1F7427AC00E87BAD /* WKWebViewAutofillTests.mm */; };
 		515BE16F1D428BB100DD7C68 /* StoreBlobToBeDeleted.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 515BE16E1D4288FF00DD7C68 /* StoreBlobToBeDeleted.html */; };
 		515BE1711D428E4B00DD7C68 /* StoreBlobThenDelete.mm in Sources */ = {isa = PBXBuildFile; fileRef = 515BE1701D428BD100DD7C68 /* StoreBlobThenDelete.mm */; };
 		51714EB41CF8C78C004723C4 /* WebProcessKillIDBCleanup-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51714EB21CF8C761004723C4 /* WebProcessKillIDBCleanup-1.html */; };
@@ -1242,6 +1243,7 @@
 		51393E1E1523944A005F39C5 /* DOMWindowExtensionBasic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMWindowExtensionBasic.cpp; sourceTree = "<group>"; };
 		5142B2701517C88B00C32B19 /* ContextMenuCanCopyURL.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContextMenuCanCopyURL.mm; sourceTree = "<group>"; };
 		5142B2721517C89100C32B19 /* ContextMenuCanCopyURL.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = ContextMenuCanCopyURL.html; sourceTree = "<group>"; };
+		514958BD1F7427AC00E87BAD /* WKWebViewAutofillTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewAutofillTests.mm; sourceTree = "<group>"; };
 		515BE16E1D4288FF00DD7C68 /* StoreBlobToBeDeleted.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = StoreBlobToBeDeleted.html; sourceTree = "<group>"; };
 		515BE1701D428BD100DD7C68 /* StoreBlobThenDelete.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StoreBlobThenDelete.mm; sourceTree = "<group>"; };
 		51714EB21CF8C761004723C4 /* WebProcessKillIDBCleanup-1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "WebProcessKillIDBCleanup-1.html"; sourceTree = "<group>"; };
@@ -2119,6 +2121,7 @@
 				F4D4F3B71E4E36E400BB2767 /* DataInteractionTests.mm */,
 				7560917719259C59009EF06E /* MemoryCacheAddImageToCacheIOS.mm */,
 				F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */,
+				514958BD1F7427AC00E87BAD /* WKWebViewAutofillTests.mm */,
 			);
 			path = ios;
 			sourceTree = "<group>";
@@ -3453,6 +3456,7 @@
 				2D4CF8BD1D8360CC0001CE8D /* WKThumbnailView.mm in Sources */,
 				51C683DE1EA134E800650183 /* WKURLSchemeHandler-1.mm in Sources */,
 				5182C22E1F2BCE540059BA7C /* WKURLSchemeHandler-leaks.mm in Sources */,
+				514958BE1F7427AC00E87BAD /* WKWebViewAutofillTests.mm in Sources */,
 				2EFF06D71D8AF34A0004BB30 /* WKWebViewCandidateTests.mm in Sources */,
 				A14FC5851B89739100D107EB /* WKWebViewConfigurationExtras.mm in Sources */,
 				7C417F331D19E14800B8EF53 /* WKWebViewDefaultNavigationDelegate.mm in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm (0 => 222487)


--- trunk/Tools/TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/WKWebViewAutofillTests.mm	2017-09-26 02:33:43 UTC (rev 222487)
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2017 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"
+
+#if WK_API_ENABLED && PLATFORM(IOS) && USE(APPLE_INTERNAL_SDK)
+
+#import "PlatformUtilities.h"
+#import "TestWKWebView.h"
+#import "UIKitSPI.h"
+
+#import <UIKit/UITextInputTraits_Private.h>
+#import <UIKit/UITextInput_Private.h>
+
+// 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
+
+@property (nonatomic, assign) NSString *username;
+@property (nonatomic, assign) NSString *password;
+
+@end
+#endif
+
+static UIKeyboardLoginCredentialsSuggestion *createUIKeyboardLoginCredentialsSuggestion()
+{
+    return [[NSClassFromString(@"UIKeyboardLoginCredentialsSuggestion") new] autorelease];
+}
+
+typedef UIView <UITextInputPrivate, UITextInputTraits_Private, UITextInputTraits_Private_Staging_34583628>  AutofillCandidateView;
+
+@implementation WKWebView (AutofillTestHelpers)
+
+- (AutofillCandidateView *)_privateTextInput
+{
+    return (AutofillCandidateView *)[self valueForKey:@"_currentContentView"];
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WKWebViewAutofillTests, UsernameAndPasswordField)
+{
+    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
+    AutofillCandidateView *contentView = [webView _privateTextInput];
+    [webView synchronouslyLoadHTMLString:@"<input id='user' type='email'><input id='password' type='password'>"];
+    [webView stringByEvaluatingJavaScript:@"user.focus()"];
+    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+
+    [webView stringByEvaluatingJavaScript:@"password.focus()"];
+    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+
+    UIKeyboardLoginCredentialsSuggestion *credentialSuggestion = createUIKeyboardLoginCredentialsSuggestion();
+    credentialSuggestion.username = @"frederik";
+    credentialSuggestion.password = @"famos";
+
+    [contentView insertTextSuggestion:credentialSuggestion];
+
+    EXPECT_WK_STREQ(credentialSuggestion.username, [webView stringByEvaluatingJavaScript:@"user.value"]);
+    EXPECT_WK_STREQ(credentialSuggestion.password, [webView stringByEvaluatingJavaScript:@"password.value"]);
+
+    [webView release];
+}
+
+TEST(WKWebViewAutofillTests, UsernameAndPasswordFieldSeparatedByRadioButton)
+{
+    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
+    AutofillCandidateView *contentView = [webView _privateTextInput];
+    [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);
+
+    [webView stringByEvaluatingJavaScript:@"password.focus()"];
+    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+
+    UIKeyboardLoginCredentialsSuggestion *credentialSuggestion = createUIKeyboardLoginCredentialsSuggestion();
+    credentialSuggestion.username = @"frederik";
+    credentialSuggestion.password = @"famos";
+
+    [contentView insertTextSuggestion:credentialSuggestion];
+
+    EXPECT_WK_STREQ(credentialSuggestion.username, [webView stringByEvaluatingJavaScript:@"user.value"]);
+    EXPECT_WK_STREQ(credentialSuggestion.password, [webView stringByEvaluatingJavaScript:@"password.value"]);
+
+    [webView release];
+}
+
+TEST(WKWebViewAutofillTests, TwoTextFields)
+{
+    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
+    AutofillCandidateView *contentView = [webView _privateTextInput];
+    [webView synchronouslyLoadHTMLString:@"<input id='text1' type='email'><input id='text2' type='text'>"];
+    [webView stringByEvaluatingJavaScript:@"text1.focus()"];
+    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+
+    [webView stringByEvaluatingJavaScript:@"text2.focus()"];
+    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+}
+
+TEST(WKWebViewAutofillTests, StandalonePasswordField)
+{
+    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
+    AutofillCandidateView *contentView = [webView _privateTextInput];
+    [webView synchronouslyLoadHTMLString:@"<input id='password' type='password'>"];
+    [webView stringByEvaluatingJavaScript:@"password.focus()"];
+    EXPECT_TRUE(contentView.acceptsAutofilledLoginCredentials);
+
+    UIKeyboardLoginCredentialsSuggestion *credentialSuggestion = createUIKeyboardLoginCredentialsSuggestion();
+    credentialSuggestion.username = @"frederik";
+    credentialSuggestion.password = @"famos";
+
+    [contentView insertTextSuggestion:credentialSuggestion];
+
+    EXPECT_WK_STREQ(credentialSuggestion.password, [webView stringByEvaluatingJavaScript:@"password.value"]);
+
+    [webView release];
+}
+
+TEST(WKWebViewAutofillTests, StandaloneTextField)
+{
+    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
+    AutofillCandidateView *contentView = [webView _privateTextInput];
+    [webView synchronouslyLoadHTMLString:@"<input id='textfield' type='text'>"];
+    [webView stringByEvaluatingJavaScript:@"textfield.focus()"];
+    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+
+    [webView release];
+}
+
+TEST(WKWebViewAutofillTests, AccountCreationPage)
+{
+    TestWKWebView *webView = [[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
+    AutofillCandidateView *contentView = [webView _privateTextInput];
+    [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);
+
+    [webView stringByEvaluatingJavaScript:@"password.focus()"];
+    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+
+    [webView stringByEvaluatingJavaScript:@"confirm_password.focus()"];
+    EXPECT_FALSE(contentView.acceptsAutofilledLoginCredentials);
+
+    [webView release];
+}
+
+
+} // namespace TestWebKitAPI
+
+#endif // WK_API_ENABLED && PLATFORM(IOS) && USE(APPLE_INTERNAL_SDK)

Modified: trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h (222486 => 222487)


--- trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h	2017-09-26 01:40:30 UTC (rev 222486)
+++ trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h	2017-09-26 02:33:43 UTC (rev 222487)
@@ -25,6 +25,8 @@
 
 #if PLATFORM(IOS)
 
+#import <UIKit/UITextInputTraits.h>
+
 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
 @protocol UIDragSession;
 @class UIDragInteraction;
@@ -35,7 +37,14 @@
 
 #import <UIKit/UIApplication_Private.h>
 #import <UIKit/UIDragInteraction_Private.h>
+#import <UIKit/UITextInputTraits_Private.h>
+#import <UIKit/UITextSuggestion.h>
 
+
+@protocol UITextInputTraits_Private_Staging_34583628 <NSObject, UITextInputTraits>
+@property (nonatomic, readonly) BOOL acceptsAutofilledLoginCredentials;
+@end
+
 #else
 
 WTF_EXTERN_C_BEGIN
@@ -51,6 +60,10 @@
 @end
 #endif // __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
 
+@protocol UITextInputTraits_Private <NSObject, UITextInputTraits>
+@property (nonatomic, readonly) BOOL acceptsAutofilledLoginCredentials;
+@end
+
 #endif
 
 #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to