Title: [268866] trunk
Revision
268866
Author
[email protected]
Date
2020-10-22 08:55:54 -0700 (Thu, 22 Oct 2020)

Log Message

[iOS] Prevent presentation of input peripherals when focusing form controls with a validation message
https://bugs.webkit.org/show_bug.cgi?id=218004
<rdar://problem/70507678>

Reviewed by Wenson Hsieh.

Source/WebCore:

Added isFocusingWithValidationMessage() to HTMLFormControlElement so
that the state can be encoded in FocusedElementInformation and sent to
the UIProcess.

See WebKit Changelog for more information.

Test: fast/forms/ios/input-peripherals-with-validation-message.html

* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::isFocusingWithValidationMessage const):
(WebCore::HTMLFormControlElement::focusAndShowValidationMessage):
* html/HTMLFormControlElement.h:

Source/WebKit:

Interactive form validation can result in the presentation of a
validation message bubble near the first form control that has invalid
data. Prior to displaying the message, the invalid control is focused.
On iOS, this also has the effect of also presenting a virtual keyboard
or another custom input peripheral, such as a context menu for date
inputs.

Attempting to present both the validation message and custom input
peripheral can leave the view in an inconsistent state. For example,
<select> popovers have a strange flashing behavior when presented
alongside a validation message, and context menus can fail to present
entirely.

In order to address these issues, we should never attempt to present
both a validation message and an input peripheral. Instead, we can
prevent the presentation of input peripherals when the focused control
is presenting a validation message. This behavior matches macOS. Note
that we still present the keyboard for controls that have a keyboard
view, since the keyboard area does overlap the area where a validation
message is presented.

* Shared/FocusedElementInformation.cpp:
(WebKit::FocusedElementInformation::encode const):
(WebKit::FocusedElementInformation::decode):
* Shared/FocusedElementInformation.h:

Added isFocusingWithValidationMessage to the struct, so that the UIProcess
knows that the element gained focus due to the presentation of a
validation message.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):

Prevent an input view from being shown if the control does not present
a keyboard and was focused with a validation message.

(-[WKContentView _elementDidBlur]):
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getFocusedElementInformation):

LayoutTests:

Added a test which verifies that focusing on a date input as a result
of presenting a validation message, successfully presents the message,
and does not present a context menu. The test also ensures that controls
that present a keyboard, such as text inputs, present both the message
and the keyboard.

* fast/forms/ios/input-peripherals-with-validation-message-expected.txt: Added.
* fast/forms/ios/input-peripherals-with-validation-message.html: Added.
* resources/ui-helper.js:
(window.UIHelper.isShowingPopover):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (268865 => 268866)


--- trunk/LayoutTests/ChangeLog	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/LayoutTests/ChangeLog	2020-10-22 15:55:54 UTC (rev 268866)
@@ -1,3 +1,22 @@
+2020-10-22  Aditya Keerthi  <[email protected]>
+
+        [iOS] Prevent presentation of input peripherals when focusing form controls with a validation message
+        https://bugs.webkit.org/show_bug.cgi?id=218004
+        <rdar://problem/70507678>
+
+        Reviewed by Wenson Hsieh.
+
+        Added a test which verifies that focusing on a date input as a result
+        of presenting a validation message, successfully presents the message,
+        and does not present a context menu. The test also ensures that controls
+        that present a keyboard, such as text inputs, present both the message
+        and the keyboard.
+
+        * fast/forms/ios/input-peripherals-with-validation-message-expected.txt: Added.
+        * fast/forms/ios/input-peripherals-with-validation-message.html: Added.
+        * resources/ui-helper.js:
+        (window.UIHelper.isShowingPopover):
+
 2020-10-22  Peng Liu  <[email protected]>
 
         Let webkitDisplayingFullscreen() return true when a video element’s fullscreen mode is not VideoFullscreenModeNone

Added: trunk/LayoutTests/fast/forms/ios/input-peripherals-with-validation-message-expected.txt (0 => 268866)


--- trunk/LayoutTests/fast/forms/ios/input-peripherals-with-validation-message-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/input-peripherals-with-validation-message-expected.txt	2020-10-22 15:55:54 UTC (rev 268866)
@@ -0,0 +1,25 @@
+Test that input peripherals are not presented when focusing form controls with a validation message.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Tap on submit button with an empty required date input.
+PASS document.activeElement is date
+PASS isShowingValidationMessage is true
+PASS hasInputSession is false
+
+Dismiss validation bubble and tap on date input.
+PASS document.activeElement is date
+PASS isShowingValidationMessage is false
+PASS hasInputSession is true
+
+Tap on submit button with an empty required text input.
+PASS document.activeElement is text
+PASS isShowingValidationMessage is true
+PASS hasInputSession is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+
+

Added: trunk/LayoutTests/fast/forms/ios/input-peripherals-with-validation-message.html (0 => 268866)


--- trunk/LayoutTests/fast/forms/ios/input-peripherals-with-validation-message.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/input-peripherals-with-validation-message.html	2020-10-22 15:55:54 UTC (rev 268866)
@@ -0,0 +1,67 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<form>
+<input type="date" id="date" required>
+<br>
+<input type="text" id="text" required>
+<br>
+<input type="submit" id="submit">
+</form>
+<script>
+jsTestIsAsync = true;
+
+description("Test that input peripherals are not presented when focusing form controls with a validation message.");
+addEventListener("load", async () => {
+    if (!window.testRunner)
+        return;
+
+    debug("Tap on submit button with an empty required date input.");
+    await UIHelper.activateElementAndWaitForInputSession(submit);
+    shouldBe("document.activeElement", "date");
+
+    isShowingValidationMessage = await UIHelper.isShowingPopover();
+    shouldBeTrue("isShowingValidationMessage");
+
+    hasInputSession = await UIHelper.hasInputSession();
+    shouldBeFalse("hasInputSession");
+
+    debug("\nDismiss validation bubble and tap on date input.");
+    await UIHelper.tapAt(1, 1);
+    await UIHelper.waitForPopoverToDismiss();
+    await UIHelper.activateElementAndWaitForInputSession(date);
+
+    shouldBe("document.activeElement", "date");
+
+    isShowingValidationMessage = await UIHelper.isShowingPopover();
+    shouldBeFalse("isShowingValidationMessage");
+
+    hasInputSession = await UIHelper.hasInputSession();
+    shouldBeTrue("hasInputSession");
+
+    await UIHelper.tapAt(1, 1);
+    await UIHelper.waitForContextMenuToHide();
+
+    // Fill date, so that the text input receives the validation message on submit.
+    date.value = "2020-10-20";
+
+    debug("\nTap on submit button with an empty required text input.");
+    await UIHelper.activateElementAndWaitForInputSession(submit);
+    shouldBe("document.activeElement", "text");
+
+    isShowingValidationMessage = await UIHelper.isShowingPopover();
+    shouldBeTrue("isShowingValidationMessage");
+
+    hasInputSession = await UIHelper.hasInputSession();
+    shouldBeTrue("hasInputSession");
+
+    finishJSTest();
+});
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/resources/ui-helper.js (268865 => 268866)


--- trunk/LayoutTests/resources/ui-helper.js	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/LayoutTests/resources/ui-helper.js	2020-10-22 15:55:54 UTC (rev 268866)
@@ -580,6 +580,13 @@
         });
     }
 
+    static isShowingPopover()
+    {
+        return new Promise(resolve => {
+            testRunner.runUIScript("uiController.isShowingPopover", result => resolve(result === "true"));
+        });
+    }
+
     static hasInputSession()
     {
         return new Promise(resolve => {

Modified: trunk/Source/WebCore/ChangeLog (268865 => 268866)


--- trunk/Source/WebCore/ChangeLog	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebCore/ChangeLog	2020-10-22 15:55:54 UTC (rev 268866)
@@ -1,3 +1,24 @@
+2020-10-22  Aditya Keerthi  <[email protected]>
+
+        [iOS] Prevent presentation of input peripherals when focusing form controls with a validation message
+        https://bugs.webkit.org/show_bug.cgi?id=218004
+        <rdar://problem/70507678>
+
+        Reviewed by Wenson Hsieh.
+
+        Added isFocusingWithValidationMessage() to HTMLFormControlElement so
+        that the state can be encoded in FocusedElementInformation and sent to
+        the UIProcess.
+
+        See WebKit Changelog for more information.
+
+        Test: fast/forms/ios/input-peripherals-with-validation-message.html
+
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::isFocusingWithValidationMessage const):
+        (WebCore::HTMLFormControlElement::focusAndShowValidationMessage):
+        * html/HTMLFormControlElement.h:
+
 2020-10-22  Peng Liu  <[email protected]>
 
         Let webkitDisplayingFullscreen() return true when a video element’s fullscreen mode is not VideoFullscreenModeNone

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (268865 => 268866)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2020-10-22 15:55:54 UTC (rev 268866)
@@ -49,6 +49,7 @@
 #include "ValidationMessage.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/Ref.h>
+#include <wtf/SetForScope.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
@@ -496,6 +497,11 @@
     return false;
 }
 
+bool HTMLFormControlElement::isFocusingWithValidationMessage() const
+{
+    return m_isFocusingWithValidationMessage;
+}
+
 bool HTMLFormControlElement::isShowingValidationMessage() const
 {
     return m_validationMessage && m_validationMessage->isVisible();
@@ -529,6 +535,8 @@
 
 void HTMLFormControlElement::focusAndShowValidationMessage()
 {
+    SetForScope<bool> isFocusingWithValidationMessageScope(m_isFocusingWithValidationMessage, true);
+
     // Calling focus() will scroll the element into view.
     focus();
 

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.h (268865 => 268866)


--- trunk/Source/WebCore/html/HTMLFormControlElement.h	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.h	2020-10-22 15:55:54 UTC (rev 268866)
@@ -106,6 +106,7 @@
     bool reportValidity();
     void focusAndShowValidationMessage();
     bool isShowingValidationMessage() const;
+    WEBCORE_EXPORT bool isFocusingWithValidationMessage() const;
     // This must be called when a validation constraint or control value is changed.
     void updateValidity();
     void setCustomValidity(const String&) override;
@@ -180,6 +181,8 @@
     bool needsMouseFocusableQuirk() const;
 
     std::unique_ptr<ValidationMessage> m_validationMessage;
+    bool m_isFocusingWithValidationMessage { false };
+
     unsigned m_disabled : 1;
     unsigned m_isReadOnly : 1;
     unsigned m_isRequired : 1;

Modified: trunk/Source/WebKit/ChangeLog (268865 => 268866)


--- trunk/Source/WebKit/ChangeLog	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebKit/ChangeLog	2020-10-22 15:55:54 UTC (rev 268866)
@@ -1,3 +1,51 @@
+2020-10-22  Aditya Keerthi  <[email protected]>
+
+        [iOS] Prevent presentation of input peripherals when focusing form controls with a validation message
+        https://bugs.webkit.org/show_bug.cgi?id=218004
+        <rdar://problem/70507678>
+
+        Reviewed by Wenson Hsieh.
+
+        Interactive form validation can result in the presentation of a
+        validation message bubble near the first form control that has invalid
+        data. Prior to displaying the message, the invalid control is focused.
+        On iOS, this also has the effect of also presenting a virtual keyboard
+        or another custom input peripheral, such as a context menu for date
+        inputs.
+
+        Attempting to present both the validation message and custom input
+        peripheral can leave the view in an inconsistent state. For example,
+        <select> popovers have a strange flashing behavior when presented
+        alongside a validation message, and context menus can fail to present
+        entirely.
+
+        In order to address these issues, we should never attempt to present
+        both a validation message and an input peripheral. Instead, we can
+        prevent the presentation of input peripherals when the focused control
+        is presenting a validation message. This behavior matches macOS. Note
+        that we still present the keyboard for controls that have a keyboard
+        view, since the keyboard area does overlap the area where a validation
+        message is presented.
+
+        * Shared/FocusedElementInformation.cpp:
+        (WebKit::FocusedElementInformation::encode const):
+        (WebKit::FocusedElementInformation::decode):
+        * Shared/FocusedElementInformation.h:
+
+        Added isFocusingWithValidationMessage to the struct, so that the UIProcess
+        knows that the element gained focus due to the presentation of a
+        validation message.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:]):
+
+        Prevent an input view from being shown if the control does not present
+        a keyboard and was focused with a validation message.
+
+        (-[WKContentView _elementDidBlur]):
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::getFocusedElementInformation):
+
 2020-10-22  Carlos Garcia Campos  <[email protected]>
 
         WebDriver: handle key events with non-ASCII unicode code point

Modified: trunk/Source/WebKit/Shared/FocusedElementInformation.cpp (268865 => 268866)


--- trunk/Source/WebKit/Shared/FocusedElementInformation.cpp	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebKit/Shared/FocusedElementInformation.cpp	2020-10-22 15:55:54 UTC (rev 268866)
@@ -110,6 +110,7 @@
     encoder << shouldAvoidResizingWhenInputViewBoundsChange;
     encoder << shouldAvoidScrollingWhenFocusedContentIsVisible;
     encoder << shouldUseLegacySelectPopoverDismissalBehaviorInDataActivation;
+    encoder << isFocusingWithValidationMessage;
 }
 
 bool FocusedElementInformation::decode(IPC::Decoder& decoder, FocusedElementInformation& result)
@@ -246,6 +247,9 @@
     if (!decoder.decode(result.shouldUseLegacySelectPopoverDismissalBehaviorInDataActivation))
         return false;
 
+    if (!decoder.decode(result.isFocusingWithValidationMessage))
+        return false;
+
     return true;
 }
 #endif

Modified: trunk/Source/WebKit/Shared/FocusedElementInformation.h (268865 => 268866)


--- trunk/Source/WebKit/Shared/FocusedElementInformation.h	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebKit/Shared/FocusedElementInformation.h	2020-10-22 15:55:54 UTC (rev 268866)
@@ -144,6 +144,7 @@
     bool shouldAvoidResizingWhenInputViewBoundsChange { false };
     bool shouldAvoidScrollingWhenFocusedContentIsVisible { false };
     bool shouldUseLegacySelectPopoverDismissalBehaviorInDataActivation { false };
+    bool isFocusingWithValidationMessage { false };
 
     FocusedElementIdentifier focusedElementIdentifier { 0 };
 

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (268865 => 268866)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2020-10-22 15:55:54 UTC (rev 268866)
@@ -5940,6 +5940,10 @@
         }
     }();
 
+    // Do not present input peripherals if a validation message is being displayed.
+    if (information.isFocusingWithValidationMessage && !_isFocusingElementWithKeyboard)
+        shouldShowInputView = NO;
+
     if (blurPreviousNode) {
         // Defer view updates until the end of this function to avoid a noticeable flash when switching focus
         // between elements that require the keyboard.
@@ -6072,6 +6076,7 @@
     _focusedElementInformation.shouldAvoidResizingWhenInputViewBoundsChange = false;
     _focusedElementInformation.shouldAvoidScrollingWhenFocusedContentIsVisible = false;
     _focusedElementInformation.shouldUseLegacySelectPopoverDismissalBehaviorInDataActivation = false;
+    _focusedElementInformation.isFocusingWithValidationMessage = false;
     _inputPeripheral = nil;
     _focusRequiresStrongPasswordAssistance = NO;
     _additionalContextForStrongPasswordAssistance = nil;

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


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2020-10-22 15:22:39 UTC (rev 268865)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2020-10-22 15:55:54 UTC (rev 268866)
@@ -3052,6 +3052,9 @@
     if (is<HTMLElement>(focusedElement))
         information.isSpellCheckingEnabled = downcast<HTMLElement>(*focusedElement).spellcheck();
 
+    if (is<HTMLFormControlElement>(focusedElement))
+        information.isFocusingWithValidationMessage = downcast<HTMLFormControlElement>(*focusedElement).isFocusingWithValidationMessage();
+
     information.minimumScaleFactor = minimumPageScaleFactor();
     information.maximumScaleFactor = maximumPageScaleFactor();
     information.maximumScaleFactorIgnoringAlwaysScalable = maximumPageScaleFactorIgnoringAlwaysScalable();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to