WebKit Bugzilla
Attachment 347452 Details for
Bug 184271
: [iOS] Paste is missing from callout bar when pasteboard only contains custom data
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
bug-184271-20180818151947.patch (text/plain), 19.99 KB, created by
Wenson Hsieh
on 2018-08-18 15:19:49 PDT
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
Wenson Hsieh
Created:
2018-08-18 15:19:49 PDT
Size:
19.99 KB
patch
obsolete
>Subversion Revision: 235010 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 881286fd27485fde5c882f4d5cb9ef702bf9aa62..a518c8f1f1561bb3c2e429024ad8565efd1b19a6 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,16 @@ >+2018-08-18 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [iOS] Paste is missing from callout bar when pasteboard only contains custom data >+ https://bugs.webkit.org/show_bug.cgi?id=184271 >+ <rdar://problem/39256708> >+ >+ Reviewed by Ryosuke Niwa. >+ >+ Export a couple of WebCore functions for use in WebKit. >+ >+ * dom/Document.h: >+ * platform/Pasteboard.h: >+ > 2018-08-17 Ryosuke Niwa <rniwa@webkit.org> > > Pack booleans in Event into a bitfield >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 86ce120869ce08ef9fe8ca17529744e7ac510d4e..f09c645ec1d86f80f6a05da5a5c2a4444f6d541e 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,42 @@ >+2018-08-18 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [iOS] Paste is missing from callout bar when pasteboard only contains custom data >+ https://bugs.webkit.org/show_bug.cgi?id=184271 >+ <rdar://problem/39256708> >+ >+ Reviewed by Ryosuke Niwa. >+ >+ Currently, the "paste:" selector action cannot be performed during editing if the pasteboard only contains >+ custom pasteboard data. This is because logic in -[WKContentView canPerformActionForWebView:withSender:] only >+ checks against a list of pasteboard types which does not include the type identifier for custom pasteboard data. >+ To fix this, we allow pasting only in the case where none of the other type identifiers exist in the pasteboard, >+ as long as the custom pasteboard data type identifier is present, and the custom pasteboard data's origin >+ matches the origin of the focused frame's document. >+ >+ Test: PasteMixedContent.CopyAndPasteWithCustomPasteboardDataOnly >+ >+ * Shared/EditorState.cpp: >+ (WebKit::EditorState::encode const): >+ (WebKit::EditorState::decode): >+ * Shared/EditorState.h: >+ >+ Add a originIdentifierForPasteboard field, and add support for encoding it when propagating EditorState via IPC. >+ >+ * UIProcess/ios/WKContentViewInteraction.mm: >+ (-[WKContentView canPerformActionForWebView:withSender:]): >+ >+ If none of the conventional pasteboard type identifiers for rich or plain text editing are present, check to see >+ if we have custom pasteboard data; if so, only allow pasting if the custom pasteboard data's origin matches that >+ of the focused frame's document origin. >+ >+ Additionally refactor a bit of logic by pulling out `_page->editorState()` into a separate local variable, used >+ throughout the rest of the method. >+ >+ * WebProcess/WebPage/WebPage.cpp: >+ (WebKit::WebPage::editorState const): >+ >+ Send the focused frame's document origin to the UI process via EditorState. >+ > 2018-08-17 Tim Horton <timothy_horton@apple.com> > > Start bringing up Unified Sources in WebKit2 >diff --git a/Source/WebCore/dom/Document.h b/Source/WebCore/dom/Document.h >index 2e3afc20b059a8b6b964b89b9b595f4b071c18c1..d79a44e9482e785ccc50082f99ab14b562708b1c 100644 >--- a/Source/WebCore/dom/Document.h >+++ b/Source/WebCore/dom/Document.h >@@ -1006,7 +1006,7 @@ public: > void incDOMTreeVersion() { m_domTreeVersion = ++s_globalTreeVersion; } > uint64_t domTreeVersion() const { return m_domTreeVersion; } > >- String originIdentifierForPasteboard(); >+ WEBCORE_EXPORT String originIdentifierForPasteboard(); > > // XPathEvaluator methods > WEBCORE_EXPORT ExceptionOr<Ref<XPathExpression>> createExpression(const String& expression, RefPtr<XPathNSResolver>&&); >diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h >index 111f3afceaa7856bd71283a5b8e7a05348364063..d5433dd920ae0ee592bd45fd560cdd3e38a34721 100644 >--- a/Source/WebCore/platform/Pasteboard.h >+++ b/Source/WebCore/platform/Pasteboard.h >@@ -170,7 +170,7 @@ struct PasteboardCustomData { > WEBCORE_EXPORT static PasteboardCustomData fromSharedBuffer(const SharedBuffer&); > > #if PLATFORM(COCOA) >- static const char* cocoaType(); >+ WEBCORE_EXPORT static const char* cocoaType(); > #endif > }; > >diff --git a/Source/WebKit/Shared/EditorState.cpp b/Source/WebKit/Shared/EditorState.cpp >index 02ca36735899770453a7f14f323eec16101d51ad..2dfa51866c43e1442486ba14a15ba5b9d8db9eb3 100644 >--- a/Source/WebKit/Shared/EditorState.cpp >+++ b/Source/WebKit/Shared/EditorState.cpp >@@ -53,6 +53,8 @@ void EditorState::encode(IPC::Encoder& encoder) const > encoder << lastMarkedRect; > encoder << markedText; > #endif >+ >+ encoder << originIdentifierForPasteboard; > } > > bool EditorState::decode(IPC::Decoder& decoder, EditorState& result) >@@ -98,6 +100,9 @@ bool EditorState::decode(IPC::Decoder& decoder, EditorState& result) > return false; > #endif > >+ if (!decoder.decode(result.originIdentifierForPasteboard)) >+ return false; >+ > return true; > } > >diff --git a/Source/WebKit/Shared/EditorState.h b/Source/WebKit/Shared/EditorState.h >index a2173a49b482c12c988a6d1f2ae725c7a84a5f91..2085c1587760020e0ebae0b996a914e88508e789 100644 >--- a/Source/WebKit/Shared/EditorState.h >+++ b/Source/WebKit/Shared/EditorState.h >@@ -80,6 +80,8 @@ struct EditorState { > String markedText; > #endif > >+ String originIdentifierForPasteboard; >+ > struct PostLayoutData { > uint32_t typingAttributes { AttributeNone }; > #if PLATFORM(IOS) || PLATFORM(GTK) >diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >index 470741fe7fa3c6dd8439923a17954445c6be1122..e829d450125f07c8523a739360a8016566a1f968 100644 >--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm >@@ -2276,35 +2276,49 @@ - (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender > if (action == @selector(_arrowKey:)) > return [self isFirstResponder]; > >+ auto editorState = _page->editorState(); > if (action == @selector(_showTextStyleOptions:)) >- return _page->editorState().isContentRichlyEditable && _page->editorState().selectionIsRange && !_showingTextStyleOptions; >+ 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:)) >- return _page->editorState().isContentRichlyEditable; >+ return editorState.isContentRichlyEditable; > if (action == @selector(cut:)) >- return !_page->editorState().isInPasswordField && _page->editorState().isContentEditable && _page->editorState().selectionIsRange; >+ return !editorState.isInPasswordField && editorState.isContentEditable && editorState.selectionIsRange; > > if (action == @selector(paste:)) { >- if (_page->editorState().selectionIsNone || !_page->editorState().isContentEditable) >+ if (editorState.selectionIsNone || !editorState.isContentEditable) > return NO; > UIPasteboard *pasteboard = [UIPasteboard generalPasteboard]; > NSArray *types = [self supportedPasteboardTypesForCurrentSelection]; > NSIndexSet *indices = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [pasteboard numberOfItems])]; >- return [pasteboard containsPasteboardTypes:types inItemSet:indices]; >+ if ([pasteboard containsPasteboardTypes:types inItemSet:indices]) >+ return YES; >+ >+ auto focusedDocumentOrigin = editorState.originIdentifierForPasteboard; >+ if (focusedDocumentOrigin.isEmpty()) >+ return NO; >+ >+ NSArray *allCustomPasteboardData = [pasteboard dataForPasteboardType:@(PasteboardCustomData::cocoaType()) inItemSet:indices]; >+ for (NSData *data in allCustomPasteboardData) { >+ auto buffer = SharedBuffer::create(data); >+ if (PasteboardCustomData::fromSharedBuffer(buffer.get()).origin == focusedDocumentOrigin) >+ return YES; >+ } >+ return NO; > } > > if (action == @selector(copy:)) { >- if (_page->editorState().isInPasswordField) >+ if (editorState.isInPasswordField) > return NO; >- return _page->editorState().selectionIsRange; >+ return editorState.selectionIsRange; > } > > if (action == @selector(_define:)) { >- if (_page->editorState().isInPasswordField || !_page->editorState().selectionIsRange) >+ if (editorState.isInPasswordField || !editorState.selectionIsRange) > return NO; > >- NSUInteger textLength = _page->editorState().postLayoutData().selectedTextLength; >+ NSUInteger textLength = editorState.postLayoutData().selectedTextLength; > // FIXME: We should be calling UIReferenceLibraryViewController to check if the length is > // acceptable, but the interface takes a string. > // <rdar://problem/15254406> >@@ -2320,7 +2334,7 @@ - (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender > } > > if (action == @selector(_lookup:)) { >- if (_page->editorState().isInPasswordField) >+ if (editorState.isInPasswordField) > return NO; > > #if !PLATFORM(IOSMAC) >@@ -2328,18 +2342,18 @@ - (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender > return NO; > #endif > >- return _page->editorState().selectionIsRange; >+ return editorState.selectionIsRange; > } > > if (action == @selector(_share:)) { >- if (_page->editorState().isInPasswordField || !_page->editorState().selectionIsRange) >+ if (editorState.isInPasswordField || !editorState.selectionIsRange) > return NO; > >- return _page->editorState().postLayoutData().selectedTextLength > 0; >+ return editorState.postLayoutData().selectedTextLength > 0; > } > > if (action == @selector(_addShortcut:)) { >- if (_page->editorState().isInPasswordField || !_page->editorState().selectionIsRange) >+ if (editorState.isInPasswordField || !editorState.selectionIsRange) > return NO; > > NSString *selectedText = [self selectedText]; >@@ -2354,7 +2368,7 @@ - (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender > } > > if (action == @selector(_promptForReplace:)) { >- if (!_page->editorState().selectionIsRange || !_page->editorState().postLayoutData().isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled]) >+ if (!editorState.selectionIsRange || !editorState.postLayoutData().isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled]) > return NO; > if ([[self selectedText] _containsCJScriptsOnly]) > return NO; >@@ -2362,24 +2376,24 @@ - (BOOL)canPerformActionForWebView:(SEL)action withSender:(id)sender > } > > if (action == @selector(_transliterateChinese:)) { >- if (!_page->editorState().selectionIsRange || !_page->editorState().postLayoutData().isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled]) >+ if (!editorState.selectionIsRange || !editorState.postLayoutData().isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled]) > return NO; > return UIKeyboardEnabledInputModesAllowChineseTransliterationForText([self selectedText]); > } > > if (action == @selector(select:)) { > // Disable select in password fields so that you can't see word boundaries. >- return !_page->editorState().isInPasswordField && [self hasContent] && !_page->editorState().selectionIsNone && !_page->editorState().selectionIsRange; >+ return !editorState.isInPasswordField && [self hasContent] && !editorState.selectionIsNone && !editorState.selectionIsRange; > } > > if (action == @selector(selectAll:)) { >- if (!_page->editorState().selectionIsNone && !_page->editorState().selectionIsRange) >+ if (!editorState.selectionIsNone && !editorState.selectionIsRange) > return YES; > return NO; > } > > if (action == @selector(replace:)) >- return _page->editorState().isContentEditable && !_page->editorState().isInPasswordField; >+ return editorState.isContentEditable && !editorState.isInPasswordField; > > return [super canPerformAction:action withSender:sender]; > } >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index dff88dcc4c4bf6d1043922bf51ddb2ad024fc390..82fff4948d28c6a6c8b25568bc589508c9603a37 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -921,6 +921,9 @@ EditorState WebPage::editorState(IncludePostLayoutDataHint shouldIncludePostLayo > result.hasComposition = editor.hasComposition(); > result.shouldIgnoreSelectionChanges = editor.ignoreSelectionChanges(); > >+ if (auto* document = frame.document()) >+ result.originIdentifierForPasteboard = document->originIdentifierForPasteboard(); >+ > bool canIncludePostLayoutData = frame.view() && !frame.view()->needsLayout(); > if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::Yes && canIncludePostLayoutData) { > auto& postLayoutData = result.postLayoutData(); >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 823737e006a83996af9bcfd899a0599412cf7ec3..773c9ac975fb03f2aa028f4eb37642c9d1197258 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,31 @@ >+2018-08-18 Wenson Hsieh <wenson_hsieh@apple.com> >+ >+ [iOS] Paste is missing from callout bar when pasteboard only contains custom data >+ https://bugs.webkit.org/show_bug.cgi?id=184271 >+ <rdar://problem/39256708> >+ >+ Reviewed by Ryosuke Niwa. >+ >+ Add a new API test to verify that on both iOS and macOS, copied custom pasteboard data can only be pasted in a >+ matching origin. Additionally verify that on iOS, the web view is capable of performing the "paste:" selector. >+ >+ * TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm: >+ (TestWebKitAPI::TEST): >+ (imagePath): Deleted. >+ (writeTypesAndDataToPasteboard): Deleted. >+ (setUpWebView): Deleted. >+ (markupString): Deleted. >+ >+ Make this test file no longer exclusive to macOS. >+ >+ * TestWebKitAPI/cocoa/TestWKWebView.h: >+ * TestWebKitAPI/cocoa/TestWKWebView.mm: >+ (-[TestWKWebView synchronouslyLoadHTMLString:baseURL:]): >+ >+ Tweak this helper to also take in a `baseURL`. Defaults to using the TestWebKitAPI bundle resource URL. >+ >+ (-[TestWKWebView synchronouslyLoadHTMLString:]): >+ > 2018-08-17 Jonathan Bedard <jbedard@apple.com> > > Add back --wtf-only to run-api-tests >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm >index 9f4ae5f071b3c0be10424e0f2cf22fe814615fbd..b5fb481be4705fc2b444c7a608a3dac044e6dcea 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/PasteMixedContent.mm >@@ -25,15 +25,21 @@ > > #include "config.h" > >-#if PLATFORM(MAC) && WK_API_ENABLED >+#if WK_API_ENABLED > > #import "PlatformUtilities.h" >+#import "TestURLSchemeHandler.h" > #import "TestWKWebView.h" > #import <WebKit/WKPreferencesRef.h> > #import <WebKit/WKPreferencesRefPrivate.h> >+#import <WebKit/WKWebViewPrivate.h> > #import <wtf/RetainPtr.h> > #import <wtf/text/WTFString.h> > >+namespace TestWebKitAPI { >+ >+#if PLATFORM(MAC) >+ > static NSString *imagePath() > { > return [[NSBundle mainBundle] pathForResource:@"icon" ofType:@"png" inDirectory:@"TestWebKitAPI.resources"]; >@@ -96,8 +102,6 @@ static NSString *markupString() > return @"<script>foo()</script><strong onmouseover='javascript:void(0)'>HELLO WORLD</strong>"; > } > >-namespace TestWebKitAPI { >- > TEST(PasteMixedContent, ImageFileAndPlainText) > { > auto webView = setUpWebView(); >@@ -251,6 +255,39 @@ TEST(PasteMixedContent, PasteURLWrittenToPasteboardUsingWriteObjects) > EXPECT_WK_STREQ([webView stringByEvaluatingJavaScript:@"document.querySelector('a').textContent"], urlToCopy); > } > >+#endif // PLATFORM(MAC) >+ >+TEST(PasteMixedContent, CopyAndPasteWithCustomPasteboardDataOnly) >+{ >+ NSString *markupForSource = @"<body oncopy=\"event.preventDefault(); event.clipboardData.setData('foo', 'bar')\">hello</body>"; >+ NSString *markupForDestination = @"<input autofocus onpaste=\"event.preventDefault(); this.value = event.clipboardData.getData('foo')\">"; >+ >+ auto schemeHandler = adoptNS([[TestURLSchemeHandler alloc] init]); >+ auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]); >+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"same"]; >+ [configuration setURLSchemeHandler:schemeHandler.get() forURLScheme:@"different"]; >+ >+ auto source = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]); >+ [source synchronouslyLoadHTMLString:markupForSource baseURL:[NSURL URLWithString:@"same://"]]; >+ [source selectAll:nil]; >+ [source _executeEditCommand:@"copy" argument:nil completion:nil]; >+ >+ auto destination = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 400, 400) configuration:configuration.get()]); >+ [destination synchronouslyLoadHTMLString:markupForDestination baseURL:[NSURL URLWithString:@"same://"]]; >+ [destination paste:nil]; >+ EXPECT_WK_STREQ("bar", [destination stringByEvaluatingJavaScript:@"document.querySelector('input').value"]); >+#if PLATFORM(IOS) >+ EXPECT_TRUE([destination canPerformAction:@selector(paste:) withSender:nil]); >+#endif >+ >+ [destination synchronouslyLoadHTMLString:markupForDestination baseURL:[NSURL URLWithString:@"different://"]]; >+ [destination paste:nil]; >+ EXPECT_WK_STREQ("", [destination stringByEvaluatingJavaScript:@"document.querySelector('input').value"]); >+#if PLATFORM(IOS) >+ EXPECT_FALSE([destination canPerformAction:@selector(paste:) withSender:nil]); >+#endif >+} >+ > } // namespace TestWebKitAPI > >-#endif // PLATFORM(MAC) && WK_API_ENABLED >+#endif // WK_API_ENABLED >diff --git a/Tools/TestWebKitAPI/cocoa/TestWKWebView.h b/Tools/TestWebKitAPI/cocoa/TestWKWebView.h >index 051fa292dc7cb063f322a9479e176d87524e0c67..613dfae8aa1dff764c773cfc5014e5c3e1638166 100644 >--- a/Tools/TestWebKitAPI/cocoa/TestWKWebView.h >+++ b/Tools/TestWebKitAPI/cocoa/TestWKWebView.h >@@ -51,6 +51,7 @@ > - (void)performAfterReceivingMessage:(NSString *)message action:(dispatch_block_t)action; > - (void)loadTestPageNamed:(NSString *)pageName; > - (void)synchronouslyLoadHTMLString:(NSString *)html; >+- (void)synchronouslyLoadHTMLString:(NSString *)html baseURL:(NSURL *)url; > - (void)synchronouslyLoadTestPageNamed:(NSString *)pageName; > - (id)objectByEvaluatingJavaScript:(NSString *)script; > - (NSString *)stringByEvaluatingJavaScript:(NSString *)script; >diff --git a/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm b/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm >index d096cf09c55cdf1c6244662d31adab16b278ec98..5f2ca53bd0629c1dff2cc408f1f52b29b9dcee1e 100644 >--- a/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm >+++ b/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm >@@ -246,13 +246,17 @@ - (void)loadTestPageNamed:(NSString *)pageName > [self loadRequest:request]; > } > >-- (void)synchronouslyLoadHTMLString:(NSString *)html >+- (void)synchronouslyLoadHTMLString:(NSString *)html baseURL:(NSURL *)url > { >- NSURL *testResourceURL = [[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"TestWebKitAPI.resources"]; >- [self loadHTMLString:html baseURL:testResourceURL]; >+ [self loadHTMLString:html baseURL:url]; > [self _test_waitForDidFinishNavigation]; > } > >+- (void)synchronouslyLoadHTMLString:(NSString *)html >+{ >+ [self synchronouslyLoadHTMLString:html baseURL:[[[NSBundle mainBundle] bundleURL] URLByAppendingPathComponent:@"TestWebKitAPI.resources"]]; >+} >+ > - (void)synchronouslyLoadTestPageNamed:(NSString *)pageName > { > [self loadTestPageNamed:pageName];
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 184271
:
347440
| 347452 |
347498