[Cocoa] Introduce WKWebView SPI to insert nested ordered and unordered lists
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 20:16:32 +0000 (20:16 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Nov 2018 20:16:32 +0000 (20:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191410
<rdar://problem/45898610>

Reviewed by Dean Jackson.

Source/WebKit:

Prefixes a few iOS-only SPI methods declared on WKWebView in r236867 with underscores, and also exposes some
more cross-platform Cocoa editing SPI. Once the unprefixed SPI methods are no longer used by internal clients,
these will need to be removed (see followup bug: webkit.org/b/191450). See below for more details.

Covered by new and existing API tests in WKWebViewEditActions.

* UIProcess/API/Cocoa/WKWebView.mm:

Hoist the definition (and undefinition) of `FORWARD_ACTION_TO_WKCONTENTVIEW` to encompass both the WKWebView
implementation and the WKWebView (WKPrivate) implementation. This allows us to use this macro when implementing
SPI methods in the WKPrivate category, as well as methods that are part of the main WKWebView implementation.

(-[WKWebView canPerformAction:withSender:]):
(-[WKWebView targetForAction:withSender:]):

Add forwarding for the new editing commands in -canPerformAction: and -targetForAction:.

(-[WKWebView _toggleStrikeThrough:]):
(-[WKWebView _increaseListLevel:]):
(-[WKWebView _decreaseListLevel:]):
(-[WKWebView _changeListType:]):
(-[WKWebView _setFont:sender:]):
(-[WKWebView _setFontSize:sender:]):
(-[WKWebView _setTextColor:sender:]):

Add definitions for the new editing methods on WKWebView, using macros (`WEBCORE_PRIVATE_COMMAND` on macOS and
`FORWARD_ACTION_TO_WKCONTENTVIEW` on iOS) to help reduce the code duplication.

(-[WKWebView _pasteAsQuotation:]): Deleted.

Remove this method definition, which is now replaced by macros on iOS and macOS.

* UIProcess/API/Cocoa/WKWebViewPrivate.h:

Introduce the new SPI to WKWebView (WKPrivate), and add FIXMEs to remove old, unprefixed variants of the SPI.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::increaseListLevel):
(WebKit::WebPageProxy::decreaseListLevel):
(WebKit::WebPageProxy::changeListType):

Add plumbing for these list editing commands.

* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _increaseListLevelForWebView:]):
(-[WKContentView _decreaseListLevelForWebView:]):
(-[WKContentView _changeListTypeForWebView:]):
(-[WKContentView _toggleStrikeThroughForWebView:]):
(-[WKContentView _setFontForWebView:sender:]):
(-[WKContentView _setFontSizeForWebView:sender:]):
(-[WKContentView _setTextColorForWebView:sender:]):
(-[WKContentView toggleStrikeThroughForWebView:]):
(-[WKContentView setFontForWebView:sender:]):
(-[WKContentView setFontSizeForWebView:sender:]):
(-[WKContentView setTextColorForWebView:sender:]):
(-[WKContentView canPerformActionForWebView:withSender:]):

Check for the new action selectors here, and additionally add validation for `_pasteAsQuotation:`. Let the
unprefixed versions of these methods simply call the prefixed versions (these method implementations will be
removed in a followup once doing so would not affect any clients of WebKit).

* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::increaseListLevel):
(WebKit::WebPage::decreaseListLevel):
(WebKit::WebPage::changeListType):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Add stubs for several list editing commands that are yet to be hooked up to WebCore. These will be implemented
in a future patch.

Tools:

Move WKWebViewEditActions from iOS to WebKitCocoa, and enable the relevant WKWebViewEditActions tests on macOS.
Additionally, add new API tests to verify that `-_pasteAsQuotation:` and `-_insertNested(Un)OrderedList:` are
hooked up to their respective editing commands.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEditActions.mm: Renamed from Tools/TestWebKitAPI/Tests/ios/WKWebViewEditActions.mm.
(-[TestWKWebView querySelectorExists:]):
(-[TestWKWebView insertString:]):

Add a helper method to insert a piece of text. This abstracts platform differences between iOS and macOS, by
invoking the WKWebView directly on macOS and calling on the content view on iOS.

(TestWebKitAPI::webViewForEditActionTesting):
(TestWebKitAPI::TEST):

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

13 files changed:
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEditActions.mm [moved from Tools/TestWebKitAPI/Tests/ios/WKWebViewEditActions.mm with 73% similarity]

index 0a79593..da023d2 100644 (file)
@@ -1,3 +1,85 @@
+2018-11-09  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Cocoa] Introduce WKWebView SPI to insert nested ordered and unordered lists
+        https://bugs.webkit.org/show_bug.cgi?id=191410
+        <rdar://problem/45898610>
+
+        Reviewed by Dean Jackson.
+
+        Prefixes a few iOS-only SPI methods declared on WKWebView in r236867 with underscores, and also exposes some
+        more cross-platform Cocoa editing SPI. Once the unprefixed SPI methods are no longer used by internal clients,
+        these will need to be removed (see followup bug: webkit.org/b/191450). See below for more details.
+
+        Covered by new and existing API tests in WKWebViewEditActions.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+
+        Hoist the definition (and undefinition) of `FORWARD_ACTION_TO_WKCONTENTVIEW` to encompass both the WKWebView
+        implementation and the WKWebView (WKPrivate) implementation. This allows us to use this macro when implementing
+        SPI methods in the WKPrivate category, as well as methods that are part of the main WKWebView implementation.
+
+        (-[WKWebView canPerformAction:withSender:]):
+        (-[WKWebView targetForAction:withSender:]):
+
+        Add forwarding for the new editing commands in -canPerformAction: and -targetForAction:.
+
+        (-[WKWebView _toggleStrikeThrough:]):
+        (-[WKWebView _increaseListLevel:]):
+        (-[WKWebView _decreaseListLevel:]):
+        (-[WKWebView _changeListType:]):
+        (-[WKWebView _setFont:sender:]):
+        (-[WKWebView _setFontSize:sender:]):
+        (-[WKWebView _setTextColor:sender:]):
+
+        Add definitions for the new editing methods on WKWebView, using macros (`WEBCORE_PRIVATE_COMMAND` on macOS and
+        `FORWARD_ACTION_TO_WKCONTENTVIEW` on iOS) to help reduce the code duplication.
+
+        (-[WKWebView _pasteAsQuotation:]): Deleted.
+
+        Remove this method definition, which is now replaced by macros on iOS and macOS.
+
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+
+        Introduce the new SPI to WKWebView (WKPrivate), and add FIXMEs to remove old, unprefixed variants of the SPI.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::increaseListLevel):
+        (WebKit::WebPageProxy::decreaseListLevel):
+        (WebKit::WebPageProxy::changeListType):
+
+        Add plumbing for these list editing commands.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _increaseListLevelForWebView:]):
+        (-[WKContentView _decreaseListLevelForWebView:]):
+        (-[WKContentView _changeListTypeForWebView:]):
+        (-[WKContentView _toggleStrikeThroughForWebView:]):
+        (-[WKContentView _setFontForWebView:sender:]):
+        (-[WKContentView _setFontSizeForWebView:sender:]):
+        (-[WKContentView _setTextColorForWebView:sender:]):
+        (-[WKContentView toggleStrikeThroughForWebView:]):
+        (-[WKContentView setFontForWebView:sender:]):
+        (-[WKContentView setFontSizeForWebView:sender:]):
+        (-[WKContentView setTextColorForWebView:sender:]):
+        (-[WKContentView canPerformActionForWebView:withSender:]):
+
+        Check for the new action selectors here, and additionally add validation for `_pasteAsQuotation:`. Let the
+        unprefixed versions of these methods simply call the prefixed versions (these method implementations will be
+        removed in a followup once doing so would not affect any clients of WebKit).
+
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::increaseListLevel):
+        (WebKit::WebPage::decreaseListLevel):
+        (WebKit::WebPage::changeListType):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
+        Add stubs for several list editing commands that are yet to be hooked up to WebCore. These will be implemented
+        in a future patch.
+
 2018-11-09  Antti Koivisto  <antti@apple.com>
 
         Use OptionSet for layout milestones
index 12a4149..4db7ef5 100644 (file)
@@ -257,6 +257,13 @@ static std::optional<WebCore::ScrollbarOverlayStyle> toCoreScrollbarStyle(_WKOve
 }
 #endif
 
+#define FORWARD_ACTION_TO_WKCONTENTVIEW(_action) \
+    - (void)_action:(id)sender \
+    { \
+        if (self.usesStandardContentView) \
+            [_contentView _action ## ForWebView:sender]; \
+    }
+
 @implementation WKWebView {
     std::unique_ptr<WebKit::NavigationState> _navigationState;
     std::unique_ptr<WebKit::UIDelegate> _uiDelegate;
@@ -1384,17 +1391,8 @@ ALLOW_DEPRECATED_DECLARATIONS_END
     return [super resignFirstResponder];
 }
 
-#define FORWARD_ACTION_TO_WKCONTENTVIEW(_action) \
-    - (void)_action:(id)sender \
-    { \
-        if (self.usesStandardContentView) \
-            [_contentView _action ## ForWebView:sender]; \
-    }
-
 FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
 
-#undef FORWARD_ACTION_TO_WKCONTENTVIEW
-
 - (BOOL)canPerformAction:(SEL)action withSender:(id)sender
 {
     #define FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(_action) \
@@ -1402,14 +1400,16 @@ FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
             return self.usesStandardContentView && [_contentView canPerformActionForWebView:action withSender:sender];
 
     FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW)
-
-    FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(_pasteAsQuotation)
+    FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW)
+    FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(setTextColor:sender)
+    FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(setFontSize:sender)
+    FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(setFont:sender)
+    FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(_setTextColor:sender)
+    FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(_setFontSize:sender)
+    FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW(_setFont:sender)
 
     #undef FORWARD_CANPERFORMACTION_TO_WKCONTENTVIEW
 
-    if (action == @selector(setTextColor:sender:) || action == @selector(setFontSize:sender:) || action == @selector(setFont:sender:))
-        return self.usesStandardContentView && [_contentView canPerformActionForWebView:action withSender:sender];
-
     return [super canPerformAction:action withSender:sender];
 }
 
@@ -1420,8 +1420,13 @@ FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
             return [_contentView targetForActionForWebView:action withSender:sender];
 
     FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW)
-
-    FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW(_pasteAsQuotation)
+    FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW)
+    FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW(setTextColor:sender)
+    FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW(setFontSize:sender)
+    FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW(setFont:sender)
+    FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW(_setTextColor:sender)
+    FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW(_setFontSize:sender)
+    FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW(_setFont:sender)
 
     #undef FORWARD_TARGETFORACTION_TO_WKCONTENTVIEW
 
@@ -4292,6 +4297,70 @@ IGNORE_WARNINGS_END
 
 @implementation WKWebView (WKPrivate)
 
+#if PLATFORM(MAC)
+
+#define WEBCORE_PRIVATE_COMMAND(command) - (void)_##command:(id)sender { _page->executeEditCommand(#command ## _s); }
+
+WEBCORE_PRIVATE_COMMAND(alignCenter)
+WEBCORE_PRIVATE_COMMAND(alignJustified)
+WEBCORE_PRIVATE_COMMAND(alignLeft)
+WEBCORE_PRIVATE_COMMAND(alignRight)
+WEBCORE_PRIVATE_COMMAND(insertOrderedList)
+WEBCORE_PRIVATE_COMMAND(insertUnorderedList)
+WEBCORE_PRIVATE_COMMAND(insertNestedOrderedList)
+WEBCORE_PRIVATE_COMMAND(insertNestedUnorderedList)
+WEBCORE_PRIVATE_COMMAND(indent)
+WEBCORE_PRIVATE_COMMAND(outdent)
+WEBCORE_PRIVATE_COMMAND(pasteAsQuotation);
+
+#undef WEBCORE_PRIVATE_COMMAND
+
+- (void)_toggleStrikeThrough:(id)sender
+{
+    _page->executeEditCommand("strikethrough"_s);
+}
+
+- (void)_increaseListLevel:(id)sender
+{
+    _page->increaseListLevel();
+}
+
+- (void)_decreaseListLevel:(id)sender
+{
+    _page->decreaseListLevel();
+}
+
+- (void)_changeListType:(id)sender
+{
+    _page->changeListType();
+}
+
+#endif // PLATFORM(MAC)
+
+#if PLATFORM(IOS_FAMILY)
+
+FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
+
+- (void)_setFont:(UIFont *)font sender:(id)sender
+{
+    if (self.usesStandardContentView)
+        [_contentView setFontForWebView:font sender:sender];
+}
+
+- (void)_setFontSize:(CGFloat)fontSize sender:(id)sender
+{
+    if (self.usesStandardContentView)
+        [_contentView setFontSizeForWebView:fontSize sender:sender];
+}
+
+- (void)_setTextColor:(UIColor *)color sender:(id)sender
+{
+    if (self.usesStandardContentView)
+        [_contentView setTextColorForWebView:color sender:sender];
+}
+
+#endif // PLATFORM(IOS_FAMILY)
+
 - (BOOL)_isEditable
 {
     return _page->isEditable();
@@ -4638,16 +4707,6 @@ IGNORE_WARNINGS_END
     return nil;
 }
 
-- (void)_pasteAsQuotation:(id)sender
-{
-#if PLATFORM(MAC)
-    _impl->executeEditCommandForSelector(_cmd);
-#else
-    if (self.usesStandardContentView)
-        [_contentView _pasteAsQuotationForWebView:sender];
-#endif
-}
-
 + (BOOL)_handlesSafeBrowsing
 {
     return DEFAULT_SAFE_BROWSING_ENABLED;
@@ -6026,6 +6085,7 @@ static WebCore::UserInterfaceLayoutDirection toUserInterfaceLayoutDirection(UISe
 
 @end
 
+#undef FORWARD_ACTION_TO_WKCONTENTVIEW
 
 @implementation WKWebView (WKTesting)
 
index a7169e5..23e68da 100644 (file)
@@ -186,11 +186,30 @@ typedef NS_OPTIONS(NSUInteger, _WKRectEdge) {
 - (_WKAttachment *)_insertAttachmentWithFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType completion:(void(^)(BOOL success))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (_WKAttachment *)_attachmentForIdentifier:(NSString *)identifier WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
-- (IBAction)_pasteAsQuotation:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
-
 + (BOOL)_handlesSafeBrowsing WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
+- (IBAction)_alignCenter:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_alignJustified:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_alignLeft:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_alignRight:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_indent:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_outdent:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_toggleStrikeThrough:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_insertOrderedList:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_insertUnorderedList:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_insertNestedOrderedList:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_insertNestedUnorderedList:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_increaseListLevel:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_decreaseListLevel:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_changeListType:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (IBAction)_pasteAsQuotation:(id)sender WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 #if TARGET_OS_IPHONE
+
+- (void)_setFont:(UIFont *)font sender:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
+- (void)_setFontSize:(CGFloat)fontSize sender:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
+- (void)_setTextColor:(UIColor *)color sender:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
+
 // DERECATED: The setters of the three following function are deprecated, please use overrideLayoutParameters.
 // Define the smallest size a page take with a regular viewport.
 @property (nonatomic, readonly) CGSize _minimumLayoutSizeOverride;
@@ -371,6 +390,7 @@ typedef NS_OPTIONS(NSUInteger, _WKRectEdge) {
 #if TARGET_OS_IPHONE
 
 @interface WKWebView () <UIResponderStandardEditActions>
+// FIXME: Remove these once internal clients have moved to the underscore-prefixed versions.
 - (void)alignCenter:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
 - (void)alignJustified:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
 - (void)alignLeft:(id)sender WK_API_AVAILABLE(ios(WK_IOS_TBA));
index 644db56..8375ca3 100644 (file)
@@ -1756,6 +1756,24 @@ void WebPageProxy::validateCommand(const String& commandName, WTF::Function<void
     m_process->send(Messages::WebPage::ValidateCommand(commandName, callbackID), m_pageID);
 }
 
+void WebPageProxy::increaseListLevel()
+{
+    if (isValid())
+        m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
+}
+
+void WebPageProxy::decreaseListLevel()
+{
+    if (isValid())
+        m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
+}
+
+void WebPageProxy::changeListType()
+{
+    if (isValid())
+        m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
+}
+
 void WebPageProxy::updateFontAttributesAfterEditorStateChange()
 {
     m_cachedFontAttributesAtSelectionStart.reset();
index f15c22e..f10d615 100644 (file)
@@ -545,6 +545,10 @@ public:
     bool hasSelectedRange() const { return m_editorState.selectionIsRange; }
     bool isContentEditable() const { return m_editorState.isContentEditable; }
 
+    void increaseListLevel();
+    void decreaseListLevel();
+    void changeListType();
+
     std::optional<WebCore::FontAttributes> cachedFontAttributesAtSelectionStart() const { return m_cachedFontAttributesAtSelectionStart; }
 
 #if PLATFORM(COCOA)
index 560ea53..5c41425 100644 (file)
@@ -134,6 +134,23 @@ typedef std::pair<WebKit::InteractionInformationRequest, InteractionInformationC
     M(alignCenter) \
     M(alignJustified)
 
+#define FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(M) \
+    M(_alignCenter) \
+    M(_alignJustified) \
+    M(_alignLeft) \
+    M(_alignRight) \
+    M(_indent) \
+    M(_outdent) \
+    M(_toggleStrikeThrough) \
+    M(_insertOrderedList) \
+    M(_insertUnorderedList) \
+    M(_insertNestedOrderedList) \
+    M(_insertNestedUnorderedList) \
+    M(_increaseListLevel) \
+    M(_decreaseListLevel) \
+    M(_changeListType) \
+    M(_pasteAsQuotation)
+
 namespace WebKit {
 
 struct WKSelectionDrawingInfo {
@@ -339,7 +356,7 @@ struct WKAutoCorrectionData {
 #define DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW(_action) \
     - (void)_action ## ForWebView:(id)sender;
 FOR_EACH_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
-DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW(_pasteAsQuotation)
+FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
 #undef DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW
 
 - (void)setFontForWebView:(UIFont *)fontFamily sender:(id)sender;
index c806e10..70c8836 100644 (file)
@@ -2194,8 +2194,7 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
     }
 
 FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKWEBVIEW)
-
-FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
+FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKWEBVIEW)
 
 #undef FORWARD_ACTION_TO_WKWEBVIEW
 
@@ -2285,18 +2284,37 @@ FORWARD_ACTION_TO_WKWEBVIEW(_pasteAsQuotation)
     [[UIKeyboardImpl sharedInstance] replaceText:sender];
 }
 
-#define WEBCORE_COMMAND_FOR_WEBVIEW(command) - (void)command ## ForWebView:(id)sender { _page->executeEditCommand(#command ## _s); }
-
+#define WEBCORE_COMMAND_FOR_WEBVIEW(command) \
+    - (void)_ ## command ## ForWebView:(id)sender { _page->executeEditCommand(#command ## _s); } \
+    - (void)command ## ForWebView:(id)sender { [self _ ## command ## ForWebView:sender]; }
 WEBCORE_COMMAND_FOR_WEBVIEW(insertOrderedList);
 WEBCORE_COMMAND_FOR_WEBVIEW(insertUnorderedList);
+WEBCORE_COMMAND_FOR_WEBVIEW(insertNestedOrderedList);
+WEBCORE_COMMAND_FOR_WEBVIEW(insertNestedUnorderedList);
 WEBCORE_COMMAND_FOR_WEBVIEW(indent);
 WEBCORE_COMMAND_FOR_WEBVIEW(outdent);
 WEBCORE_COMMAND_FOR_WEBVIEW(alignLeft);
 WEBCORE_COMMAND_FOR_WEBVIEW(alignRight);
 WEBCORE_COMMAND_FOR_WEBVIEW(alignCenter);
 WEBCORE_COMMAND_FOR_WEBVIEW(alignJustified);
+#undef WEBCORE_COMMAND_FOR_WEBVIEW
 
-- (void)toggleStrikeThroughForWebView:(id)sender
+- (void)_increaseListLevelForWebView:(id)sender
+{
+    _page->increaseListLevel();
+}
+
+- (void)_decreaseListLevelForWebView:(id)sender
+{
+    _page->decreaseListLevel();
+}
+
+- (void)_changeListTypeForWebView:(id)sender
+{
+    _page->changeListType();
+}
+
+- (void)_toggleStrikeThroughForWebView:(id)sender
 {
     _page->executeEditCommand("StrikeThrough"_s);
 }
@@ -2311,7 +2329,7 @@ WEBCORE_COMMAND_FOR_WEBVIEW(alignJustified);
     _page->executeEditCommand("FontSizeDelta"_s, "-1"_s);
 }
 
-- (void)setFontForWebView:(UIFont *)font sender:(id)sender
+- (void)_setFontForWebView:(UIFont *)font sender:(id)sender
 {
     WebCore::FontChanges changes;
     changes.setFontFamily(font.familyName);
@@ -2322,19 +2340,37 @@ WEBCORE_COMMAND_FOR_WEBVIEW(alignJustified);
     _page->changeFont(WTFMove(changes));
 }
 
-- (void)setFontSizeForWebView:(CGFloat)fontSize sender:(id)sender
+- (void)_setFontSizeForWebView:(CGFloat)fontSize sender:(id)sender
 {
     WebCore::FontChanges changes;
     changes.setFontSize(fontSize);
     _page->changeFont(WTFMove(changes));
 }
 
-- (void)setTextColorForWebView:(UIColor *)color sender:(id)sender
+- (void)_setTextColorForWebView:(UIColor *)color sender:(id)sender
 {
     _page->executeEditCommand("ForeColor"_s, WebCore::Color(color.CGColor).serialized());
 }
 
-#undef WEBCORE_COMMAND_FOR_WEBVIEW
+- (void)toggleStrikeThroughForWebView:(id)sender
+{
+    [self _toggleStrikeThroughForWebView:sender];
+}
+
+- (void)setFontForWebView:(UIFont *)font sender:(id)sender
+{
+    [self _setFontForWebView:font sender:sender];
+}
+
+- (void)setFontSizeForWebView:(CGFloat)fontSize sender:(id)sender
+{
+    [self _setFontSizeForWebView:fontSize sender:sender];
+}
+
+- (void)setTextColorForWebView:(UIColor *)color sender:(id)sender
+{
+    [self _setTextColorForWebView:color sender:sender];
+}
 
 - (NSDictionary *)textStylingAtPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
 {
@@ -2392,11 +2428,16 @@ WEBCORE_COMMAND_FOR_WEBVIEW(alignJustified);
         return editorState.isContentRichlyEditable && editorState.selectionIsRange && !_showingTextStyleOptions;
     if (_showingTextStyleOptions)
         return (action == @selector(toggleBoldface:) || action == @selector(toggleItalics:) || action == @selector(toggleUnderline:));
-    if (action == @selector(toggleBoldface:) || action == @selector(toggleItalics:) || action == @selector(toggleUnderline:) || action == @selector(toggleStrikeThrough:)
-        || action == @selector(insertOrderedList:) || action == @selector(insertUnorderedList:) || action == @selector(indent:) || action == @selector(outdent:)
+    // FIXME: Some of the following checks should be removed once internal clients move to the underscore-prefixed versions.
+    if (action == @selector(toggleBoldface:) || action == @selector(toggleItalics:) || action == @selector(toggleUnderline:) || action == @selector(_toggleStrikeThrough:)
+        || action == @selector(_alignLeft:) || action == @selector(_alignRight:) || action == @selector(_alignCenter:) || action == @selector(_alignJustified:)
+        || action == @selector(_setTextColor:sender:) || action == @selector(_setFont:sender:) || action == @selector(_setFontSize:sender:)
+        || action == @selector(_insertOrderedList:) || action == @selector(_insertUnorderedList:) || action == @selector(_insertNestedOrderedList:) || action == @selector(_insertNestedUnorderedList:)
+        || action == @selector(_increaseListLevel:) || action == @selector(_decreaseListLevel:) || action == @selector(_changeListType:) || action == @selector(_indent:) || action == @selector(_outdent:)
+        || action == @selector(increaseSize:) || action == @selector(decreaseSize:)
+        || action == @selector(toggleStrikeThrough:) || action == @selector(insertOrderedList:) || action == @selector(insertUnorderedList:) || action == @selector(indent:) || action == @selector(outdent:)
         || action == @selector(alignLeft:) || action == @selector(alignRight:) || action == @selector(alignCenter:) || action == @selector(alignJustified:)
-        || action == @selector(increaseSize:) || action == @selector(decreaseSize:) || action == @selector(setTextColor:sender:)
-        || action == @selector(setFont:sender:) || action == @selector(setFontSize:sender:)) {
+        || action == @selector(setTextColor:sender:) || action == @selector(setFont:sender:) || action == @selector(setFontSize:sender:)) {
         // FIXME: This should be more nuanced in the future, rather than returning YES for all richly editable areas. For instance, outdent: should be disabled when the selection is already
         // at the outermost indentation level.
         return editorState.isContentRichlyEditable;
@@ -2404,7 +2445,7 @@ WEBCORE_COMMAND_FOR_WEBVIEW(alignJustified);
     if (action == @selector(cut:))
         return !editorState.isInPasswordField && editorState.isContentEditable && editorState.selectionIsRange;
     
-    if (action == @selector(paste:)) {
+    if (action == @selector(paste:) || action == @selector(_pasteAsQuotation:)) {
         if (editorState.selectionIsNone || !editorState.isContentEditable)
             return NO;
         UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
index 0925420..73baf00 100644 (file)
@@ -1150,6 +1150,21 @@ void WebPage::setEditable(bool editable)
     }
 }
 
+void WebPage::increaseListLevel()
+{
+    // FIXME: Not implemented.
+}
+
+void WebPage::decreaseListLevel()
+{
+    // FIXME: Not implemented.
+}
+
+void WebPage::changeListType()
+{
+    // FIXME: Not implemented.
+}
+
 bool WebPage::isEditingCommandEnabled(const String& commandName)
 {
     Frame& frame = m_page->focusController().focusedOrMainFrame();
index 6c68649..650a752 100644 (file)
@@ -1186,6 +1186,10 @@ private:
     void executeEditCommand(const String&, const String&);
     void setEditable(bool);
 
+    void increaseListLevel();
+    void decreaseListLevel();
+    void changeListType();
+
     void setNeedsFontAttributes(bool);
 
     void mouseEvent(const WebMouseEvent&);
index 68700f7..dbc6812 100644 (file)
@@ -212,6 +212,10 @@ messages -> WebPage LegacyReceiver {
     ValidateCommand(String name, WebKit::CallbackID callbackID)
     ExecuteEditCommand(String name, String argument)
 
+    IncreaseListLevel()
+    DecreaseListLevel()
+    ChangeListType()
+
     SetNeedsFontAttributes(bool needsFontAttributes)
 
     RequestFontAttributesAtSelectionStart(WebKit::CallbackID callbackID)
index ed73b3d..f220818 100644 (file)
@@ -1,3 +1,26 @@
+2018-11-09  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Cocoa] Introduce WKWebView SPI to insert nested ordered and unordered lists
+        https://bugs.webkit.org/show_bug.cgi?id=191410
+        <rdar://problem/45898610>
+
+        Reviewed by Dean Jackson.
+
+        Move WKWebViewEditActions from iOS to WebKitCocoa, and enable the relevant WKWebViewEditActions tests on macOS.
+        Additionally, add new API tests to verify that `-_pasteAsQuotation:` and `-_insertNested(Un)OrderedList:` are
+        hooked up to their respective editing commands.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/WKWebViewEditActions.mm: Renamed from Tools/TestWebKitAPI/Tests/ios/WKWebViewEditActions.mm.
+        (-[TestWKWebView querySelectorExists:]):
+        (-[TestWKWebView insertString:]):
+
+        Add a helper method to insert a piece of text. This abstracts platform differences between iOS and macOS, by
+        invoking the WKWebView directly on macOS and calling on the content view on iOS.
+
+        (TestWebKitAPI::webViewForEditActionTesting):
+        (TestWebKitAPI::TEST):
+
 2018-11-09  Philippe Normand  <pnormand@igalia.com>
 
         [Flatpak] Refactoring and drive-by fixes
index 6eef735..d5a8caa 100644 (file)
                F46A095A1ED8A6E600D4AA55 /* apple.gif in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47D30EB1ED28619000482E1 /* apple.gif */; };
                F46A095B1ED8A6E600D4AA55 /* gif-and-file-input.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */; };
                F47728991E4AE3C1007ABF6A /* full-page-contenteditable.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F47728981E4AE3AD007ABF6A /* full-page-contenteditable.html */; };
+               F4811E5921940BDE00A5E0FD /* WKWebViewEditActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4811E5821940B4400A5E0FD /* WKWebViewEditActions.mm */; };
                F4856CA31E649EA8009D7EE7 /* attachment-element.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4856CA21E6498A8009D7EE7 /* attachment-element.html */; };
                F486B1D01F67952300F34BDD /* DataTransfer-setDragImage.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */; };
                F4A32EC41F05F3850047C544 /* dragstart-change-selection-offscreen.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4A32EC31F05F3780047C544 /* dragstart-change-selection-offscreen.html */; };
                F4F5BB5221667BAA002D06B9 /* TestFontOptions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4F5BB5121667BAA002D06B9 /* TestFontOptions.mm */; };
                F4FA91811E61849B007B8C1D /* WKWebViewMacEditingTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4FA917F1E61849B007B8C1D /* WKWebViewMacEditingTests.mm */; };
                F4FA91831E61857B007B8C1D /* double-click-does-not-select-trailing-space.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4FA91821E618566007B8C1D /* double-click-does-not-select-trailing-space.html */; };
-               F4FB682521643EFC0034607A /* WKWebViewEditActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4FB682421643EFC0034607A /* WKWebViewEditActions.mm */; };
                F4FC077720F013B600CA043C /* significant-text-milestone.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = F4FC077620F0108100CA043C /* significant-text-milestone.html */; };
                F660AA1115A5F631003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F660AA0F15A5F624003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp */; };
                F660AA1515A61ABF003A1243 /* InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F660AA1415A61ABF003A1243 /* InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp */; };
                F47728981E4AE3AD007ABF6A /* full-page-contenteditable.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "full-page-contenteditable.html"; sourceTree = "<group>"; };
                F47D30EB1ED28619000482E1 /* apple.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = apple.gif; sourceTree = "<group>"; };
                F47D30ED1ED28A6C000482E1 /* gif-and-file-input.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "gif-and-file-input.html"; sourceTree = "<group>"; };
+               F4811E5821940B4400A5E0FD /* WKWebViewEditActions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewEditActions.mm; sourceTree = "<group>"; };
                F4856CA21E6498A8009D7EE7 /* attachment-element.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "attachment-element.html"; sourceTree = "<group>"; };
                F486B1CF1F6794FF00F34BDD /* DataTransfer-setDragImage.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "DataTransfer-setDragImage.html"; sourceTree = "<group>"; };
                F493247C1F44DF8D006F4336 /* UIKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIKitSPI.h; sourceTree = "<group>"; };
                F4F5BB5121667BAA002D06B9 /* TestFontOptions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = TestFontOptions.mm; sourceTree = "<group>"; };
                F4FA917F1E61849B007B8C1D /* WKWebViewMacEditingTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewMacEditingTests.mm; sourceTree = "<group>"; };
                F4FA91821E618566007B8C1D /* double-click-does-not-select-trailing-space.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = "double-click-does-not-select-trailing-space.html"; path = "Tests/WebKitCocoa/double-click-does-not-select-trailing-space.html"; sourceTree = SOURCE_ROOT; };
-               F4FB682421643EFC0034607A /* WKWebViewEditActions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewEditActions.mm; sourceTree = "<group>"; };
                F4FC077620F0108100CA043C /* significant-text-milestone.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "significant-text-milestone.html"; sourceTree = "<group>"; };
                F660AA0C15A5F061003A1243 /* GetInjectedBundleInitializationUserDataCallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetInjectedBundleInitializationUserDataCallback.cpp; sourceTree = "<group>"; };
                F660AA0F15A5F624003A1243 /* GetInjectedBundleInitializationUserDataCallback_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetInjectedBundleInitializationUserDataCallback_Bundle.cpp; sourceTree = "<group>"; };
                                7C417F311D19E14800B8EF53 /* WKWebViewDefaultNavigationDelegate.mm */,
                                46E66A8F1F0D75590026D83C /* WKWebViewDiagnosticLogging.mm */,
                                2DB647871F4161F70051A89E /* WKWebViewDoesNotLogDuringInitialization.mm */,
+                               F4811E5821940B4400A5E0FD /* WKWebViewEditActions.mm */,
                                0F3B94A51A77266C00DE3272 /* WKWebViewEvaluateJavaScript.mm */,
                                D3BE5E341E4CE85E00FD563A /* WKWebViewGetContents.mm */,
                                37A9DBE7213B4C9300D261A2 /* WKWebViewServerTrustKVC.mm */,
                                F46849BD1EEF58E400B937FE /* UIPasteboardTests.mm */,
                                F43E3BBE20DADA1E00A4E7ED /* WKScrollViewTests.mm */,
                                514958BD1F7427AC00E87BAD /* WKWebViewAutofillTests.mm */,
-                               F4FB682421643EFC0034607A /* WKWebViewEditActions.mm */,
                        );
                        path = ios;
                        sourceTree = "<group>";
                                7C417F331D19E14800B8EF53 /* WKWebViewDefaultNavigationDelegate.mm in Sources */,
                                46E66A901F0D75590026D83C /* WKWebViewDiagnosticLogging.mm in Sources */,
                                2DB647881F4163D60051A89E /* WKWebViewDoesNotLogDuringInitialization.mm in Sources */,
-                               F4FB682521643EFC0034607A /* WKWebViewEditActions.mm in Sources */,
+                               F4811E5921940BDE00A5E0FD /* WKWebViewEditActions.mm in Sources */,
                                0F3B94A71A77267400DE3272 /* WKWebViewEvaluateJavaScript.mm in Sources */,
                                D34E08761E4E42E1005FF14A /* WKWebViewGetContents.mm in Sources */,
                                F4FA91811E61849B007B8C1D /* WKWebViewMacEditingTests.mm in Sources */,
 
 #import "config.h"
 
-#if PLATFORM(IOS_FAMILY) && WK_API_ENABLED
+#if WK_API_ENABLED
 
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
+#import <WebKit/WKWebViewPrivate.h>
+
+#if PLATFORM(IOS_FAMILY)
 #import "UIKitSPI.h"
 #import <UIKit/UIFontDescriptor.h>
-#import <WebKit/WKWebViewPrivate.h>
+#endif
 
 @interface TestWKWebView (EditActionTesting)
 - (BOOL)querySelectorExists:(NSString *)querySelector;
+- (void)insertString:(NSString *)string;
 @end
 
 @implementation TestWKWebView (EditActionTesting)
     return [[self objectByEvaluatingJavaScript:[NSString stringWithFormat:@"!!document.querySelector(`%@`)", querySelector]] boolValue];
 }
 
+- (void)insertString:(NSString *)string
+{
+#if PLATFORM(IOS_FAMILY)
+    [[self textInputContentView] insertText:string];
+#else
+    [self insertText:string];
+#endif
+}
+
 @end
 
 namespace TestWebKitAPI {
@@ -57,18 +70,39 @@ static RetainPtr<TestWKWebView> webViewForEditActionTesting()
     return webView;
 }
 
+TEST(WKWebViewEditActions, NestedListInsertion)
+{
+    auto webView = webViewForEditActionTesting();
+
+    [webView _insertNestedOrderedList:nil];
+    EXPECT_TRUE([webView querySelectorExists:@"ol"]);
+    EXPECT_TRUE([webView querySelectorExists:@"ol > li"]);
+
+    [webView _insertNestedOrderedList:nil];
+    EXPECT_TRUE([webView querySelectorExists:@"ol > ol"]);
+    EXPECT_TRUE([webView querySelectorExists:@"ol > ol > li"]);
+
+    [webView _insertNestedUnorderedList:nil];
+    EXPECT_TRUE([webView querySelectorExists:@"ol > ol > ul"]);
+    EXPECT_TRUE([webView querySelectorExists:@"ol > ol > ul > li"]);
+
+    [webView _insertNestedUnorderedList:nil];
+    EXPECT_TRUE([webView querySelectorExists:@"ol > ol > ul > ul"]);
+    EXPECT_TRUE([webView querySelectorExists:@"ol > ol > ul > ul > li"]);
+}
+
 TEST(WKWebViewEditActions, ListInsertion)
 {
     auto webView = webViewForEditActionTesting();
 
-    [webView insertOrderedList:nil];
+    [webView _insertOrderedList:nil];
     EXPECT_TRUE([webView querySelectorExists:@"ol"]);
-    [webView insertOrderedList:nil];
+    [webView _insertOrderedList:nil];
     EXPECT_FALSE([webView querySelectorExists:@"ol"]);
 
-    [webView insertUnorderedList:nil];
+    [webView _insertUnorderedList:nil];
     EXPECT_TRUE([webView querySelectorExists:@"ul"]);
-    [webView insertUnorderedList:nil];
+    [webView _insertUnorderedList:nil];
     EXPECT_FALSE([webView querySelectorExists:@"ul"]);
 }
 
@@ -76,14 +110,14 @@ TEST(WKWebViewEditActions, ChangeIndentation)
 {
     auto webView = webViewForEditActionTesting();
 
-    [webView indent:nil];
+    [webView _indent:nil];
     EXPECT_TRUE([webView querySelectorExists:@"blockquote"]);
-    [webView indent:nil];
+    [webView _indent:nil];
     EXPECT_TRUE([webView querySelectorExists:@"blockquote > blockquote"]);
 
-    [webView outdent:nil];
+    [webView _outdent:nil];
     EXPECT_TRUE([webView querySelectorExists:@"blockquote"]);
-    [webView outdent:nil];
+    [webView _outdent:nil];
     EXPECT_FALSE([webView querySelectorExists:@"blockquote"]);
 }
 
@@ -91,13 +125,13 @@ TEST(WKWebViewEditActions, SetAlignment)
 {
     auto webView = webViewForEditActionTesting();
     auto runTest = [webView] {
-        [webView alignCenter:nil];
+        [webView _alignCenter:nil];
         EXPECT_WK_STREQ("center", [webView stylePropertyAtSelectionStart:@"text-align"]);
-        [webView alignLeft:nil];
+        [webView _alignLeft:nil];
         EXPECT_WK_STREQ("left", [webView stylePropertyAtSelectionStart:@"text-align"]);
-        [webView alignRight:nil];
+        [webView _alignRight:nil];
         EXPECT_WK_STREQ("right", [webView stylePropertyAtSelectionStart:@"text-align"]);
-        [webView alignJustified:nil];
+        [webView _alignJustified:nil];
         EXPECT_WK_STREQ("justify", [webView stylePropertyAtSelectionStart:@"text-align"]);
     };
 
@@ -112,24 +146,35 @@ TEST(WKWebViewEditActions, ToggleStrikeThrough)
 {
     auto webView = webViewForEditActionTesting();
     [webView selectAll:nil];
-    [webView toggleStrikeThrough:nil];
+    [webView _toggleStrikeThrough:nil];
     EXPECT_WK_STREQ("line-through", [webView stylePropertyAtSelectionStart:@"-webkit-text-decorations-in-effect"]);
     EXPECT_WK_STREQ("line-through", [webView stylePropertyAtSelectionEnd:@"-webkit-text-decorations-in-effect"]);
 
-    [webView toggleStrikeThrough:nil];
+    [webView _toggleStrikeThrough:nil];
     EXPECT_WK_STREQ("none", [webView stylePropertyAtSelectionStart:@"-webkit-text-decorations-in-effect"]);
     EXPECT_WK_STREQ("none", [webView stylePropertyAtSelectionEnd:@"-webkit-text-decorations-in-effect"]);
 
     [webView collapseToEnd];
-    [webView toggleStrikeThrough:nil];
-    [[webView textInputContentView] insertText:@"Hello"];
+    [webView _toggleStrikeThrough:nil];
+    [webView insertString:@"Hello"];
     EXPECT_WK_STREQ("line-through", [webView stylePropertyAtSelectionStart:@"-webkit-text-decorations-in-effect"]);
 
-    [webView toggleStrikeThrough:nil];
-    [[webView textInputContentView] insertText:@"Hello"];
+    [webView _toggleStrikeThrough:nil];
+    [webView insertString:@"Hello"];
     EXPECT_WK_STREQ("none", [webView stylePropertyAtSelectionStart:@"-webkit-text-decorations-in-effect"]);
 }
 
+TEST(WKWebViewEditActions, PasteAsQuotation)
+{
+    auto webView = webViewForEditActionTesting();
+    [webView selectAll:nil];
+    [webView _executeEditCommand:@"cut" argument:nil completion:nil];
+    [webView _pasteAsQuotation:nil];
+    EXPECT_TRUE([webView querySelectorExists:@"blockquote"]);
+}
+
+#if PLATFORM(IOS_FAMILY)
+
 TEST(WKWebViewEditActions, ChangeFontSize)
 {
     auto webView = webViewForEditActionTesting();
@@ -146,7 +191,7 @@ TEST(WKWebViewEditActions, ChangeFontSize)
     [webView decreaseSize:nil];
     EXPECT_EQ(16, [[webView stylePropertyAtSelectionStart:@"font-size"] floatValue]);
 
-    [webView setFontSize:20 sender:nil];
+    [webView _setFontSize:20 sender:nil];
     EXPECT_EQ(20, [[webView stylePropertyAtSelectionStart:@"font-size"] floatValue]);
 }
 
@@ -155,11 +200,11 @@ TEST(WKWebViewEditActions, SetTextColor)
     auto webView = webViewForEditActionTesting();
     [webView selectAll:nil];
 
-    [webView setTextColor:[UIColor colorWithRed:1 green:0 blue:0 alpha:1] sender:nil];
+    [webView _setTextColor:[UIColor colorWithRed:1 green:0 blue:0 alpha:1] sender:nil];
     EXPECT_WK_STREQ("rgb(255, 0, 0)", [webView stylePropertyAtSelectionStart:@"color"]);
     EXPECT_TRUE([webView querySelectorExists:@"font"]);
 
-    [webView setTextColor:[UIColor colorWithRed:0 green:1 blue:0 alpha:0.2] sender:nil];
+    [webView _setTextColor:[UIColor colorWithRed:0 green:1 blue:0 alpha:0.2] sender:nil];
     EXPECT_WK_STREQ("rgba(0, 255, 0, 0.2)", [webView stylePropertyAtSelectionStart:@"color"]);
     EXPECT_FALSE([webView querySelectorExists:@"font"]);
 }
@@ -170,26 +215,28 @@ TEST(WKWebViewEditActions, SetFontFamily)
     [webView selectAll:nil];
 
     UIFontDescriptor *fontDescriptor = [UIFontDescriptor fontDescriptorWithFontAttributes:@{ UIFontDescriptorFamilyAttribute: @"Helvetica" }];
-    [webView setFont:[UIFont fontWithDescriptor:fontDescriptor size:24] sender:nil];
+    [webView _setFont:[UIFont fontWithDescriptor:fontDescriptor size:24] sender:nil];
     EXPECT_WK_STREQ("Helvetica", [webView stylePropertyAtSelectionStart:@"font-family"]);
     EXPECT_WK_STREQ("24px", [webView stylePropertyAtSelectionStart:@"font-size"]);
     EXPECT_WK_STREQ("normal", [webView stylePropertyAtSelectionStart:@"font-weight"]);
     EXPECT_WK_STREQ("normal", [webView stylePropertyAtSelectionStart:@"font-style"]);
 
-    [webView setFont:[UIFont fontWithName:@"TimesNewRomanPS-BoldMT" size:12] sender:nil];
+    [webView _setFont:[UIFont fontWithName:@"TimesNewRomanPS-BoldMT" size:12] sender:nil];
     EXPECT_WK_STREQ("\"Times New Roman\"", [webView stylePropertyAtSelectionStart:@"font-family"]);
     EXPECT_WK_STREQ("12px", [webView stylePropertyAtSelectionStart:@"font-size"]);
     EXPECT_WK_STREQ("bold", [webView stylePropertyAtSelectionStart:@"font-weight"]);
     EXPECT_WK_STREQ("normal", [webView stylePropertyAtSelectionStart:@"font-style"]);
 
     fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic | UIFontDescriptorTraitBold];
-    [webView setFont:[UIFont fontWithDescriptor:fontDescriptor size:20] sender:nil];
+    [webView _setFont:[UIFont fontWithDescriptor:fontDescriptor size:20] sender:nil];
     EXPECT_WK_STREQ("Helvetica", [webView stylePropertyAtSelectionStart:@"font-family"]);
     EXPECT_WK_STREQ("20px", [webView stylePropertyAtSelectionStart:@"font-size"]);
     EXPECT_WK_STREQ("bold", [webView stylePropertyAtSelectionStart:@"font-weight"]);
     EXPECT_WK_STREQ("italic", [webView stylePropertyAtSelectionStart:@"font-style"]);
 }
 
+#endif // PLATFORM(IOS_FAMILY)
+
 } // namespace TestWebKitAPI
 
-#endif // PLATFORM(IOS_FAMILY) && WK_API_ENABLED
+#endif // WK_API_ENABLED