Add quirks to emulate undo and redo in hidden editable areas on some websites
authormegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 May 2019 23:46:03 +0000 (23:46 +0000)
committermegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 May 2019 23:46:03 +0000 (23:46 +0000)
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):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@245079 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/WebCore/ChangeLog
Source/WebCore/page/Quirks.cpp
Source/WebCore/page/Quirks.h
Source/WebCore/platform/PlatformKeyboardEvent.h
Source/WebKit/ChangeLog
Source/WebKit/Shared/FocusedElementInformation.cpp
Source/WebKit/Shared/FocusedElementInformation.h
Source/WebKit/Shared/SyntheticEditingCommandType.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/WKContentView.mm
Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

index 2c6ec8b..9d57a21 100644 (file)
@@ -1,3 +1,30 @@
+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):
+
 2019-05-08  Don Olmstead  <don.olmstead@sony.com>
 
         CSSFontFaceSource fails to compile when !ENABLE(SVG_FONTS)
index 522a33a..2abd896 100644 (file)
@@ -235,6 +235,11 @@ static bool shouldSuppressAutocorrectionAndAutocaptializationInHiddenEditableAre
     return false;
 }
 
+static bool shouldEmulateUndoRedoInHiddenEditableAreasForHost(const StringView&)
+{
+    return false;
+}
+
 #endif
 
 bool Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const
@@ -255,6 +260,14 @@ bool Quirks::shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const
     return false;
 }
 
+bool Quirks::shouldEmulateUndoRedoInHiddenEditableAreas() const
+{
+    if (!needsQuirks())
+        return false;
+
+    return shouldEmulateUndoRedoInHiddenEditableAreasForHost(m_document->topDocument().url().host());
+}
+
 bool Quirks::shouldSuppressAutocorrectionAndAutocaptializationInHiddenEditableAreas() const
 {
     if (!needsQuirks())
index 7689f70..d3d5f88 100644 (file)
@@ -54,6 +54,7 @@ public:
 
     WEBCORE_EXPORT bool shouldDispatchSyntheticMouseEventsWhenModifyingSelection() const;
     WEBCORE_EXPORT bool shouldSuppressAutocorrectionAndAutocaptializationInHiddenEditableAreas() const;
+    WEBCORE_EXPORT bool shouldEmulateUndoRedoInHiddenEditableAreas() const;
     WEBCORE_EXPORT bool isTouchBarUpdateSupressedForHiddenContentEditable() const;
     WEBCORE_EXPORT bool isNeverRichlyEditableForTouchBar() const;
 
index b7a02a9..1a386cc 100644 (file)
@@ -128,6 +128,9 @@ namespace WebCore {
         bool isAutoRepeat() const { return m_autoRepeat; }
         bool isKeypad() const { return m_isKeypad; }
         bool isSystemKey() const { return m_isSystemKey; }
+        
+        bool isSyntheticEvent() const { return m_isSyntheticEvent; }
+        void setIsSyntheticEvent() { m_isSyntheticEvent = true; }
 
         WEBCORE_EXPORT static bool currentCapsLockState();
         WEBCORE_EXPORT static void getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey);
@@ -190,6 +193,8 @@ namespace WebCore {
         bool m_autoRepeat;
         bool m_isKeypad;
         bool m_isSystemKey;
+        
+        bool m_isSyntheticEvent { false };
 
 #if PLATFORM(COCOA)
 #if !PLATFORM(IOS_FAMILY)
index aa93f41..5c62974 100644 (file)
@@ -1,3 +1,37 @@
+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):
+
 2019-05-08  Alex Christensen  <achristensen@webkit.org>
 
         Add SPI to set HSTS storage directory
index bc2bc33..cdef1a2 100644 (file)
@@ -104,6 +104,7 @@ void FocusedElementInformation::encode(IPC::Encoder& encoder) const
     encoder << suggestedColors;
 #endif
 #endif
+    encoder << shouldSynthesizeKeyEventsForUndoAndRedo;
 }
 
 bool FocusedElementInformation::decode(IPC::Decoder& decoder, FocusedElementInformation& result)
@@ -222,6 +223,8 @@ bool FocusedElementInformation::decode(IPC::Decoder& decoder, FocusedElementInfo
         return false;
 #endif
 #endif
+    if (!decoder.decode(result.shouldSynthesizeKeyEventsForUndoAndRedo))
+        return false;
 
     return true;
 }
index 188d5a7..b3900ce 100644 (file)
@@ -136,6 +136,7 @@ struct FocusedElementInformation {
     Vector<WebCore::Color> suggestedColors;
 #endif
 #endif
+    bool shouldSynthesizeKeyEventsForUndoAndRedo { false };
 
     FocusedElementIdentifier focusedElementIdentifier { 0 };
 
diff --git a/Source/WebKit/Shared/SyntheticEditingCommandType.h b/Source/WebKit/Shared/SyntheticEditingCommandType.h
new file mode 100644 (file)
index 0000000..7e381e4
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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
+    >;
+};
+
+}
index f29d5a1..a8ab15e 100644 (file)
@@ -81,6 +81,7 @@
 #include "SafeBrowsingWarning.h"
 #include "ShareSheetCallbackID.h"
 #include "SharedBufferDataReference.h"
+#include "SyntheticEditingCommandType.h"
 #include "TextChecker.h"
 #include "TextCheckerState.h"
 #include "TextInputContext.h"
index 03786e8..b239a9c 100644 (file)
@@ -46,6 +46,7 @@
 #include "ShareSheetCallbackID.h"
 #include "ShareableBitmap.h"
 #include "SuspendedPageProxy.h"
+#include "SyntheticEditingCommandType.h"
 #include "SystemPreviewController.h"
 #include "UserMediaPermissionRequestManagerProxy.h"
 #include "VisibleContentRectUpdateInfo.h"
@@ -722,6 +723,7 @@ public:
     void requestEvasionRectsAboveSelection(CompletionHandler<void(const Vector<WebCore::FloatRect>&)>&&);
     void updateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta, CompletionHandler<void()>&&);
     void requestDocumentEditingContext(WebKit::DocumentEditingContextRequest, CompletionHandler<void(WebKit::DocumentEditingContext)>&&);
+    void generateSyntheticEditingCommand(SyntheticEditingCommandType);
 #if ENABLE(DATA_INTERACTION)
     void didHandleDragStartRequest(bool started);
     void didHandleAdditionalDragItemsRequest(bool added);
@@ -729,7 +731,7 @@ public:
     void requestAdditionalItemsForDragSession(const WebCore::IntPoint& clientPosition, const WebCore::IntPoint& globalPosition, WebCore::DragSourceAction allowedActions);
     void didConcludeEditDrag(Optional<WebCore::TextIndicatorData>);
 #endif
-#endif
+#endif // PLATFORM(IOS_FAMILY)
 #if ENABLE(DATA_DETECTION)
     void setDataDetectionResult(const DataDetectionResult&);
 #endif
index 6b2d9f9..ab68809 100644 (file)
@@ -59,6 +59,7 @@
 #import <WebCore/InspectorOverlay.h>
 #import <WebCore/NotImplemented.h>
 #import <WebCore/PlatformScreen.h>
+#import <WebCore/Quirks.h>
 #import <pal/spi/cocoa/QuartzCoreSPI.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/text/TextStream.h>
@@ -172,6 +173,41 @@ private:
 
 @end
 
+@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
+
 @implementation WKContentView {
     std::unique_ptr<WebKit::PageClientImpl> _pageClient;
     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
@@ -190,6 +226,7 @@ private:
     WebKit::HistoricalVelocityData _historicalKinematicData;
 
     RetainPtr<NSUndoManager> _undoManager;
+    RetainPtr<WKQuirkyNSUndoManager> _quirkyUndoManager;
 
     BOOL _isPrintingToPDF;
     RetainPtr<CGPDFDocumentRef> _printedDocument;
@@ -498,9 +535,13 @@ static WebCore::FloatBoxExtent floatBoxExtent(UIEdgeInsets insets)
 
 - (NSUndoManager *)undoManager
 {
+    if (self.focusedElementInformation.shouldSynthesizeKeyEventsForUndoAndRedo && self.hasHiddenContentEditable) {
+        if (!_quirkyUndoManager)
+            _quirkyUndoManager = adoptNS([[WKQuirkyNSUndoManager alloc] initWithContentView:self]);
+        return _quirkyUndoManager.get();
+    }
     if (!_undoManager)
         _undoManager = adoptNS([[NSUndoManager alloc] init]);
-
     return _undoManager.get();
 }
 
index 99839a2..a223ba1 100644 (file)
@@ -36,6 +36,7 @@
 #import "FocusedElementInformation.h"
 #import "GestureTypes.h"
 #import "InteractionInformationAtPosition.h"
+#import "SyntheticEditingCommandType.h"
 #import "TextCheckingController.h"
 #import "UIKitSPI.h"
 #import "WKActionSheetAssistant.h"
@@ -471,6 +472,9 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
 
 - (void)willFinishIgnoringCalloutBarFadeAfterPerformingAction;
 
+- (BOOL)hasHiddenContentEditable;
+- (void)generateSyntheticEditingCommand:(WebKit::SyntheticEditingCommandType)command;
+
 // UIWebFormAccessoryDelegate protocol
 - (void)accessoryDone;
 
index 4ecce81..d9c674a 100644 (file)
@@ -4476,6 +4476,11 @@ static NSString *contentTypeFromFieldName(WebCore::AutofillFieldName fieldName)
     [super _handleKeyUIEvent:event];
 }
 
+- (void)generateSyntheticEditingCommand:(WebKit::SyntheticEditingCommandType)command
+{
+    _page->generateSyntheticEditingCommand(command);
+}
+
 #if !USE(UIKIT_KEYBOARD_ADDITIONS)
 - (void)handleKeyEvent:(::UIEvent *)event
 {
@@ -5166,6 +5171,7 @@ static RetainPtr<NSObject <WKFormPeripheral>> createInputPeripheralWithView(WebK
     BOOL editableChanged = [self setIsEditable:NO];
 
     _focusedElementInformation.elementType = WebKit::InputType::None;
+    _focusedElementInformation.shouldSynthesizeKeyEventsForUndoAndRedo = false;
     _inputPeripheral = nil;
     _focusRequiresStrongPasswordAssistance = NO;
 
@@ -5730,6 +5736,11 @@ static BOOL allPasteboardItemOriginsMatchOrigin(UIPasteboard *pasteboard, const
     return !_ignoreSelectionCommandFadeCount;
 }
 
+- (BOOL)hasHiddenContentEditable
+{
+    return _suppressSelectionAssistantReasons.contains(WebKit::EditableRootIsTransparentOrFullyClipped);
+}
+
 - (BOOL)_shouldSuppressSelectionCommands
 {
     return !!_suppressSelectionAssistantReasons;
index 9030b7b..fabafef 100644 (file)
@@ -1102,6 +1102,14 @@ void WebPageProxy::contentSizeCategoryDidChange(const String& contentSizeCategor
     process().send(Messages::WebPage::ContentSizeCategoryDidChange(contentSizeCategory), m_pageID);
 }
 
+void WebPageProxy::generateSyntheticEditingCommand(WebKit::SyntheticEditingCommandType command)
+{
+    if (!hasRunningProcess())
+        return;
+
+    process().send(Messages::WebPage::GenerateSyntheticEditingCommand(command), m_pageID);
+}
+
 void WebPageProxy::updateEditorState(const EditorState& editorState)
 {
     bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
index 8f7773e..26c05c7 100644 (file)
                41FABD2A1F4DE001006A6C97 /* CacheStorageEngineCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FABD281F4DDFDC006A6C97 /* CacheStorageEngineCache.h */; };
                41FAF5F51E3C0649001AE678 /* WebRTCResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FAF5F41E3C0641001AE678 /* WebRTCResolver.h */; };
                41FAF5F81E3C1021001AE678 /* LibWebRTCResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 41FAF5F61E3C0B47001AE678 /* LibWebRTCResolver.h */; };
+               4459984222833E8700E61373 /* SyntheticEditingCommandType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4459984122833E6000E61373 /* SyntheticEditingCommandType.h */; };
                449D90DA21FDC30B00F677C0 /* LocalAuthenticationSoftLink.mm in Sources */ = {isa = PBXBuildFile; fileRef = 449D90D821FD63FE00F677C0 /* LocalAuthenticationSoftLink.mm */; };
                460F488F1F996F7100CF4B87 /* WebSWContextManagerConnectionMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 460F488D1F996F6C00CF4B87 /* WebSWContextManagerConnectionMessageReceiver.cpp */; };
                460F48901F996F7100CF4B87 /* WebSWContextManagerConnectionMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 460F488E1F996F6C00CF4B87 /* WebSWContextManagerConnectionMessages.h */; };
                41FBE823206DA79C000F0741 /* NetworkContentRuleListManager.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NetworkContentRuleListManager.messages.in; sourceTree = "<group>"; };
                41FBE824206DA79C000F0741 /* NetworkContentRuleListManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkContentRuleListManager.cpp; sourceTree = "<group>"; };
                4450AEBF1DC3FAE5009943F2 /* SharedMemoryCocoa.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SharedMemoryCocoa.cpp; sourceTree = "<group>"; };
+               4459984122833E6000E61373 /* SyntheticEditingCommandType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SyntheticEditingCommandType.h; sourceTree = "<group>"; };
                449D90D821FD63FE00F677C0 /* LocalAuthenticationSoftLink.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalAuthenticationSoftLink.mm; sourceTree = "<group>"; };
                44A481C621F2D27B00F2F919 /* ClientCertificateAuthenticationXPCConstants.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ClientCertificateAuthenticationXPCConstants.cpp; sourceTree = "<group>"; };
                460F488D1F996F6C00CF4B87 /* WebSWContextManagerConnectionMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebSWContextManagerConnectionMessageReceiver.cpp; path = DerivedSources/WebKit2/WebSWContextManagerConnectionMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
                                2DA944981884E4F000ED86DB /* NativeWebTouchEventIOS.mm */,
                                A118A9EC1907AD6F00F7C92B /* QuickLookDocumentData.cpp */,
                                A118A9ED1907AD6F00F7C92B /* QuickLookDocumentData.h */,
+                               4459984122833E6000E61373 /* SyntheticEditingCommandType.h */,
                                F40D1B68220BDC0F00B49A01 /* WebAutocorrectionContext.h */,
                                F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */,
                                F44DFEB11E9E752F0038D196 /* WebIconUtilities.mm */,
                                1AB31A9716BC688100F6DBC9 /* StorageManagerMessages.h in Headers */,
                                1AE00D6C18327C1200087DD7 /* StringReference.h in Headers */,
                                296BD85D15019BC30071F424 /* StringUtilities.h in Headers */,
+                               4459984222833E8700E61373 /* SyntheticEditingCommandType.h in Headers */,
                                3157135F2040A9B20084F9CF /* SystemPreviewController.h in Headers */,
                                CE1A0BD61A48E6C60054EF74 /* TCCSPI.h in Headers */,
                                1AA417CB12C00CCA002BE67B /* TextChecker.h in Headers */,
index 32748ce..c29645d 100644 (file)
@@ -170,6 +170,7 @@ class ResourceResponse;
 class SelectionRect;
 class SharedBuffer;
 class SubstituteData;
+class SyntheticEditingCommandType;
 class TextCheckingRequest;
 class VisiblePosition;
 
@@ -1224,6 +1225,7 @@ private:
     RefPtr<WebCore::Range> rangeForWebSelectionAtPosition(const WebCore::IntPoint&, const WebCore::VisiblePosition&, SelectionFlags&);
     void getFocusedElementInformation(FocusedElementInformation&);
     void platformInitializeAccessibility();
+    void generateSyntheticEditingCommand(SyntheticEditingCommandType);
     void handleSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>);
     void completeSyntheticClick(WebCore::Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebKit::WebEvent::Modifier>, WebCore::SyntheticClickType);
     void sendTapHighlightForNodeIfNecessary(uint64_t requestID, WebCore::Node*);
index 1c9a6d1..f2f49d5 100644 (file)
@@ -113,6 +113,7 @@ messages -> WebPage LegacyReceiver {
     SetIsShowingInputViewForFocusedElement(bool showingInputView)
     UpdateSelectionWithDelta(int64_t locationDelta, int64_t lengthDelta) -> () Async
     RequestDocumentEditingContext(struct WebKit::DocumentEditingContextRequest request) -> (struct WebKit::DocumentEditingContext response) Async
+GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType command)
 #endif
 
     SetControlledByAutomation(bool controlled)
index 8f4047e..e3ee326 100644 (file)
@@ -42,6 +42,7 @@
 #import "PrintInfo.h"
 #import "RemoteLayerTreeDrawingArea.h"
 #import "SandboxUtilities.h"
+#import "SyntheticEditingCommandType.h"
 #import "TextCheckingControllerProxy.h"
 #import "UIKitSPI.h"
 #import "UserData.h"
@@ -419,6 +420,11 @@ bool WebPage::handleEditingKeyboardEvent(KeyboardEvent& event)
     auto* platformEvent = event.underlyingPlatformEvent();
     if (!platformEvent)
         return false;
+    
+    // Don't send synthetic events to the UIProcess. They are only
+    // used for interacting with JavaScript.
+    if (platformEvent->isSyntheticEvent())
+        return false;
 
     // FIXME: Interpret the event immediately upon receiving it in UI process, without sending to WebProcess first.
     bool eventWasHandled = false;
@@ -580,6 +586,46 @@ static bool nodeAlwaysTriggersClick(const Node& targetNode)
     return AccessibilityObject::isARIAControl(ariaRole) || AccessibilityObject::isARIAInput(ariaRole);
 }
 
+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);
+}
+
 void WebPage::handleSyntheticClick(Node& nodeRespondingToClick, const WebCore::FloatPoint& location, OptionSet<WebEvent::Modifier> modifiers)
 {
     if (!nodeRespondingToClick.document().settings().contentChangeObserverEnabled()) {
@@ -2824,6 +2870,7 @@ void WebPage::getFocusedElementInformation(FocusedElementInformation& informatio
             information.isAutocorrect = focusedElement.shouldAutocorrect();
             information.autocapitalizeType = focusedElement.autocapitalizeType();
             information.inputMode = focusedElement.canonicalInputMode();
+            information.shouldSynthesizeKeyEventsForUndoAndRedo = focusedElement.document().quirks().shouldEmulateUndoRedoInHiddenEditableAreas();
         } else {
             information.isAutocorrect = true;
             information.autocapitalizeType = AutocapitalizeTypeDefault;