<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[243808] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/243808">243808</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2019-04-03 10:06:04 -0700 (Wed, 03 Apr 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] Should be able to dismiss picker or popover using the keyboard
https://bugs.webkit.org/show_bug.cgi?id=196272
<rdar://problem/48943170>

Patch by Daniel Bates <dabates@apple.com> on 2019-04-03
Reviewed by Wenson Hsieh.

Source/WebKit:

Intercept key events and route them to the current input peripheral (if we have one). Add a base key event handler
for all form peripherals that dismisses the accessory when either the Escape key is pressed or Command + . is pressed.
I will fix this issue for the file upload picker/popover in <https://bugs.webkit.org/show_bug.cgi?id=196287>.

* SourcesCocoa.txt: Add file WKFormPeripheralBase.mm.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView endEditingAndUpdateFocusAppearanceWithReason]): Added.
(-[WKContentView resignFirstResponderForWebView]): Write in terms of -endEditingAndUpdateFocusAppearance.
(-[WKContentView inputView]): Code style nit while I am here; add an empty line to demarcate the "crazy"
code that the FIXME is referring to and should ideally be removed from the code that is sane to always do.
(-[WKContentView accessoryDone]): When the accessory is dismissed via the Done button (iPhone) or by pressing
Escape or Command + . using a hardware keyboard (iPhone or iPad) then end the current editing session, but
do not resign first responder status as the page activation state should not be changed.
(-[WKContentView _handleKeyUIEvent:]): Bring back this code when building with USE(UIKIT_KEYBOARD_ADDITIONS)
as we need to route key events to the input peripheral (if we have one). If the input peripheral handles it
then we're done: no need to let UIKit or WebKit handle it when building with USE(UIKIT_KEYBOARD_ADDITIONS),
respectively. If the input peripheral does not handle it then do what we do now.
(-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
If the element is re-focused and we have an input peripheral then we want to ensure we are first responder,
reveal the focused element, update the accessory and tell the peripheral that editing has begun (again).
For all other element re-focusing where we don't have a peripheral do what we do now. Also, update _isEditable
to reflect whether the focused element contains selectable text. This is what UIKit wants to know when it queries
-isEditable. Now that we no longer blur the focused element on iPad when the popover is dismissed and keep the
peripheral until there is a focus change we need to ensure that we give the correct answer to UIKit on view
editability. Otherwise, UIKit thinks it needs to update the text selection state when a popup button is tapped
again (as part of its gesture recognizer logic) and this causes an assertion failure in UIKit after it calls back
into us to ask for selection details, which we correctly respond with the equivalent of "we have none" and is
not the answer UIKit expects since we told it we are editable. (Currently we manage to get away with telling UIKit
we are always editable because it is not possible to perform a selection operation when we have a popover open.
Closing the popover blurs the element, setting -isEditable to NO and deallocates the peripheral avoiding this issue).
* UIProcess/ios/forms/WKFormColorControl.h:
* UIProcess/ios/forms/WKFormColorControl.mm:
(-[WKColorPopover controlEndEditing]): Dismiss the popover.
(-[WKFormColorControl initWithView:]): Modified to call base class initializer.
(-[WKFormColorControl assistantView]): Deleted.
(-[WKFormColorControl beginEditing]): Deleted.
(-[WKFormColorControl endEditing]): Deleted.
* UIProcess/ios/forms/WKFormInputControl.h:
* UIProcess/ios/forms/WKFormInputControl.mm:
(-[WKFormInputControl initWithView:]): Modified to call base class initializer.
(-[WKFormInputControl dateTimePickerCalendarType]): Write in terms of self.control.
(-[WKDateTimePopover controlEndEditing]): Dismiss the popover and tell the controller that editing ended.
(-[WKFormInputControl beginEditing]): Deleted.
(-[WKFormInputControl endEditing]): Deleted.
(-[WKFormInputControl assistantView]): Deleted.
* UIProcess/ios/forms/WKFormPeripheral.h:
* UIProcess/ios/forms/WKFormPeripheralBase.h: Added.
* UIProcess/ios/forms/WKFormPeripheralBase.mm: Added.
(-[WKFormPeripheralBase initWithView:control:]): Take ownership of the passed WKFormControl.
(-[WKFormPeripheralBase beginEditing]): Turn around and tell the control.
(-[WKFormPeripheralBase endEditing]): Ditto.
(-[WKFormPeripheralBase assistantView]): Ditto.
(-[WKFormPeripheralBase control]): Return the control.
(-[WKFormPeripheralBase handleKeyEvent:]): Dismiss the accessory (in the same way we dismiss when the Done
button is pressed on iPhone) on keydown of the Escape key or when we receive a UIKeyInputEscape event (for
Command + .).
* UIProcess/ios/forms/WKFormSelectControl.h:
* UIProcess/ios/forms/WKFormSelectControl.mm:
(-[WKFormSelectControl initWithView:]): Modified to call base class initializer.
(-[WKFormSelectControl selectRow:inComponent:extendingSelection:]): Write in terms of self.control.
(-[WKFormSelectControl selectFormPopoverTitle]): Ditto.
(-[WKFormSelectControl assistantView]): Deleted.
(-[WKFormSelectControl beginEditing]): Deleted.
(-[WKFormSelectControl endEditing]): Deleted.
* UIProcess/ios/forms/WKFormSelectPopover.mm:
(-[WKSelectPopover controlEndEditing]): Dismiss the popover.
* WebKit.xcodeproj/project.pbxproj: Add files WKFormPeripheralBase.{h, mm}.

LayoutTests:

Add test to ensure that pressing Escape or Command + . dismisses a picker.

* fast/forms/ios/dismiss-picker-using-keyboard-expected.txt: Added.
* fast/forms/ios/dismiss-picker-using-keyboard.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitSourcesCocoatxt">trunk/Source/WebKit/SourcesCocoa.txt</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosWKContentViewInteractionh">trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormColorControlh">trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormColorControlmm">trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormInputControlh">trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormInputControlmm">trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormPeripheralh">trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheral.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormSelectControlh">trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormSelectControlmm">trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormSelectPopovermm">trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectPopover.mm</a></li>
<li><a href="#trunkSourceWebKitWebKitxcodeprojprojectpbxproj">trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastformsiosdismisspickerusingkeyboardexpectedtxt">trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastformsiosdismisspickerusingkeyboardhtml">trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard.html</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormPeripheralBaseh">trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosformsWKFormPeripheralBasemm">trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog      2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/LayoutTests/ChangeLog 2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2019-04-03  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Should be able to dismiss picker or popover using the keyboard
+        https://bugs.webkit.org/show_bug.cgi?id=196272
+        <rdar://problem/48943170>
+
+        Reviewed by Wenson Hsieh.
+
+        Add test to ensure that pressing Escape or Command + . dismisses a picker.
+
+        * fast/forms/ios/dismiss-picker-using-keyboard-expected.txt: Added.
+        * fast/forms/ios/dismiss-picker-using-keyboard.html: Added.
+
</ins><span class="cx"> 2019-04-03  Sihui Liu  <sihui_liu@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Blob type cannot be stored correctly in IDB when IDBObjectStore has autoIncrement and keyPath options
</span></span></pre></div>
<a id="trunkLayoutTestsfastformsiosdismisspickerusingkeyboardexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard-expected.txt (0 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard-expected.txt                              (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard-expected.txt 2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+Tests that pressing the Escape key or Command + . dismisses a picker without causing a value change.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Dismiss by pressing escape:
+
+For color:
+PASS elementToTest.value is "#000000"
+
+For date:
+PASS elementToTest.value is "2019-03-26"
+
+For datetime-local:
+PASS elementToTest.value is "2019-03-26T14:28:05.455"
+
+For month:
+PASS elementToTest.value is "2019-03"
+
+For select:
+PASS elementToTest.value is "First"
+
+For time:
+PASS elementToTest.value is "14:28"
+
+Dismiss by pressing Command + .:
+
+For color:
+PASS elementToTest.value is "#000000"
+
+For date:
+PASS elementToTest.value is "2019-03-26"
+
+For datetime-local:
+PASS elementToTest.value is "2019-03-26T14:28:05.455"
+
+For month:
+PASS elementToTest.value is "2019-03"
+
+For select:
+PASS elementToTest.value is "First"
+
+For time:
+PASS elementToTest.value is "14:28"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastformsiosdismisspickerusingkeyboardhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard.html (0 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard.html                              (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/dismiss-picker-using-keyboard.html 2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -0,0 +1,86 @@
</span><ins>+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../../resources/js-test.js"></script>
+<script src="../../../resources/ui-helper.js"></script>
+</head>
+<body>
+<!-- Place the test container above the console output to avoid the need to compensate for page scroll. -->
+<div id="test-container">
+    <p><input type="color" class="test" data-test-name="color"></p>
+    <p><input type="date" class="test" data-test-name="date" value="2019-03-26"></p>
+    <p><input type="datetime-local" class="test" data-test-name="datetime-local" value="2019-03-26T14:28:05.455"></p>
+    <p><input type="month" class="test" data-test-name="month" value="2019-03"></p>
+    <p><select class="test" data-test-name="select">
+        <option>First</option>
+        <option>Second</option>
+    </select></p>
+    <p><input type="time" class="test" data-test-name="time" value="14:28"></p>
+</div>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+window.jsTestIsAsync = true;
+
+let elementToTest;
+
+const modifierDisplayNameMap = {
+    "altKey": "Option",
+    "ctrlKey": "Control",
+    "metaKey": "Command",
+    "shiftKey": "Shift",
+    "capsLockKey": "Caps Lock",
+}
+
+class KeyCommand {
+    constructor(key, modifiers = [])
+    {
+        this.key = key;
+        this.modifiers = modifiers;
+    }
+
+    toString()
+    {
+        let readableCommand = this.modifiers.map((modifier) => modifierDisplayNameMap[modifier]);
+        readableCommand.push(this.key);
+        return readableCommand.join(" + ");
+    }
+}
+
+function done()
+{
+    let testContainer = document.getElementById("test-container");
+    document.body.removeChild(testContainer);
+    finishJSTest()
+}
+
+async function runTest()
+{
+    if (!window.testRunner) {
+        testFailed("Must be run in WebKitTestRunner.");
+        done();
+        return;
+    }
+
+    let elementsToTest = document.getElementsByClassName("test");
+    for (let keyCommand of [new KeyCommand("escape"), new KeyCommand(".", ["metaKey"])]) {
+        debug(`<br>Dismiss by pressing ${keyCommand}:`);
+        for (elementToTest of elementsToTest) {
+            debug(`<br>For ${elementToTest.dataset.testName}:`);
+            let expectedValue = elementToTest.value;
+            await UIHelper.activateElementAndWaitForInputSession(elementToTest);
+            UIHelper.keyDown(keyCommand.key, keyCommand.modifiers);
+            await UIHelper.waitForKeyboardToHide();
+            shouldBeEqualToString("elementToTest.value", expectedValue);
+        }
+    }
+    elementToTest = null;
+    done();
+}
+
+description("Tests that pressing the Escape key or Command + . dismisses a picker without causing a value change.");
+
+runTest();
+</script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/ChangeLog       2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -1,3 +1,79 @@
</span><ins>+2019-04-03  Daniel Bates  <dabates@apple.com>
+
+        [iOS] Should be able to dismiss picker or popover using the keyboard
+        https://bugs.webkit.org/show_bug.cgi?id=196272
+        <rdar://problem/48943170>
+
+        Reviewed by Wenson Hsieh.
+
+        Intercept key events and route them to the current input peripheral (if we have one). Add a base key event handler
+        for all form peripherals that dismisses the accessory when either the Escape key is pressed or Command + . is pressed.
+        I will fix this issue for the file upload picker/popover in <https://bugs.webkit.org/show_bug.cgi?id=196287>.
+
+        * SourcesCocoa.txt: Add file WKFormPeripheralBase.mm.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView endEditingAndUpdateFocusAppearanceWithReason]): Added.
+        (-[WKContentView resignFirstResponderForWebView]): Write in terms of -endEditingAndUpdateFocusAppearance.
+        (-[WKContentView inputView]): Code style nit while I am here; add an empty line to demarcate the "crazy"
+        code that the FIXME is referring to and should ideally be removed from the code that is sane to always do.
+        (-[WKContentView accessoryDone]): When the accessory is dismissed via the Done button (iPhone) or by pressing
+        Escape or Command + . using a hardware keyboard (iPhone or iPad) then end the current editing session, but
+        do not resign first responder status as the page activation state should not be changed.
+        (-[WKContentView _handleKeyUIEvent:]): Bring back this code when building with USE(UIKIT_KEYBOARD_ADDITIONS)
+        as we need to route key events to the input peripheral (if we have one). If the input peripheral handles it
+        then we're done: no need to let UIKit or WebKit handle it when building with USE(UIKIT_KEYBOARD_ADDITIONS),
+        respectively. If the input peripheral does not handle it then do what we do now.
+        (-[WKContentView _elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:]):
+        If the element is re-focused and we have an input peripheral then we want to ensure we are first responder,
+        reveal the focused element, update the accessory and tell the peripheral that editing has begun (again).
+        For all other element re-focusing where we don't have a peripheral do what we do now. Also, update _isEditable
+        to reflect whether the focused element contains selectable text. This is what UIKit wants to know when it queries
+        -isEditable. Now that we no longer blur the focused element on iPad when the popover is dismissed and keep the
+        peripheral until there is a focus change we need to ensure that we give the correct answer to UIKit on view
+        editability. Otherwise, UIKit thinks it needs to update the text selection state when a popup button is tapped
+        again (as part of its gesture recognizer logic) and this causes an assertion failure in UIKit after it calls back
+        into us to ask for selection details, which we correctly respond with the equivalent of "we have none" and is
+        not the answer UIKit expects since we told it we are editable. (Currently we manage to get away with telling UIKit
+        we are always editable because it is not possible to perform a selection operation when we have a popover open.
+        Closing the popover blurs the element, setting -isEditable to NO and deallocates the peripheral avoiding this issue).
+        * UIProcess/ios/forms/WKFormColorControl.h:
+        * UIProcess/ios/forms/WKFormColorControl.mm:
+        (-[WKColorPopover controlEndEditing]): Dismiss the popover.
+        (-[WKFormColorControl initWithView:]): Modified to call base class initializer.
+        (-[WKFormColorControl assistantView]): Deleted.
+        (-[WKFormColorControl beginEditing]): Deleted.
+        (-[WKFormColorControl endEditing]): Deleted.
+        * UIProcess/ios/forms/WKFormInputControl.h:
+        * UIProcess/ios/forms/WKFormInputControl.mm:
+        (-[WKFormInputControl initWithView:]): Modified to call base class initializer.
+        (-[WKFormInputControl dateTimePickerCalendarType]): Write in terms of self.control.
+        (-[WKDateTimePopover controlEndEditing]): Dismiss the popover and tell the controller that editing ended.
+        (-[WKFormInputControl beginEditing]): Deleted.
+        (-[WKFormInputControl endEditing]): Deleted.
+        (-[WKFormInputControl assistantView]): Deleted.
+        * UIProcess/ios/forms/WKFormPeripheral.h:
+        * UIProcess/ios/forms/WKFormPeripheralBase.h: Added.
+        * UIProcess/ios/forms/WKFormPeripheralBase.mm: Added.
+        (-[WKFormPeripheralBase initWithView:control:]): Take ownership of the passed WKFormControl.
+        (-[WKFormPeripheralBase beginEditing]): Turn around and tell the control.
+        (-[WKFormPeripheralBase endEditing]): Ditto.
+        (-[WKFormPeripheralBase assistantView]): Ditto.
+        (-[WKFormPeripheralBase control]): Return the control.
+        (-[WKFormPeripheralBase handleKeyEvent:]): Dismiss the accessory (in the same way we dismiss when the Done
+        button is pressed on iPhone) on keydown of the Escape key or when we receive a UIKeyInputEscape event (for
+        Command + .).
+        * UIProcess/ios/forms/WKFormSelectControl.h:
+        * UIProcess/ios/forms/WKFormSelectControl.mm:
+        (-[WKFormSelectControl initWithView:]): Modified to call base class initializer.
+        (-[WKFormSelectControl selectRow:inComponent:extendingSelection:]): Write in terms of self.control.
+        (-[WKFormSelectControl selectFormPopoverTitle]): Ditto.
+        (-[WKFormSelectControl assistantView]): Deleted.
+        (-[WKFormSelectControl beginEditing]): Deleted.
+        (-[WKFormSelectControl endEditing]): Deleted.
+        * UIProcess/ios/forms/WKFormSelectPopover.mm:
+        (-[WKSelectPopover controlEndEditing]): Dismiss the popover.
+        * WebKit.xcodeproj/project.pbxproj: Add files WKFormPeripheralBase.{h, mm}.
+
</ins><span class="cx"> 2019-04-03  Youenn Fablet  <youenn@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Resetting quota should take into account third party origins
</span></span></pre></div>
<a id="trunkSourceWebKitSourcesCocoatxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/SourcesCocoa.txt (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/SourcesCocoa.txt     2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/SourcesCocoa.txt        2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -367,6 +367,7 @@
</span><span class="cx"> UIProcess/ios/forms/WKFormColorControl.mm
</span><span class="cx"> UIProcess/ios/forms/WKFormColorPicker.mm
</span><span class="cx"> UIProcess/ios/forms/WKFormInputControl.mm
</span><ins>+UIProcess/ios/forms/WKFormPeripheralBase.mm
</ins><span class="cx"> UIProcess/ios/forms/WKFormPopover.mm
</span><span class="cx"> UIProcess/ios/forms/WKFormSelectControl.mm
</span><span class="cx"> UIProcess/ios/forms/WKFormSelectPicker.mm
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewInteractionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h     2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h        2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -312,7 +312,6 @@
</span><span class="cx"> 
</span><span class="cx">     BOOL _becomingFirstResponder;
</span><span class="cx">     BOOL _resigningFirstResponder;
</span><del>-    BOOL _dismissingAccessory;
</del><span class="cx">     BOOL _needsDeferredEndScrollingSelectionUpdate;
</span><span class="cx">     BOOL _isChangingFocus;
</span><span class="cx">     BOOL _isBlurringFocusedElement;
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm    2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm       2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -1169,25 +1169,35 @@
</span><span class="cx">     return [_webView resignFirstResponder];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (BOOL)resignFirstResponderForWebView
</del><ins>+typedef NS_ENUM(NSInteger, EndEditingReason) {
+    EndEditingReasonAccessoryDone,
+    EndEditingReasonResigningFirstResponder,
+};
+
+- (void)endEditingAndUpdateFocusAppearanceWithReason:(EndEditingReason)reason
</ins><span class="cx"> {
</span><del>-    // FIXME: Maybe we should call resignFirstResponder on the superclass
-    // and do nothing if the return value is NO.
-
-    SetForScope<BOOL> resigningFirstResponderScope { _resigningFirstResponder, YES };
-
</del><span class="cx">     if (!_webView._retainingActiveFocusedState) {
</span><span class="cx">         // We need to complete the editing operation before we blur the element.
</span><span class="cx">         [self _endEditing];
</span><del>-        if (_dismissingAccessory || _keyboardDidRequestDismissal)
</del><ins>+        if ((reason == EndEditingReasonAccessoryDone && !currentUserInterfaceIdiomIsPad()) || _keyboardDidRequestDismissal)
</ins><span class="cx">             _page->blurFocusedElement();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     [self _cancelInteraction];
</span><span class="cx">     [_textSelectionAssistant deactivateSelection];
</span><del>-    
</del><ins>+
</ins><span class="cx">     [self _resetInputViewDeferral];
</span><ins>+}
</ins><span class="cx"> 
</span><ins>+- (BOOL)resignFirstResponderForWebView
+{
+    // FIXME: Maybe we should call resignFirstResponder on the superclass
+    // and do nothing if the return value is NO.
+
+    SetForScope<BOOL> resigningFirstResponderScope { _resigningFirstResponder, YES };
+
+    [self endEditingAndUpdateFocusAppearanceWithReason:EndEditingReasonResigningFirstResponder];
+
</ins><span class="cx">     // If the user explicitly dismissed the keyboard then we will lose first responder
</span><span class="cx">     // status only to gain it back again. Just don't resign in that case.
</span><span class="cx">     if (_keyboardDidRequestDismissal) {
</span><span class="lines">@@ -3758,8 +3768,8 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)accessoryDone
</span><span class="cx"> {
</span><del>-    SetForScope<BOOL> dismissingAccessoryScope { _dismissingAccessory, YES };
-    [self resignFirstResponder];
</del><ins>+    [self endEditingAndUpdateFocusAppearanceWithReason:EndEditingReasonAccessoryDone];
+    _page->setIsShowingInputViewForFocusedElement(false);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)accessoryTab:(BOOL)isNext
</span><span class="lines">@@ -4362,15 +4372,21 @@
</span><span class="cx">     return YES;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if !USE(UIKIT_KEYBOARD_ADDITIONS)
</del><span class="cx"> - (void)_handleKeyUIEvent:(::UIEvent *)event
</span><span class="cx"> {
</span><span class="cx">     bool isHardwareKeyboardEvent = !!event._hidEvent;
</span><del>-
</del><span class="cx">     // We only want to handle key event from the hardware keyboard when we are
</span><span class="cx">     // first responder and we are not interacting with editable content.
</span><del>-    if ([self isFirstResponder] && isHardwareKeyboardEvent && !_page->editorState().isContentEditable) {
</del><ins>+    if ([self isFirstResponder] && isHardwareKeyboardEvent && (_inputPeripheral || !_page->editorState().isContentEditable)) {
+        if ([_inputPeripheral respondsToSelector:@selector(handleKeyEvent:)]) {
+            if ([_inputPeripheral handleKeyEvent:event])
+                return;
+        }
+#if USE(UIKIT_KEYBOARD_ADDITIONS)
+        [super _handleKeyUIEvent:event];
+#else
</ins><span class="cx">         [self handleKeyEvent:event];
</span><ins>+#endif
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -4377,6 +4393,7 @@
</span><span class="cx">     [super _handleKeyUIEvent:event];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if !USE(UIKIT_KEYBOARD_ADDITIONS)
</ins><span class="cx"> - (void)handleKeyEvent:(::UIEvent *)event
</span><span class="cx"> {
</span><span class="cx">     // WebCore has already seen the event, no need for custom processing.
</span><span class="lines">@@ -4969,8 +4986,16 @@
</span><span class="cx"> 
</span><span class="cx">     // FIXME: We should remove this check when we manage to send ElementDidFocus from the WebProcess
</span><span class="cx">     // only when it is truly time to show the keyboard.
</span><del>-    if (_focusedElementInformation.elementType == information.elementType && _focusedElementInformation.elementRect == information.elementRect)
</del><ins>+    if (_focusedElementInformation.elementType == information.elementType && _focusedElementInformation.elementRect == information.elementRect) {
+        if (_inputPeripheral) {
+            if (!self.isFirstResponder)
+                [self becomeFirstResponder];
+            [self _zoomToRevealFocusedElement];
+            [self _updateAccessory];
+            [_inputPeripheral beginEditing];
+        }
</ins><span class="cx">         return;
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     [_webView _resetFocusPreservationCount];
</span><span class="cx"> 
</span><span class="lines">@@ -4989,7 +5014,8 @@
</span><span class="cx">     if (delegateImplementsWillStartInputSession)
</span><span class="cx">         [inputDelegate _webView:_webView willStartInputSession:_formInputSession.get()];
</span><span class="cx"> 
</span><del>-    BOOL editableChanged = [self setIsEditable:YES];
</del><ins>+    BOOL isSelectable = mayContainSelectableText(information.elementType);
+    BOOL editableChanged = [self setIsEditable:isSelectable];
</ins><span class="cx">     _focusedElementInformation = information;
</span><span class="cx">     _traits = nil;
</span><span class="cx"> 
</span><span class="lines">@@ -5006,7 +5032,7 @@
</span><span class="cx">     [self reloadInputViews];
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    if (mayContainSelectableText(_focusedElementInformation.elementType))
</del><ins>+    if (isSelectable)
</ins><span class="cx">         [self _showKeyboard];
</span><span class="cx"> 
</span><span class="cx">     // The custom fixed position rect behavior is affected by -isFocusingElement, so if that changes we need to recompute rects.
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormColorControlh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.h (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.h     2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.h        2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -25,11 +25,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(INPUT_TYPE_COLOR) && PLATFORM(IOS_FAMILY)
</span><span class="cx"> 
</span><del>-#import "WKFormPeripheral.h"
</del><ins>+#import "WKFormPeripheralBase.h"
</ins><span class="cx"> 
</span><span class="cx"> @class WKContentView;
</span><span class="cx"> 
</span><del>-@interface WKFormColorControl : NSObject<WKFormPeripheral>
</del><ins>+@interface WKFormColorControl : WKFormPeripheralBase
</ins><span class="cx"> - (instancetype)initWithView:(WKContentView *)view;
</span><span class="cx"> @end
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormColorControlmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.mm (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.mm    2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormColorControl.mm       2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -86,6 +86,7 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)controlEndEditing
</span><span class="cx"> {
</span><ins>+    [self dismissPopoverAnimated:NO];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @end
</span><span class="lines">@@ -92,38 +93,18 @@
</span><span class="cx"> 
</span><span class="cx"> #pragma mark - WKFormColorControl
</span><span class="cx"> 
</span><del>-@implementation WKFormColorControl {
-    RetainPtr<id<WKFormControl>> _control;
-}
</del><ins>+@implementation WKFormColorControl
</ins><span class="cx"> 
</span><span class="cx"> - (instancetype)initWithView:(WKContentView *)view
</span><span class="cx"> {
</span><del>-    if (!(self = [super init]))
-        return nil;
-
</del><ins>+    RetainPtr<NSObject <WKFormControl>> control;
</ins><span class="cx">     if (currentUserInterfaceIdiomIsPad())
</span><del>-        _control = adoptNS([[WKColorPopover alloc] initWithView:view]);
</del><ins>+        control = adoptNS([[WKColorPopover alloc] initWithView:view]);
</ins><span class="cx">     else
</span><del>-        _control = adoptNS([[WKColorPicker alloc] initWithView:view]);
-
-    return self;
</del><ins>+        control = adoptNS([[WKColorPicker alloc] initWithView:view]);
+    return [super initWithView:view control:WTFMove(control)];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (UIView *)assistantView
-{
-    return [_control controlView];
-}
-
-- (void)beginEditing
-{
-    [_control controlBeginEditing];
-}
-
-- (void)endEditing
-{
-    [_control controlEndEditing];
-}
-
</del><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(INPUT_TYPE_COLOR) && PLATFORM(IOS_FAMILY)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormInputControlh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.h (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.h     2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.h        2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -25,11 +25,11 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS_FAMILY)
</span><span class="cx"> 
</span><del>-#import "WKFormPeripheral.h"
</del><ins>+#import "WKFormPeripheralBase.h"
</ins><span class="cx"> 
</span><span class="cx"> @class WKContentView;
</span><span class="cx"> 
</span><del>-@interface WKFormInputControl : NSObject<WKFormPeripheral>
</del><ins>+@interface WKFormInputControl : WKFormPeripheralBase
</ins><span class="cx"> - (instancetype)initWithView:(WKContentView *)view;
</span><span class="cx"> @end
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormInputControlmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.mm (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.mm    2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.mm       2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -239,15 +239,10 @@
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> // WKFormInputControl
</span><del>-@implementation WKFormInputControl {
-    RetainPtr<NSObject <WKFormControl>> _control;
-}
</del><ins>+@implementation WKFormInputControl
</ins><span class="cx"> 
</span><span class="cx"> - (instancetype)initWithView:(WKContentView *)view
</span><span class="cx"> {
</span><del>-    if (!(self = [super init]))
-        return nil;
-
</del><span class="cx">     UIDatePickerMode mode;
</span><span class="cx"> 
</span><span class="cx">     switch (view.focusedElementInformation.elementType) {
</span><span class="lines">@@ -254,48 +249,28 @@
</span><span class="cx">     case InputType::Date:
</span><span class="cx">         mode = UIDatePickerModeDate;
</span><span class="cx">         break;
</span><del>-
</del><span class="cx">     case InputType::DateTimeLocal:
</span><span class="cx">         mode = UIDatePickerModeDateAndTime;
</span><span class="cx">         break;
</span><del>-
</del><span class="cx">     case InputType::Time:
</span><span class="cx">         mode = UIDatePickerModeTime;
</span><span class="cx">         break;
</span><del>-
</del><span class="cx">     case InputType::Month:
</span><span class="cx">         mode = (UIDatePickerMode)UIDatePickerModeYearAndMonth;
</span><span class="cx">         break;
</span><del>-
</del><span class="cx">     default:
</span><span class="cx">         [self release];
</span><span class="cx">         return nil;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    RetainPtr<NSObject <WKFormControl>> control;
</ins><span class="cx">     if (currentUserInterfaceIdiomIsPad())
</span><del>-        _control = adoptNS([[WKDateTimePopover alloc] initWithView:view datePickerMode:mode]);
</del><ins>+        control = adoptNS([[WKDateTimePopover alloc] initWithView:view datePickerMode:mode]);
</ins><span class="cx">     else
</span><del>-        _control = adoptNS([[WKDateTimePicker alloc] initWithView:view datePickerMode:mode]);
-
-    return self;
-
</del><ins>+        control = adoptNS([[WKDateTimePicker alloc] initWithView:view datePickerMode:mode]);
+    return [super initWithView:view control:WTFMove(control)];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)beginEditing
-{
-    [_control controlBeginEditing];
-}
-
-- (void)endEditing
-{
-    [_control controlEndEditing];
-}
-
-- (UIView *)assistantView
-{
-    return [_control controlView];
-}
-
</del><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @implementation WKFormInputControl (WKTesting)
</span><span class="lines">@@ -302,12 +277,10 @@
</span><span class="cx"> 
</span><span class="cx"> - (NSString *)dateTimePickerCalendarType
</span><span class="cx"> {
</span><del>-    if ([_control isKindOfClass:WKDateTimePicker.class])
-        return [(WKDateTimePicker *)_control.get() calendarType];
-
-    if ([_control isKindOfClass:WKDateTimePopover.class])
-        return [(WKDateTimePopover *)_control.get() calendarType];
-
</del><ins>+    if ([self.control isKindOfClass:WKDateTimePicker.class])
+        return [(WKDateTimePicker *)self.control calendarType];
+    if ([self.control isKindOfClass:WKDateTimePopover.class])
+        return [(WKDateTimePopover *)self.control calendarType];
</ins><span class="cx">     return nil;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -388,6 +361,8 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)controlEndEditing
</span><span class="cx"> {
</span><ins>+    [self dismissPopoverAnimated:NO];
+    [_viewController.get().innerControl controlEndEditing];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (UIView *)controlView
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormPeripheralh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheral.h (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheral.h       2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheral.h  2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -23,6 +23,7 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+@class UIEvent;
</ins><span class="cx"> @class UIView;
</span><span class="cx"> 
</span><span class="cx"> @protocol WKFormPeripheral
</span><span class="lines">@@ -29,6 +30,8 @@
</span><span class="cx"> - (void)beginEditing;
</span><span class="cx"> - (void)endEditing;
</span><span class="cx"> - (UIView *)assistantView;
</span><ins>+@optional
+- (BOOL)handleKeyEvent:(UIEvent *)event;
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @protocol WKFormControl
</span><span class="lines">@@ -35,4 +38,6 @@
</span><span class="cx"> - (UIView *)controlView;
</span><span class="cx"> - (void)controlBeginEditing;
</span><span class="cx"> - (void)controlEndEditing;
</span><ins>+@optional
+- (BOOL)controlHandleKeyEvent:(UIEvent *)event;
</ins><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormPeripheralBasehfromrev243807trunkSourceWebKitUIProcessiosformsWKFormInputControlh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.h (from rev 243807, trunk/Source/WebKit/UIProcess/ios/forms/WKFormInputControl.h) (0 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.h                           (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.h      2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+/*
+ * Copyright (C) 2019 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.
+ */
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "WKFormPeripheral.h"
+#import <wtf/Forward.h>
+
+@class WKContentView;
+
+@interface WKFormPeripheralBase : NSObject <WKFormPeripheral>
+
+- (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithView:(WKContentView *)view control:(RetainPtr<NSObject <WKFormControl>>&&)control NS_DESIGNATED_INITIALIZER;
+
+- (void)beginEditing;
+- (void)endEditing;
+- (UIView *)assistantView;
+- (BOOL)handleKeyEvent:(UIEvent *)event;
+
+@property (nonatomic, readonly) WKContentView *view;
+@property (nonatomic, readonly) NSObject <WKFormControl> *control;
+@property (nonatomic, readonly, getter=isEditing) BOOL editing;
+
+@end
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormPeripheralBasemm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.mm (0 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.mm                          (rev 0)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormPeripheralBase.mm     2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -0,0 +1,92 @@
</span><ins>+/*
+ * Copyright (C) 2019 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.
+ */
+
+#import "config.h"
+#import "WKFormPeripheralBase.h"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "WKContentView.h"
+#import <pal/spi/cocoa/IOKitSPI.h>
+#import <wtf/RetainPtr.h>
+
+@implementation WKFormPeripheralBase {
+    RetainPtr<NSObject <WKFormControl>> _control;
+}
+
+- (instancetype)initWithView:(WKContentView *)view control:(RetainPtr<NSObject <WKFormControl>>&&)control
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _view = view;
+    _control = WTFMove(control);
+    return self;
+}
+
+- (void)beginEditing
+{
+    _editing = YES;
+    [_control controlBeginEditing];
+}
+
+- (void)endEditing
+{
+    _editing = NO;
+    [_control controlEndEditing];
+}
+
+- (UIView *)assistantView
+{
+    return [_control controlView];
+}
+
+- (NSObject <WKFormControl> *)control
+{
+    return _control.get();
+}
+
+- (BOOL)handleKeyEvent:(UIEvent *)event
+{
+    ASSERT(event._hidEvent);
+    if ([_control respondsToSelector:@selector(controlHandleKeyEvent:)]) {
+        if ([_control controlHandleKeyEvent:event])
+            return YES;
+    }
+    if (!event._isKeyDown)
+        return NO;
+    UIPhysicalKeyboardEvent *keyEvent = (UIPhysicalKeyboardEvent *)event;
+    if (keyEvent._inputFlags & kUIKeyboardInputModifierFlagsChanged)
+        return NO;
+    if (_editing && (keyEvent._keyCode == kHIDUsage_KeyboardEscape || [keyEvent._unmodifiedInput isEqualToString:UIKeyInputEscape])) {
+        [_view accessoryDone];
+        return YES;
+    }
+    return NO;
+}
+
+@end
+
+#endif // PLATFORM(IOS_FAMILY)
</ins></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormSelectControlh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.h (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.h    2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.h       2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx"> 
</span><span class="cx"> #import "FocusedElementInformation.h"
</span><span class="cx"> #import "UIKitSPI.h"
</span><del>-#import "WKFormPeripheral.h"
</del><ins>+#import "WKFormPeripheralBase.h"
</ins><span class="cx"> #import "WKFormPopover.h"
</span><span class="cx"> #import <UIKit/UIPickerView.h>
</span><span class="cx"> 
</span><span class="lines">@@ -35,7 +35,7 @@
</span><span class="cx"> 
</span><span class="cx"> @class WKContentView;
</span><span class="cx"> 
</span><del>-@interface WKFormSelectControl : NSObject<WKFormPeripheral>
</del><ins>+@interface WKFormSelectControl : WKFormPeripheralBase
</ins><span class="cx"> - (instancetype)initWithView:(WKContentView *)view;
</span><span class="cx"> @end
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormSelectControlmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.mm (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.mm   2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectControl.mm      2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -65,9 +65,6 @@
</span><span class="cx"> 
</span><span class="cx"> - (instancetype)initWithView:(WKContentView *)view
</span><span class="cx"> {
</span><del>-    if (!(self = [super init]))
-        return nil;
-
</del><span class="cx">     bool hasGroups = false;
</span><span class="cx">     for (size_t i = 0; i < view.focusedElementInformation.selectOptions.size(); ++i) {
</span><span class="cx">         if (view.focusedElementInformation.selectOptions[i].isGroup) {
</span><span class="lines">@@ -76,31 +73,17 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    RetainPtr<NSObject <WKFormControl>> control;
</ins><span class="cx">     if (currentUserInterfaceIdiomIsPad())
</span><del>-        _control = adoptNS([[WKSelectPopover alloc] initWithView:view hasGroups:hasGroups]);
</del><ins>+        control = adoptNS([[WKSelectPopover alloc] initWithView:view hasGroups:hasGroups]);
</ins><span class="cx">     else if (view.focusedElementInformation.isMultiSelect || hasGroups)
</span><del>-        _control = adoptNS([[WKMultipleSelectPicker alloc] initWithView:view]);
</del><ins>+        control = adoptNS([[WKMultipleSelectPicker alloc] initWithView:view]);
</ins><span class="cx">     else
</span><del>-        _control = adoptNS([[WKSelectSinglePicker alloc] initWithView:view]);
-        
-    return self;
-}
</del><ins>+        control = adoptNS([[WKSelectSinglePicker alloc] initWithView:view]);
</ins><span class="cx"> 
</span><del>-- (UIView *)assistantView
-{
-    return [_control controlView];
</del><ins>+    return [super initWithView:view control:WTFMove(control)];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)beginEditing
-{
-    [_control controlBeginEditing];
-}
-
-- (void)endEditing
-{
-    [_control controlEndEditing];
-}
-
</del><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @implementation WKFormSelectControl(WKTesting)
</span><span class="lines">@@ -107,16 +90,15 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)selectRow:(NSInteger)rowIndex inComponent:(NSInteger)componentIndex extendingSelection:(BOOL)extendingSelection
</span><span class="cx"> {
</span><del>-    if ([_control respondsToSelector:@selector(selectRow:inComponent:extendingSelection:)])
-        [id<WKSelectTesting>(_control.get()) selectRow:rowIndex inComponent:componentIndex extendingSelection:extendingSelection];
</del><ins>+    if ([self.control respondsToSelector:@selector(selectRow:inComponent:extendingSelection:)])
+        [id<WKSelectTesting>(self.control) selectRow:rowIndex inComponent:componentIndex extendingSelection:extendingSelection];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (NSString *)selectFormPopoverTitle
</span><span class="cx"> {
</span><del>-    if (![_control isKindOfClass:[WKSelectPopover class]])
</del><ins>+    if (![self.control isKindOfClass:[WKSelectPopover class]])
</ins><span class="cx">         return nil;
</span><del>-
-    return [(WKSelectPopover *)_control.get() tableViewController].title;
</del><ins>+    return [(WKSelectPopover *)self.control tableViewController].title;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosformsWKFormSelectPopovermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectPopover.mm (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectPopover.mm   2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/UIProcess/ios/forms/WKFormSelectPopover.mm      2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #import "WebPageProxy.h"
</span><span class="cx"> #import <UIKit/UIPickerView.h>
</span><span class="cx"> #import <WebCore/LocalizedStrings.h>
</span><ins>+#import <pal/spi/cocoa/IOKitSPI.h>
</ins><span class="cx"> #import <wtf/RetainPtr.h>
</span><span class="cx"> 
</span><span class="cx"> using namespace WebKit;
</span><span class="lines">@@ -446,6 +447,7 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)controlEndEditing
</span><span class="cx"> {
</span><ins>+    [self dismissPopoverAnimated:NO];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_userActionDismissedPopover:(id)sender
</span></span></pre></div>
<a id="trunkSourceWebKitWebKitxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (243807 => 243808)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj     2019-04-03 17:03:59 UTC (rev 243807)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj        2019-04-03 17:06:04 UTC (rev 243808)
</span><span class="lines">@@ -1589,6 +1589,7 @@
</span><span class="cx">          CE1A0BD61A48E6C60054EF74 /* TCCSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1A0BD01A48E6C60054EF74 /* TCCSPI.h */; };
</span><span class="cx">          CE1A0BD71A48E6C60054EF74 /* TextInputSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1A0BD11A48E6C60054EF74 /* TextInputSPI.h */; };
</span><span class="cx">          CE5B4C8821B73D870022E64F /* WKSyntheticFlagsChangedWebEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = CE5B4C8621B73D870022E64F /* WKSyntheticFlagsChangedWebEvent.h */; };
</span><ins>+               CE70EE5D22442BD000E0AF0F /* WKFormPeripheralBase.h in Headers */ = {isa = PBXBuildFile; fileRef = CE70EE5C22442BD000E0AF0F /* WKFormPeripheralBase.h */; };
</ins><span class="cx">           CEC8F9CB1FDF5870002635E7 /* WKWebProcessPlugInNodeHandlePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = CEC8F9CA1FDF5870002635E7 /* WKWebProcessPlugInNodeHandlePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">          CEDA12E3152CD1B300D9E08D /* WebAlternativeTextClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CEDA12DE152CCAE800D9E08D /* WebAlternativeTextClient.h */; };
</span><span class="cx">          CEE4AE2B1A5DCF430002F49B /* UIKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CEE4AE2A1A5DCF430002F49B /* UIKitSPI.h */; };
</span><span class="lines">@@ -4470,6 +4471,8 @@
</span><span class="cx">          CE1A0BD11A48E6C60054EF74 /* TextInputSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextInputSPI.h; sourceTree = "<group>"; };
</span><span class="cx">          CE5B4C8621B73D870022E64F /* WKSyntheticFlagsChangedWebEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKSyntheticFlagsChangedWebEvent.h; path = ios/WKSyntheticFlagsChangedWebEvent.h; sourceTree = "<group>"; };
</span><span class="cx">          CE5B4C8721B73D870022E64F /* WKSyntheticFlagsChangedWebEvent.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKSyntheticFlagsChangedWebEvent.mm; path = ios/WKSyntheticFlagsChangedWebEvent.mm; sourceTree = "<group>"; };
</span><ins>+               CE70EE5A22442BB300E0AF0F /* WKFormPeripheralBase.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKFormPeripheralBase.mm; path = ios/forms/WKFormPeripheralBase.mm; sourceTree = "<group>"; };
+               CE70EE5C22442BD000E0AF0F /* WKFormPeripheralBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKFormPeripheralBase.h; path = ios/forms/WKFormPeripheralBase.h; sourceTree = "<group>"; };
</ins><span class="cx">           CEC8F9CA1FDF5870002635E7 /* WKWebProcessPlugInNodeHandlePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKWebProcessPlugInNodeHandlePrivate.h; sourceTree = "<group>"; };
</span><span class="cx">          CEDA12DE152CCAE800D9E08D /* WebAlternativeTextClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebAlternativeTextClient.h; sourceTree = "<group>"; };
</span><span class="cx">          CEDA12DF152CCAE800D9E08D /* WebAlternativeTextClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebAlternativeTextClient.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -8731,6 +8734,8 @@
</span><span class="cx">                          C54256AF18BEC18B00DE4179 /* WKFormInputControl.h */,
</span><span class="cx">                          C54256B018BEC18B00DE4179 /* WKFormInputControl.mm */,
</span><span class="cx">                          C54256B118BEC18B00DE4179 /* WKFormPeripheral.h */,
</span><ins>+                               CE70EE5C22442BD000E0AF0F /* WKFormPeripheralBase.h */,
+                               CE70EE5A22442BB300E0AF0F /* WKFormPeripheralBase.mm */,
</ins><span class="cx">                           C54256B218BEC18B00DE4179 /* WKFormPopover.h */,
</span><span class="cx">                          C54256B318BEC18B00DE4179 /* WKFormPopover.mm */,
</span><span class="cx">                          C54256B418BEC18C00DE4179 /* WKFormSelectControl.h */,
</span><span class="lines">@@ -9855,6 +9860,7 @@
</span><span class="cx">                          E548EBD121015F0E00BE3C32 /* WKFormColorPicker.h in Headers */,
</span><span class="cx">                          C54256B518BEC18C00DE4179 /* WKFormInputControl.h in Headers */,
</span><span class="cx">                          C54256B718BEC18C00DE4179 /* WKFormPeripheral.h in Headers */,
</span><ins>+                               CE70EE5D22442BD000E0AF0F /* WKFormPeripheralBase.h in Headers */,
</ins><span class="cx">                           C54256B818BEC18C00DE4179 /* WKFormPopover.h in Headers */,
</span><span class="cx">                          C54256BA18BEC18C00DE4179 /* WKFormSelectControl.h in Headers */,
</span><span class="cx">                          0F08CF521D63C13A00B48DF1 /* WKFormSelectPicker.h in Headers */,
</span></span></pre>
</div>
</div>

</body>
</html>