<!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>[245079] trunk/Source</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/245079">245079</a></dd>
<dt>Author</dt> <dd>megan_gardner@apple.com</dd>
<dt>Date</dt> <dd>2019-05-08 16:46:03 -0700 (Wed, 08 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add quirks to emulate undo and redo in hidden editable areas on some websites
https://bugs.webkit.org/show_bug.cgi?id=197452

Reviewed by Alex Christensen.

Source/WebCore:

UI change, not testable.

We need to send synthetic keyboard events to the web process to emulate undo and redo
key combinations for when we are trying to get our undo and redo UI to work
on rich editing websites that only listen to keystrokes, and don't let us use our
undo manager to help manage the input content.

* page/EventHandler.cpp:
(WebCore::EventHandler::keyEvent):
* platform/PlatformKeyboardEvent.h:
(WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent):
(WebCore::PlatformKeyboardEvent::isSyntheticEvent):
(WebCore::PlatformKeyboardEvent::setSyntheticEvent):
* platform/ios/KeyEventIOS.mm:
(WebCore::PlatformKeyboardEvent::currentStateOfModifierKeys):
* platform/ios/PlatformEventFactoryIOS.mm:
(WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder):
* platform/mac/PlatformEventFactoryMac.mm:
(WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder):

Source/WebKit:

We need to make our own undo manager to allow undo even when
the manager is empty. This is to interface with rich editing
websites that don't actually interface with our undo abilities.
Then we need to generate synthetic undo and redo in the web process.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::isCurrentURLHost const):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentView.mm:
(-[WKNSUndoManager initWithContentView:]):
(-[WKNSUndoManager canUndo]):
(-[WKNSUndoManager canRedo]):
(-[WKNSUndoManager undo]):
(-[WKNSUndoManager redo]):
(-[WKContentView undoManager]):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView generateSyntheticUndoRedo:]):
(-[WKContentView hasHiddenContentEditable]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::generateSyntheticUndoRedo):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::handleEditingKeyboardEvent):
(WebKit::WebPage::generateSyntheticUndoRedo):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageQuirkscpp">trunk/Source/WebCore/page/Quirks.cpp</a></li>
<li><a href="#trunkSourceWebCorepageQuirksh">trunk/Source/WebCore/page/Quirks.h</a></li>
<li><a href="#trunkSourceWebCoreplatformPlatformKeyboardEventh">trunk/Source/WebCore/platform/PlatformKeyboardEvent.h</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitSharedFocusedElementInformationcpp">trunk/Source/WebKit/Shared/FocusedElementInformation.cpp</a></li>
<li><a href="#trunkSourceWebKitSharedFocusedElementInformationh">trunk/Source/WebKit/Shared/FocusedElementInformation.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxycpp">trunk/Source/WebKit/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxyh">trunk/Source/WebKit/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosWKContentViewmm">trunk/Source/WebKit/UIProcess/ios/WKContentView.mm</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="#trunkSourceWebKitUIProcessiosWebPageProxyIOSmm">trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKitWebKitxcodeprojprojectpbxproj">trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPageh">trunk/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagemessagesin">trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitSharedSyntheticEditingCommandTypeh">trunk/Source/WebKit/Shared/SyntheticEditingCommandType.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebCore/ChangeLog      2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2019-05-08  Megan Gardner  <megan_gardner@apple.com>
+
+        Add quirks to emulate undo and redo in hidden editable areas on some websites
+        https://bugs.webkit.org/show_bug.cgi?id=197452
+
+        Reviewed by Alex Christensen.
+
+        UI change, not testable.
+
+        We need to send synthetic keyboard events to the web process to emulate undo and redo
+        key combinations for when we are trying to get our undo and redo UI to work
+        on rich editing websites that only listen to keystrokes, and don't let us use our
+        undo manager to help manage the input content.
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::keyEvent):
+        * platform/PlatformKeyboardEvent.h:
+        (WebCore::PlatformKeyboardEvent::PlatformKeyboardEvent):
+        (WebCore::PlatformKeyboardEvent::isSyntheticEvent):
+        (WebCore::PlatformKeyboardEvent::setSyntheticEvent):
+        * platform/ios/KeyEventIOS.mm:
+        (WebCore::PlatformKeyboardEvent::currentStateOfModifierKeys):
+        * platform/ios/PlatformEventFactoryIOS.mm:
+        (WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder):
+        * platform/mac/PlatformEventFactoryMac.mm:
+        (WebCore::PlatformKeyboardEventBuilder::PlatformKeyboardEventBuilder):
+
</ins><span class="cx"> 2019-05-08  Don Olmstead  <don.olmstead@sony.com>
</span><span class="cx"> 
</span><span class="cx">         CSSFontFaceSource fails to compile when !ENABLE(SVG_FONTS)
</span></span></pre></div>
<a id="trunkSourceWebCorepageQuirkscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Quirks.cpp (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Quirks.cpp     2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebCore/page/Quirks.cpp        2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -235,6 +235,11 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static bool shouldEmulateUndoRedoInHiddenEditableAreasForHost(const StringView&)
+{
+    return false;
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> bool Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const
</span><span class="lines">@@ -255,6 +260,14 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Quirks::shouldEmulateUndoRedoInHiddenEditableAreas() const
+{
+    if (!needsQuirks())
+        return false;
+
+    return shouldEmulateUndoRedoInHiddenEditableAreasForHost(m_document->topDocument().url().host());
+}
+
</ins><span class="cx"> bool Quirks::shouldSuppressAutocorrectionAndAutocaptializationInHiddenEditableAreas() const
</span><span class="cx"> {
</span><span class="cx">     if (!needsQuirks())
</span></span></pre></div>
<a id="trunkSourceWebCorepageQuirksh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Quirks.h (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Quirks.h       2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebCore/page/Quirks.h  2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -54,6 +54,7 @@
</span><span class="cx"> 
</span><span class="cx">     WEBCORE_EXPORT bool shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const;
</span><span class="cx">     WEBCORE_EXPORT bool shouldSuppressAutocorrectionAndAutocaptializationInHiddenEditableAreas() const;
</span><ins>+    WEBCORE_EXPORT bool shouldEmulateUndoRedoInHiddenEditableAreas() const;
</ins><span class="cx">     WEBCORE_EXPORT bool isTouchBarUpdateSupressedForHiddenContentEditable() const;
</span><span class="cx">     WEBCORE_EXPORT bool isNeverRichlyEditableForTouchBar() const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformPlatformKeyboardEventh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/PlatformKeyboardEvent.h (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/PlatformKeyboardEvent.h    2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebCore/platform/PlatformKeyboardEvent.h       2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -128,6 +128,9 @@
</span><span class="cx">         bool isAutoRepeat() const { return m_autoRepeat; }
</span><span class="cx">         bool isKeypad() const { return m_isKeypad; }
</span><span class="cx">         bool isSystemKey() const { return m_isSystemKey; }
</span><ins>+        
+        bool isSyntheticEvent() const { return m_isSyntheticEvent; }
+        void setIsSyntheticEvent() { m_isSyntheticEvent = true; }
</ins><span class="cx"> 
</span><span class="cx">         WEBCORE_EXPORT static bool currentCapsLockState();
</span><span class="cx">         WEBCORE_EXPORT static void getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey);
</span><span class="lines">@@ -190,6 +193,8 @@
</span><span class="cx">         bool m_autoRepeat;
</span><span class="cx">         bool m_isKeypad;
</span><span class="cx">         bool m_isSystemKey;
</span><ins>+        
+        bool m_isSyntheticEvent { false };
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx"> #if !PLATFORM(IOS_FAMILY)
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/ChangeLog       2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -1,3 +1,37 @@
</span><ins>+2019-05-08  Megan Gardner  <megan_gardner@apple.com>
+
+        Add quirks to emulate undo and redo in hidden editable areas on some websites
+        https://bugs.webkit.org/show_bug.cgi?id=197452
+
+        Reviewed by Alex Christensen.
+
+        We need to make our own undo manager to allow undo even when 
+        the manager is empty. This is to interface with rich editing 
+        websites that don't actually interface with our undo abilities.
+        Then we need to generate synthetic undo and redo in the web process.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::isCurrentURLHost const):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKNSUndoManager initWithContentView:]):
+        (-[WKNSUndoManager canUndo]):
+        (-[WKNSUndoManager canRedo]):
+        (-[WKNSUndoManager undo]):
+        (-[WKNSUndoManager redo]):
+        (-[WKContentView undoManager]):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView generateSyntheticUndoRedo:]):
+        (-[WKContentView hasHiddenContentEditable]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::generateSyntheticUndoRedo):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::handleEditingKeyboardEvent):
+        (WebKit::WebPage::generateSyntheticUndoRedo):
+
</ins><span class="cx"> 2019-05-08  Alex Christensen  <achristensen@webkit.org>
</span><span class="cx"> 
</span><span class="cx">         Add SPI to set HSTS storage directory
</span></span></pre></div>
<a id="trunkSourceWebKitSharedFocusedElementInformationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/FocusedElementInformation.cpp (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/FocusedElementInformation.cpp 2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/Shared/FocusedElementInformation.cpp    2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -104,6 +104,7 @@
</span><span class="cx">     encoder << suggestedColors;
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><ins>+    encoder << shouldSynthesizeKeyEventsForUndoAndRedo;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool FocusedElementInformation::decode(IPC::Decoder& decoder, FocusedElementInformation& result)
</span><span class="lines">@@ -222,6 +223,8 @@
</span><span class="cx">         return false;
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><ins>+    if (!decoder.decode(result.shouldSynthesizeKeyEventsForUndoAndRedo))
+        return false;
</ins><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKitSharedFocusedElementInformationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/FocusedElementInformation.h (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/FocusedElementInformation.h   2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/Shared/FocusedElementInformation.h      2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -136,6 +136,7 @@
</span><span class="cx">     Vector<WebCore::Color> suggestedColors;
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><ins>+    bool shouldSynthesizeKeyEventsForUndoAndRedo { false };
</ins><span class="cx"> 
</span><span class="cx">     FocusedElementIdentifier focusedElementIdentifier { 0 };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitSharedSyntheticEditingCommandTypeh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit/Shared/SyntheticEditingCommandType.h (0 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/SyntheticEditingCommandType.h                         (rev 0)
+++ trunk/Source/WebKit/Shared/SyntheticEditingCommandType.h    2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -0,0 +1,47 @@
</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.
+ */
+
+#pragma once
+
+namespace WebKit {
+    
+enum class SyntheticEditingCommandType : uint8_t  {
+    Undo,
+    Redo
+};
+
+} // namespace WebKit
+
+namespace WTF {
+
+template<> struct EnumTraits<WebKit::SyntheticEditingCommandType> {
+    using values = EnumValues <
+    WebKit::SyntheticEditingCommandType,
+    WebKit::SyntheticEditingCommandType::Undo,
+    WebKit::SyntheticEditingCommandType::Redo
+    >;
+};
+
+}
</ins></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp   2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp      2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -81,6 +81,7 @@
</span><span class="cx"> #include "SafeBrowsingWarning.h"
</span><span class="cx"> #include "ShareSheetCallbackID.h"
</span><span class="cx"> #include "SharedBufferDataReference.h"
</span><ins>+#include "SyntheticEditingCommandType.h"
</ins><span class="cx"> #include "TextChecker.h"
</span><span class="cx"> #include "TextCheckerState.h"
</span><span class="cx"> #include "TextInputContext.h"
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.h     2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h        2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx"> #include "ShareSheetCallbackID.h"
</span><span class="cx"> #include "ShareableBitmap.h"
</span><span class="cx"> #include "SuspendedPageProxy.h"
</span><ins>+#include "SyntheticEditingCommandType.h"
</ins><span class="cx"> #include "SystemPreviewController.h"
</span><span class="cx"> #include "UserMediaPermissionRequestManagerProxy.h"
</span><span class="cx"> #include "VisibleContentRectUpdateInfo.h"
</span><span class="lines">@@ -722,6 +723,7 @@
</span><span class="cx">     void requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&&);
</span><span class="cx">     void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&);
</span><span class="cx">     void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&);
</span><ins>+    void generateSyntheticEditingCommand(SyntheticEditingCommandType);
</ins><span class="cx"> #if ENABLE(DATA_INTERACTION)
</span><span class="cx">     void didHandleDragStartRequest(bool started);
</span><span class="cx">     void didHandleAdditionalDragItemsRequest(bool added);
</span><span class="lines">@@ -729,7 +731,7 @@
</span><span class="cx">     void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, WebCore::DragSourceAction allowedActions);
</span><span class="cx">     void didConcludeEditDrag(Optional<WebCore::TextIndicatorData>);
</span><span class="cx"> #endif
</span><del>-#endif
</del><ins>+#endif // PLATFORM(IOS_FAMILY)
</ins><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><span class="cx">     void setDataDetectionResult(const DataDetectionResult&);
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentView.mm (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentView.mm       2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentView.mm  2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -59,6 +59,7 @@
</span><span class="cx"> #import <WebCore/InspectorOverlay.h>
</span><span class="cx"> #import <WebCore/NotImplemented.h>
</span><span class="cx"> #import <WebCore/PlatformScreen.h>
</span><ins>+#import <WebCore/Quirks.h>
</ins><span class="cx"> #import <pal/spi/cocoa/QuartzCoreSPI.h>
</span><span class="cx"> #import <wtf/RetainPtr.h>
</span><span class="cx"> #import <wtf/text/TextStream.h>
</span><span class="lines">@@ -172,6 +173,41 @@
</span><span class="cx"> 
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+@interface WKQuirkyNSUndoManager : NSUndoManager
+@property (readonly, weak) WKContentView *contentView;
+@end
+
+@implementation WKQuirkyNSUndoManager
+- (instancetype)initWithContentView:(WKContentView *)contentView
+{
+    if (!(self = [super init]))
+        return nil;
+    _contentView = contentView;
+    return self;
+}
+
+- (BOOL)canUndo 
+{
+    return YES;
+}
+
+- (BOOL)canRedo 
+{
+    return YES;
+}
+
+- (void)undo 
+{
+    [self.contentView generateSyntheticEditingCommand:WebKit::SyntheticEditingCommandType::Undo];
+}
+
+- (void)redo 
+{
+    [self.contentView generateSyntheticEditingCommand:WebKit::SyntheticEditingCommandType::Redo];
+}
+
+@end
+
</ins><span class="cx"> @implementation WKContentView {
</span><span class="cx">     std::unique_ptr<WebKit::PageClientImpl> _pageClient;
</span><span class="cx">     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
</span><span class="lines">@@ -190,6 +226,7 @@
</span><span class="cx">     WebKit::HistoricalVelocityData _historicalKinematicData;
</span><span class="cx"> 
</span><span class="cx">     RetainPtr<NSUndoManager> _undoManager;
</span><ins>+    RetainPtr<WKQuirkyNSUndoManager> _quirkyUndoManager;
</ins><span class="cx"> 
</span><span class="cx">     BOOL _isPrintingToPDF;
</span><span class="cx">     RetainPtr<CGPDFDocumentRef> _printedDocument;
</span><span class="lines">@@ -498,9 +535,13 @@
</span><span class="cx"> 
</span><span class="cx"> - (NSUndoManager *)undoManager
</span><span class="cx"> {
</span><ins>+    if (self.focusedElementInformation.shouldSynthesizeKeyEventsForUndoAndRedo && self.hasHiddenContentEditable) {
+        if (!_quirkyUndoManager)
+            _quirkyUndoManager = adoptNS([[WKQuirkyNSUndoManager alloc] initWithContentView:self]);
+        return _quirkyUndoManager.get();
+    }
</ins><span class="cx">     if (!_undoManager)
</span><span class="cx">         _undoManager = adoptNS([[NSUndoManager alloc] init]);
</span><del>-
</del><span class="cx">     return _undoManager.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewInteractionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h     2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h        2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #import "FocusedElementInformation.h"
</span><span class="cx"> #import "GestureTypes.h"
</span><span class="cx"> #import "InteractionInformationAtPosition.h"
</span><ins>+#import "SyntheticEditingCommandType.h"
</ins><span class="cx"> #import "TextCheckingController.h"
</span><span class="cx"> #import "UIKitSPI.h"
</span><span class="cx"> #import "WKActionSheetAssistant.h"
</span><span class="lines">@@ -471,6 +472,9 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)willFinishIgnoringCalloutBarFadeAfterPerformingAction;
</span><span class="cx"> 
</span><ins>+- (BOOL)hasHiddenContentEditable;
+- (void)generateSyntheticEditingCommand:(WebKit::SyntheticEditingCommandType)command;
+
</ins><span class="cx"> // UIWebFormAccessoryDelegate protocol
</span><span class="cx"> - (void)accessoryDone;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm    2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm       2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -4476,6 +4476,11 @@
</span><span class="cx">     [super _handleKeyUIEvent:event];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)generateSyntheticEditingCommand:(WebKit::SyntheticEditingCommandType)command
+{
+    _page->generateSyntheticEditingCommand(command);
+}
+
</ins><span class="cx"> #if !USE(UIKIT_KEYBOARD_ADDITIONS)
</span><span class="cx"> - (void)handleKeyEvent:(::UIEvent *)event
</span><span class="cx"> {
</span><span class="lines">@@ -5166,6 +5171,7 @@
</span><span class="cx">     BOOL editableChanged = [self setIsEditable:NO];
</span><span class="cx"> 
</span><span class="cx">     _focusedElementInformation.elementType = WebKit::InputType::None;
</span><ins>+    _focusedElementInformation.shouldSynthesizeKeyEventsForUndoAndRedo = false;
</ins><span class="cx">     _inputPeripheral = nil;
</span><span class="cx">     _focusRequiresStrongPasswordAssistance = NO;
</span><span class="cx"> 
</span><span class="lines">@@ -5730,6 +5736,11 @@
</span><span class="cx">     return !_ignoreSelectionCommandFadeCount;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (BOOL)hasHiddenContentEditable
+{
+    return _suppressSelectionAssistantReasons.contains(WebKit::EditableRootIsTransparentOrFullyClipped);
+}
+
</ins><span class="cx"> - (BOOL)_shouldSuppressSelectionCommands
</span><span class="cx"> {
</span><span class="cx">     return !!_suppressSelectionAssistantReasons;
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWebPageProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm     2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm        2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -1102,6 +1102,14 @@
</span><span class="cx">     process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::generateSyntheticEditingCommand(WebKit::SyntheticEditingCommandType command)
+{
+    if (!hasRunningProcess())
+        return;
+
+    process().send(Messages::WebPage::GenerateSyntheticEditingCommand(command), m_pageID);
+}
+
</ins><span class="cx"> void WebPageProxy::updateEditorState(const EditorState& editorState)
</span><span class="cx"> {
</span><span class="cx">     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
</span></span></pre></div>
<a id="trunkSourceWebKitWebKitxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj     2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj        2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -896,6 +896,7 @@
</span><span class="cx">          41FABD2A1F4DE001006A6C97 /* CacheStorageEngineCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FABD281F4DDFDC006A6C97 /* CacheStorageEngineCache.h */; };
</span><span class="cx">          41FAF5F51E3C0649001AE678 /* WebRTCResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FAF5F41E3C0641001AE678 /* WebRTCResolver.h */; };
</span><span class="cx">          41FAF5F81E3C1021001AE678 /* LibWebRTCResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FAF5F61E3C0B47001AE678 /* LibWebRTCResolver.h */; };
</span><ins>+               4459984222833E8700E61373 /* SyntheticEditingCommandType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4459984122833E6000E61373 /* SyntheticEditingCommandType.h */; };
</ins><span class="cx">           449D90DA21FDC30B00F677C0 /* LocalAuthenticationSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 449D90D821FD63FE00F677C0 /* LocalAuthenticationSoftLink.mm */; };
</span><span class="cx">          460F488F1F996F7100CF4B87 /* WebSWContextManagerConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 460F488D1F996F6C00CF4B87 /* WebSWContextManagerConnectionMessageReceiver.cpp */; };
</span><span class="cx">          460F48901F996F7100CF4B87 /* WebSWContextManagerConnectionMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 460F488E1F996F6C00CF4B87 /* WebSWContextManagerConnectionMessages.h */; };
</span><span class="lines">@@ -3136,6 +3137,7 @@
</span><span class="cx">          41FBE823206DA79C000F0741 /* NetworkContentRuleListManager.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NetworkContentRuleListManager.messages.in; sourceTree = "<group>"; };
</span><span class="cx">          41FBE824206DA79C000F0741 /* NetworkContentRuleListManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkContentRuleListManager.cpp; sourceTree = "<group>"; };
</span><span class="cx">          4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SharedMemoryCocoa.cpp; sourceTree = "<group>"; };
</span><ins>+               4459984122833E6000E61373 /* SyntheticEditingCommandType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SyntheticEditingCommandType.h; sourceTree = "<group>"; };
</ins><span class="cx">           449D90D821FD63FE00F677C0 /* LocalAuthenticationSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalAuthenticationSoftLink.mm; sourceTree = "<group>"; };
</span><span class="cx">          44A481C621F2D27B00F2F919 /* ClientCertificateAuthenticationXPCConstants.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ClientCertificateAuthenticationXPCConstants.cpp; sourceTree = "<group>"; };
</span><span class="cx">          460F488D1F996F6C00CF4B87 /* WebSWContextManagerConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebSWContextManagerConnectionMessageReceiver.cpp; path = DerivedSources/WebKit2/WebSWContextManagerConnectionMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="lines">@@ -5914,6 +5916,7 @@
</span><span class="cx">                          2DA944981884E4F000ED86DB /* NativeWebTouchEventIOS.mm */,
</span><span class="cx">                          A118A9EC1907AD6F00F7C92B /* QuickLookDocumentData.cpp */,
</span><span class="cx">                          A118A9ED1907AD6F00F7C92B /* QuickLookDocumentData.h */,
</span><ins>+                               4459984122833E6000E61373 /* SyntheticEditingCommandType.h */,
</ins><span class="cx">                           F40D1B68220BDC0F00B49A01 /* WebAutocorrectionContext.h */,
</span><span class="cx">                          F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */,
</span><span class="cx">                          F44DFEB11E9E752F0038D196 /* WebIconUtilities.mm */,
</span><span class="lines">@@ -9528,6 +9531,7 @@
</span><span class="cx">                          1AB31A9716BC688100F6DBC9 /* StorageManagerMessages.h in Headers */,
</span><span class="cx">                          1AE00D6C18327C1200087DD7 /* StringReference.h in Headers */,
</span><span class="cx">                          296BD85D15019BC30071F424 /* StringUtilities.h in Headers */,
</span><ins>+                               4459984222833E8700E61373 /* SyntheticEditingCommandType.h in Headers */,
</ins><span class="cx">                           3157135F2040A9B20084F9CF /* SystemPreviewController.h in Headers */,
</span><span class="cx">                          CE1A0BD61A48E6C60054EF74 /* TCCSPI.h in Headers */,
</span><span class="cx">                          1AA417CB12C00CCA002BE67B /* TextChecker.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h    2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -170,6 +170,7 @@
</span><span class="cx"> class SelectionRect;
</span><span class="cx"> class SharedBuffer;
</span><span class="cx"> class SubstituteData;
</span><ins>+class SyntheticEditingCommandType;
</ins><span class="cx"> class TextCheckingRequest;
</span><span class="cx"> class VisiblePosition;
</span><span class="cx"> 
</span><span class="lines">@@ -1224,6 +1225,7 @@
</span><span class="cx">     RefPtr<WebCore::Range> rangeForWebSelectionAtPosition(const WebCore::IntPoint&, const WebCore::VisiblePosition&, SelectionFlags&);
</span><span class="cx">     void getFocusedElementInformation(FocusedElementInformation&);
</span><span class="cx">     void platformInitializeAccessibility();
</span><ins>+    void generateSyntheticEditingCommand(SyntheticEditingCommandType);
</ins><span class="cx">     void handleSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>);
</span><span class="cx">     void completeSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>, WebCore::SyntheticClickType);
</span><span class="cx">     void sendTapHighlightForNodeIfNecessary(uint64_t requestID, WebCore::Node*);
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in       2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in  2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -113,6 +113,7 @@
</span><span class="cx">     SetIsShowingInputViewForFocusedElement(bool showingInputView)
</span><span class="cx">     UpdateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta) -> () Async
</span><span class="cx">     RequestDocumentEditingContext(struct WebKit::DocumentEditingContextRequest request) -> (struct WebKit::DocumentEditingContext response) Async
</span><ins>+GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType command)
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     SetControlledByAutomation(bool controlled)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (245078 => 245079)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2019-05-08 23:42:50 UTC (rev 245078)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm    2019-05-08 23:46:03 UTC (rev 245079)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #import "PrintInfo.h"
</span><span class="cx"> #import "RemoteLayerTreeDrawingArea.h"
</span><span class="cx"> #import "SandboxUtilities.h"
</span><ins>+#import "SyntheticEditingCommandType.h"
</ins><span class="cx"> #import "TextCheckingControllerProxy.h"
</span><span class="cx"> #import "UIKitSPI.h"
</span><span class="cx"> #import "UserData.h"
</span><span class="lines">@@ -419,6 +420,11 @@
</span><span class="cx">     auto* platformEvent = event.underlyingPlatformEvent();
</span><span class="cx">     if (!platformEvent)
</span><span class="cx">         return false;
</span><ins>+    
+    // Don't send synthetic events to the UIProcess. They are only
+    // used for interacting with JavaScript.
+    if (platformEvent->isSyntheticEvent())
+        return false;
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: Interpret the event immediately upon receiving it in UI process, without sending to WebProcess first.
</span><span class="cx">     bool eventWasHandled = false;
</span><span class="lines">@@ -580,6 +586,46 @@
</span><span class="cx">     return AccessibilityObject::isARIAControl(ariaRole) || AccessibilityObject::isARIAInput(ariaRole);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPage::generateSyntheticEditingCommand(SyntheticEditingCommandType command)
+{
+    PlatformKeyboardEvent keyEvent;
+    auto& frame = m_page->focusController().focusedOrMainFrame();
+    
+    OptionSet<PlatformEvent::Modifier> modifiers;
+    modifiers.add(PlatformEvent::Modifier::MetaKey);
+    
+    switch (command) {
+    case SyntheticEditingCommandType::Undo:
+        keyEvent = PlatformKeyboardEvent(PlatformEvent::KeyDown, "z", "z",
+#if ENABLE(KEYBOARD_KEY_ATTRIBUTE)
+        "z",
+#endif
+#if ENABLE(KEYBOARD_CODE_ATTRIBUTE)
+        "KeyZ"_s,
+#endif
+        @"U+005A", 90, false, false, false, modifiers, WallTime::now());
+        break;
+    case SyntheticEditingCommandType::Redo:
+        keyEvent = PlatformKeyboardEvent(PlatformEvent::KeyDown, "y", "y",
+#if ENABLE(KEYBOARD_KEY_ATTRIBUTE)
+        "y",
+#endif
+#if ENABLE(KEYBOARD_CODE_ATTRIBUTE)
+        "KeyY"_s,
+#endif
+        @"U+0059", 89, false, false, false, modifiers, WallTime::now());
+        break;
+    default:
+        break;
+    }
+
+    keyEvent.setIsSyntheticEvent();
+    
+    PlatformKeyboardEvent::setCurrentModifierState(modifiers);
+    
+    frame.eventHandler().keyEvent(keyEvent);
+}
+
</ins><span class="cx"> void WebPage::handleSyntheticClick(Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers)
</span><span class="cx"> {
</span><span class="cx">     if (!nodeRespondingToClick.document().settings().contentChangeObserverEnabled()) {
</span><span class="lines">@@ -2824,6 +2870,7 @@
</span><span class="cx">             information.isAutocorrect = focusedElement.shouldAutocorrect();
</span><span class="cx">             information.autocapitalizeType = focusedElement.autocapitalizeType();
</span><span class="cx">             information.inputMode = focusedElement.canonicalInputMode();
</span><ins>+            information.shouldSynthesizeKeyEventsForUndoAndRedo = focusedElement.document().quirks().shouldEmulateUndoRedoInHiddenEditableAreas();
</ins><span class="cx">         } else {
</span><span class="cx">             information.isAutocorrect = true;
</span><span class="cx">             information.autocapitalizeType = AutocapitalizeTypeDefault;
</span></span></pre>
</div>
</div>

</body>
</html>