https://bugs.webkit.org/show_bug.cgi?id=173277
<rdar://problem/
32396742>
Reviewed by Dan Bernstein.
* UIProcess/API/Cocoa/WKWebView.mm:
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _lookupForWebView:]):
(-[WKContentView _shareForWebView:]):
(-[WKContentView _addShortcutForWebView:]):
(-[WKContentView _promptForReplaceForWebView:]):
(-[WKContentView _transliterateChineseForWebView:]):
(-[WKContentView _reanalyzeForWebView:]):
(-[WKContentView replaceForWebView:]):
(-[WKContentView canPerformAction:withSender:]):
(-[WKContentView copyForWebView:]):
(-[WKContentView cutForWebView:]):
(-[WKContentView pasteForWebView:]):
(-[WKContentView selectForWebView:]):
(-[WKContentView selectAllForWebView:]):
(-[WKContentView toggleBoldfaceForWebView:]):
(-[WKContentView toggleItalicsForWebView:]):
(-[WKContentView toggleUnderlineForWebView:]):
(-[WKContentView _showTextStyleOptionsForWebView:]):
(-[WKContentView _defineForWebView:]):
(-[WKContentView _arrowKeyForWebView:]):
(-[WKContentView _lookup:]): Deleted.
(-[WKContentView _share:]): Deleted.
(-[WKContentView _addShortcut:]): Deleted.
(-[WKContentView _promptForReplace:]): Deleted.
(-[WKContentView _transliterateChinese:]): Deleted.
(-[WKContentView _reanalyze:]): Deleted.
(-[WKContentView replace:]): Deleted.
(-[WKContentView copy:]): Deleted.
(-[WKContentView cut:]): Deleted.
(-[WKContentView paste:]): Deleted.
(-[WKContentView select:]): Deleted.
(-[WKContentView selectAll:]): Deleted.
(-[WKContentView toggleBoldface:]): Deleted.
(-[WKContentView toggleItalics:]): Deleted.
(-[WKContentView toggleUnderline:]): Deleted.
(-[WKContentView _showTextStyleOptions:]): Deleted.
(-[WKContentView _define:]): Deleted.
(-[WKContentView _arrowKey:]): Deleted.
Similar to what r211897 did for canPerformAction, and other patches
have done for other selectors, forward methods for standard editing
commands from WKContentView up to WKWebView, and back down to WKContentView.
This is necessary because these are not treated as normal
responder-chain-respecting methods, so they do not bubble up the view tree.
In 211897, WKContentView (who is usually first responder and thus receives
the actions) stopped claiming to be able to perform these actions, depending
on this non-existent bubbling behavior to keep them working.
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* Tests/WebKit2Cocoa/WKContentViewEditingActions.mm:
Add a test ensuring that -copy on WKContentView will cause text to be copied.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@218144
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2017-06-12 Tim Horton <timothy_horton@apple.com>
+
+ [iOS] Cmd-C doesn't copy text from WKWebView
+ https://bugs.webkit.org/show_bug.cgi?id=173277
+ <rdar://problem/32396742>
+
+ Reviewed by Dan Bernstein.
+
+ * UIProcess/API/Cocoa/WKWebView.mm:
+ * UIProcess/API/Cocoa/WKWebViewInternal.h:
+ * UIProcess/ios/WKContentViewInteraction.h:
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (-[WKContentView _lookupForWebView:]):
+ (-[WKContentView _shareForWebView:]):
+ (-[WKContentView _addShortcutForWebView:]):
+ (-[WKContentView _promptForReplaceForWebView:]):
+ (-[WKContentView _transliterateChineseForWebView:]):
+ (-[WKContentView _reanalyzeForWebView:]):
+ (-[WKContentView replaceForWebView:]):
+ (-[WKContentView canPerformAction:withSender:]):
+ (-[WKContentView copyForWebView:]):
+ (-[WKContentView cutForWebView:]):
+ (-[WKContentView pasteForWebView:]):
+ (-[WKContentView selectForWebView:]):
+ (-[WKContentView selectAllForWebView:]):
+ (-[WKContentView toggleBoldfaceForWebView:]):
+ (-[WKContentView toggleItalicsForWebView:]):
+ (-[WKContentView toggleUnderlineForWebView:]):
+ (-[WKContentView _showTextStyleOptionsForWebView:]):
+ (-[WKContentView _defineForWebView:]):
+ (-[WKContentView _arrowKeyForWebView:]):
+ (-[WKContentView _lookup:]): Deleted.
+ (-[WKContentView _share:]): Deleted.
+ (-[WKContentView _addShortcut:]): Deleted.
+ (-[WKContentView _promptForReplace:]): Deleted.
+ (-[WKContentView _transliterateChinese:]): Deleted.
+ (-[WKContentView _reanalyze:]): Deleted.
+ (-[WKContentView replace:]): Deleted.
+ (-[WKContentView copy:]): Deleted.
+ (-[WKContentView cut:]): Deleted.
+ (-[WKContentView paste:]): Deleted.
+ (-[WKContentView select:]): Deleted.
+ (-[WKContentView selectAll:]): Deleted.
+ (-[WKContentView toggleBoldface:]): Deleted.
+ (-[WKContentView toggleItalics:]): Deleted.
+ (-[WKContentView toggleUnderline:]): Deleted.
+ (-[WKContentView _showTextStyleOptions:]): Deleted.
+ (-[WKContentView _define:]): Deleted.
+ (-[WKContentView _arrowKey:]): Deleted.
+ Similar to what r211897 did for canPerformAction, and other patches
+ have done for other selectors, forward methods for standard editing
+ commands from WKContentView up to WKWebView, and back down to WKContentView.
+
+ This is necessary because these are not treated as normal
+ responder-chain-respecting methods, so they do not bubble up the view tree.
+
+ In 211897, WKContentView (who is usually first responder and thus receives
+ the actions) stopped claiming to be able to perform these actions, depending
+ on this non-existent bubbling behavior to keep them working.
+
2017-06-12 Chris Dumez <cdumez@apple.com>
Null dereference under WebProcessPool::pageRemovedFromProcess()
return [super resignFirstResponder];
}
-#define FOR_EACH_WKCONTENTVIEW_ACTION(M) \
- M(_addShortcut) \
- M(_arrowKey) \
- M(_define) \
- M(_lookup) \
- M(_promptForReplace) \
- M(_reanalyze) \
- M(_share) \
- M(_showTextStyleOptions) \
- M(_transliterateChinese) \
- M(copy) \
- M(cut) \
- M(paste) \
- M(replace) \
- M(select) \
- M(selectAll) \
- M(toggleBoldface) \
- M(toggleItalics) \
- M(toggleUnderline) \
-
#define FORWARD_ACTION_TO_WKCONTENTVIEW(_action) \
- (void)_action:(id)sender \
{ \
if (self.usesStandardContentView) \
- [_contentView _action:sender]; \
+ [_contentView _action ## ForWebView:sender]; \
}
FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
return [super canPerformAction:action withSender:sender];
}
-#undef FOR_EACH_WKCONTENTVIEW_ACTION
-
static inline CGFloat floorToDevicePixel(CGFloat input, float deviceScaleFactor)
{
return CGFloor(input * deviceScaleFactor) / deviceScaleFactor;
- (void)_didChangeAvoidsUnsafeArea:(BOOL)avoidsUnsafeArea;
+- (void)_addShortcut:(id)sender;
+- (void)_arrowKey:(id)sender;
+- (void)_define:(id)sender;
+- (void)_lookup:(id)sender;
+- (void)_reanalyze:(id)sender;
+- (void)_share:(id)sender;
+- (void)_showTextStyleOptions:(id)sender;
+- (void)_promptForReplace:(id)sender;
+- (void)_transliterateChinese:(id)sender;
+- (void)replace:(id)sender;
+
@property (nonatomic, readonly) WKPasswordView *_passwordView;
@property (nonatomic, readonly) BOOL _isBackground;
typedef BlockPtr<void(WebKit::InteractionInformationAtPosition)> InteractionInformationCallback;
typedef std::pair<WebKit::InteractionInformationRequest, InteractionInformationCallback> InteractionInformationRequestAndCallback;
+#define FOR_EACH_WKCONTENTVIEW_ACTION(M) \
+ M(_addShortcut) \
+ M(_arrowKey) \
+ M(_define) \
+ M(_lookup) \
+ M(_promptForReplace) \
+ M(_reanalyze) \
+ M(_share) \
+ M(_showTextStyleOptions) \
+ M(_transliterateChinese) \
+ M(copy) \
+ M(cut) \
+ M(paste) \
+ M(replace) \
+ M(select) \
+ M(selectAll) \
+ M(toggleBoldface) \
+ M(toggleItalics) \
+ M(toggleUnderline)
+
namespace WebKit {
struct WKSelectionDrawingInfo {
- (BOOL)resignFirstResponderForWebView;
- (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender;
-- (void)_addShortcut:(id)sender;
-- (void)_arrowKey:(id)sender;
-- (void)_define:(id)sender;
-- (void)_lookup:(id)sender;
-- (void)_reanalyze:(id)sender;
-- (void)_share:(id)sender;
-- (void)_showTextStyleOptions:(id)sender;
-- (void)_promptForReplace:(id)sender;
-- (void)_transliterateChinese:(id)sender;
-- (void)replace:(id)sender;
+#define DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW(_action) \
+ - (void)_action ## ForWebView:(id)sender;
+FOR_EACH_WKCONTENTVIEW_ACTION(DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW)
+#undef DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW
#if ENABLE(TOUCH_EVENTS)
- (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsDefault;
return (_page->editorState().isContentRichlyEditable) ? richTypes : plainTextTypes;
}
-- (void)_lookup:(id)sender
+#define FORWARD_ACTION_TO_WKWEBVIEW(_action) \
+ - (void)_action:(id)sender \
+ { \
+ [_webView _action:sender]; \
+ }
+
+FOR_EACH_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKWEBVIEW)
+
+#undef FORWARD_ACTION_TO_WKWEBVIEW
+
+- (void)_lookupForWebView:(id)sender
{
RetainPtr<WKContentView> view = self;
_page->getSelectionContext([view](const String& selectedText, const String& textBefore, const String& textAfter, CallbackBase::Error error) {
});
}
-- (void)_share:(id)sender
+- (void)_shareForWebView:(id)sender
{
RetainPtr<WKContentView> view = self;
_page->getSelectionOrContentsAsString([view](const String& string, CallbackBase::Error error) {
});
}
-- (void)_addShortcut:(id)sender
+- (void)_addShortcutForWebView:(id)sender
{
if (_textSelectionAssistant)
[_textSelectionAssistant showTextServiceFor:[self selectedText] fromRect:_page->editorState().postLayoutData().selectionRects[0].rect()];
_page->selectWordBackward();
}
-- (void)_promptForReplace:(id)sender
+- (void)_promptForReplaceForWebView:(id)sender
{
const auto& wordAtSelection = _page->editorState().postLayoutData().wordAtSelection;
if (wordAtSelection.isEmpty())
[_textSelectionAssistant scheduleReplacementsForText:wordAtSelection];
}
-- (void)_transliterateChinese:(id)sender
+- (void)_transliterateChineseForWebView:(id)sender
{
[_textSelectionAssistant scheduleChineseTransliterationForText:_page->editorState().postLayoutData().wordAtSelection];
}
-- (void)_reanalyze:(id)sender
+- (void)_reanalyzeForWebView:(id)sender
{
[_textSelectionAssistant scheduleReanalysis];
}
-- (void)replace:(id)sender
+- (void)replaceForWebView:(id)sender
{
[[UIKeyboardImpl sharedInstance] replaceText:sender];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
- return NO;
+ return [_webView canPerformAction:action withSender:sender];
}
- (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender
[_textSelectionAssistant hideTextStyleOptions];
}
-- (void)copy:(id)sender
+- (void)copyForWebView:(id)sender
{
_page->executeEditCommand(ASCIILiteral("copy"));
}
-- (void)cut:(id)sender
+- (void)cutForWebView:(id)sender
{
_page->executeEditCommand(ASCIILiteral("cut"));
}
-- (void)paste:(id)sender
+- (void)pasteForWebView:(id)sender
{
_page->executeEditCommand(ASCIILiteral("paste"));
}
-- (void)select:(id)sender
+- (void)selectForWebView:(id)sender
{
[_textSelectionAssistant selectWord];
// We cannot use selectWord command, because we want to be able to select the word even when it is the last in the paragraph.
_page->extendSelection(WordGranularity);
}
-- (void)selectAll:(id)sender
+- (void)selectAllForWebView:(id)sender
{
[_textSelectionAssistant selectAll:sender];
_page->executeEditCommand(ASCIILiteral("selectAll"));
}
-- (void)toggleBoldface:(id)sender
+- (void)toggleBoldfaceForWebView:(id)sender
{
if (!_page->editorState().isContentRichlyEditable)
return;
[self executeEditCommandWithCallback:@"toggleBold"];
}
-- (void)toggleItalics:(id)sender
+- (void)toggleItalicsForWebView:(id)sender
{
if (!_page->editorState().isContentRichlyEditable)
return;
[self executeEditCommandWithCallback:@"toggleItalic"];
}
-- (void)toggleUnderline:(id)sender
+- (void)toggleUnderlineForWebView:(id)sender
{
if (!_page->editorState().isContentRichlyEditable)
return;
[self executeEditCommandWithCallback:@"toggleUnderline"];
}
-- (void)_showTextStyleOptions:(id)sender
+- (void)_showTextStyleOptionsForWebView:(id)sender
{
_showingTextStyleOptions = YES;
[_textSelectionAssistant showTextStyleOptions];
[_webSelectionAssistant showDictionaryFor:text fromRect:presentationRect];
}
-- (void)_define:(id)sender
+- (void)_defineForWebView:(id)sender
{
if ([[getMCProfileConnectionClass() sharedConnection] effectiveBoolValueForSetting:MCFeatureDefinitionLookupAllowed] == MCRestrictedBoolExplicitNo)
return;
return (_page->editorState().isContentEditable) ? editableKeyCommands : nonEditableKeyCommands;
}
-- (void)_arrowKey:(id)sender
+- (void)_arrowKeyForWebView:(id)sender
{
UIKeyCommand* command = sender;
[self handleKeyEvent:command._triggeringEvent];
+2017-06-12 Tim Horton <timothy_horton@apple.com>
+
+ [iOS] Cmd-C doesn't copy text from WKWebView
+ https://bugs.webkit.org/show_bug.cgi?id=173277
+ <rdar://problem/32396742>
+
+ Reviewed by Dan Bernstein.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * Tests/WebKit2Cocoa/WKContentViewEditingActions.mm:
+ Add a test ensuring that -copy on WKContentView will cause text to be copied.
+
2017-06-12 Jiewen Tan <jiewen_tan@apple.com>
[WebCrypto] Remove experimental feature flag of SubtleCrypto
2D1C04A71D76298B000A6816 /* TestNavigationDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D1C04A61D76298B000A6816 /* TestNavigationDelegate.mm */; };
2D4CF8BD1D8360CC0001CE8D /* WKThumbnailView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D4CF8BC1D8360CC0001CE8D /* WKThumbnailView.mm */; };
2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */; };
+ 2D838B1F1EEF3A5C009B980E /* WKContentViewEditingActions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */; };
2DB0232F1E4E871800707123 /* InteractionDeadlockAfterCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DB0232E1E4E871800707123 /* InteractionDeadlockAfterCrash.mm */; };
2DC4CF771D2D9DD800ECCC94 /* DataDetection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DC4CF761D2D9DD800ECCC94 /* DataDetection.mm */; };
2DC60E231E79F88C00FA6C7D /* DoAfterNextPresentationUpdateAfterCrash.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DC60E221E79F88C00FA6C7D /* DoAfterNextPresentationUpdateAfterCrash.mm */; };
2D51A0C51C8BF00400765C45 /* DOMHTMLVideoElementWrapper.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMHTMLVideoElementWrapper.mm; sourceTree = "<group>"; };
2D640B5417875DFF00BFAF99 /* ScrollPinningBehaviors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScrollPinningBehaviors.cpp; sourceTree = "<group>"; };
2D8104CB1BEC13E70020DA46 /* FindInPage.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FindInPage.mm; sourceTree = "<group>"; };
+ 2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKContentViewEditingActions.mm; sourceTree = "<group>"; };
2D9A53AE1B31FA8D0074D5AA /* ShrinkToFit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ShrinkToFit.mm; sourceTree = "<group>"; };
2DB0232E1E4E871800707123 /* InteractionDeadlockAfterCrash.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InteractionDeadlockAfterCrash.mm; sourceTree = "<group>"; };
2DC4CF761D2D9DD800ECCC94 /* DataDetection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DataDetection.mm; sourceTree = "<group>"; };
5120C83C1E6750790025B250 /* WebsiteDataStoreCustomPaths.mm */,
5C9E56841DF9143D00C9EE33 /* WebsitePolicies.mm */,
1F83571A1D3FFB0E00E3967B /* WKBackForwardList.mm */,
+ 2D838B1E1EEF3A5B009B980E /* WKContentViewEditingActions.mm */,
51D124971E763AF8002B2820 /* WKHTTPCookieStore.mm */,
375E0E151D66674400EFEC2C /* WKNSNumber.mm */,
37B47E2E1D64E7CA005F4EFF /* WKObject.mm */,
2D51A0C71C8BF00C00765C45 /* DOMHTMLVideoElementWrapper.mm in Sources */,
46397B951DC2C850009A78AE /* DOMNode.mm in Sources */,
5198A2401EA7E59F008910B7 /* InitialWarmedProcessUsed.mm in Sources */,
+ 2D838B1F1EEF3A5C009B980E /* WKContentViewEditingActions.mm in Sources */,
7CCE7EBC1A411A7E00447C4C /* DOMNodeFromJSObject.mm in Sources */,
7CCE7EBD1A411A7E00447C4C /* DOMRangeOfString.mm in Sources */,
115EB3431EE0BA03003C2C0A /* ViewportSizeForViewportUnits.mm in Sources */,
--- /dev/null
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if PLATFORM(IOS)
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
+#import <WebKit/WebKit.h>
+#import <wtf/RetainPtr.h>
+
+static UIView *recursiveFindWKContentView(UIView *view)
+{
+ if ([view isKindOfClass:NSClassFromString(@"WKContentView")])
+ return view;
+
+ for (UIView *subview in view.subviews) {
+ UIView *contentView = recursiveFindWKContentView(subview);
+ if (contentView)
+ return contentView;
+ }
+
+ return nil;
+}
+
+TEST(WebKit2, WKContentViewEditingActions)
+{
+ RetainPtr<TestWKWebView> webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+
+ [webView synchronouslyLoadTestPageNamed:@"simple"];
+
+ UIView *contentView = recursiveFindWKContentView(webView.get());
+
+ if ([contentView canPerformAction:@selector(selectAll:) withSender:nil])
+ [contentView selectAll:nil];
+ [webView _doAfterNextPresentationUpdate:^ {
+ if ([contentView canPerformAction:@selector(copy:) withSender:nil])
+ [contentView copy:nil];
+ }];
+
+ while (1) {
+ [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
+ if ([[[UIPasteboard generalPasteboard] string] isEqualToString:@"Simple HTML file."])
+ break;
+ TestWebKitAPI::Util::sleep(0.01);
+ }
+}
+
+#endif