Diff
Modified: trunk/LayoutTests/ChangeLog (261824 => 261825)
--- trunk/LayoutTests/ChangeLog 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/LayoutTests/ChangeLog 2020-05-18 19:05:27 UTC (rev 261825)
@@ -1,3 +1,21 @@
+2020-05-18 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Allow clipboard API access when pasting from a menu item or key binding
+ https://bugs.webkit.org/show_bug.cgi?id=211990
+ <rdar://problem/63308916>
+
+ Reviewed by Megan Gardner.
+
+ Add a new layout test to verify that the contents of the clipboard can be read while performing a paste that was
+ not triggered from the DOM.
+
+ * editing/async-clipboard/clipboard-read-while-pasting-expected.txt: Added.
+ * editing/async-clipboard/clipboard-read-while-pasting.html: Added.
+ * platform/win/TestExpectations:
+ * resources/ui-helper.js:
+ (window.UIHelper.async copyText):
+ (window.UIHelper.async paste):
+
2020-05-18 Peng Liu <peng.l...@apple.com>
REGRESSION (r261493?): media/video-isplayingtoautomotiveheadunit.html is a flaky failure
Added: trunk/LayoutTests/editing/async-clipboard/clipboard-read-while-pasting-expected.txt (0 => 261825)
--- trunk/LayoutTests/editing/async-clipboard/clipboard-read-while-pasting-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/async-clipboard/clipboard-read-while-pasting-expected.txt 2020-05-18 19:05:27 UTC (rev 261825)
@@ -0,0 +1,12 @@
+This test verifies that the clipboard is accessible while performing a paste from native UI. To manually run the test, click the 'Copy' button above, and then paste in the text field below using native UI (e.g. menu item or cmd+V on macOS, and the callout menu on iOS). The text 'The quick brown fox jumped over the lazy dog.' should be read via the clipboard API, without triggering an additional DOM paste menu.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS doneWritingText became true
+PASS Read text: 'The quick brown fox jumped over the lazy dog.'
+PASS doneReadingText became true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Copy
Added: trunk/LayoutTests/editing/async-clipboard/clipboard-read-while-pasting.html (0 => 261825)
--- trunk/LayoutTests/editing/async-clipboard/clipboard-read-while-pasting.html (rev 0)
+++ trunk/LayoutTests/editing/async-clipboard/clipboard-read-while-pasting.html 2020-05-18 19:05:27 UTC (rev 261825)
@@ -0,0 +1,63 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true experimental:AsyncClipboardAPIEnabled=true domPasteAllowed=false ] -->
+<html>
+ <meta charset="utf8">
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <script src=""
+ <script src=""
+ <style>
+ button {
+ width: 300px;
+ padding: 1em;
+ }
+
+ input {
+ display: block;
+ font-size: 40px;
+ width: 300px;
+ }
+ </style>
+ </head>
+ <script>
+ jsTestIsAsync = true;
+ doneWritingText = false;
+ doneReadingText = false;
+
+ description("This test verifies that the clipboard is accessible while performing a paste from native UI. To manually run the test, click the 'Copy' button above, and then paste in the text field below using native UI (e.g. menu item or cmd+V on macOS, and the callout menu on iOS). The text 'The quick brown fox jumped over the lazy dog.' should be read via the clipboard API, without triggering an additional DOM paste menu.");
+
+ async function runTest() {
+ const copyButton = document.querySelector("button");
+ const field = document.querySelector("input")
+
+ copyButton.addEventListener("click", async () => {
+ await navigator.clipboard.writeText("The quick brown fox jumped over the lazy dog.");
+ doneWritingText = true;
+ });
+
+ field.addEventListener("paste", async event => {
+ event.preventDefault();
+ testPassed(`Read text: '${await navigator.clipboard.readText()}'`);
+ doneReadingText = true;
+ });
+
+ if (!window.testRunner)
+ return;
+
+ await UIHelper.activateElement(copyButton);
+ await new Promise(resolve => shouldBecomeEqual("doneWritingText", "true", resolve));
+ await UIHelper.activateElementAndWaitForInputSession(field);
+ await UIHelper.paste();
+ await new Promise(resolve => shouldBecomeEqual("doneReadingText", "true", resolve));
+
+ field.blur();
+ await UIHelper.waitForKeyboardToHide();
+ finishJSTest();
+ }
+
+ addEventListener("load", runTest);
+ </script>
+ <body>
+ <button>Copy</button>
+ <input>
+ </body>
+</html>
Modified: trunk/LayoutTests/platform/win/TestExpectations (261824 => 261825)
--- trunk/LayoutTests/platform/win/TestExpectations 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/LayoutTests/platform/win/TestExpectations 2020-05-18 19:05:27 UTC (rev 261825)
@@ -1206,6 +1206,7 @@
webkit.org/b/203100 editing/async-clipboard/clipboard-read-text-from-platform.html [ Skip ]
webkit.org/b/203100 editing/async-clipboard/clipboard-read-text-same-origin.html [ Skip ]
webkit.org/b/203100 editing/async-clipboard/clipboard-read-text.html [ Skip ]
+webkit.org/b/203100 editing/async-clipboard/clipboard-read-while-pasting.html [ Skip ]
webkit.org/b/203100 editing/async-clipboard/sanitize-when-writing-image.html [ Skip ]
webkit.org/b/203100 editing/async-clipboard/sanitize-when-reading-markup.html [ Skip ]
Modified: trunk/LayoutTests/resources/ui-helper.js (261824 => 261825)
--- trunk/LayoutTests/resources/ui-helper.js 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/LayoutTests/resources/ui-helper.js 2020-05-18 19:05:27 UTC (rev 261825)
@@ -1190,10 +1190,14 @@
}
static async copyText(text) {
- const copyTextScript = `uiController.copyText(\`${text.replace(/`/g, "\\`")}\`)()`;
+ const copyTextScript = `uiController.copyText(\`${text.replace(/`/g, "\\`")}\`)`;
return new Promise(resolve => testRunner.runUIScript(copyTextScript, resolve));
}
+ static async paste() {
+ return new Promise(resolve => testRunner.runUIScript(`uiController.paste()`, resolve));
+ }
+
static async setContinuousSpellCheckingEnabled(enabled) {
return new Promise(resolve => {
testRunner.runUIScript(`uiController.setContinuousSpellCheckingEnabled(${enabled})`, resolve);
Modified: trunk/Source/WebCore/ChangeLog (261824 => 261825)
--- trunk/Source/WebCore/ChangeLog 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Source/WebCore/ChangeLog 2020-05-18 19:05:27 UTC (rev 261825)
@@ -1,3 +1,49 @@
+2020-05-18 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Allow clipboard API access when pasting from a menu item or key binding
+ https://bugs.webkit.org/show_bug.cgi?id=211990
+ <rdar://problem/63308916>
+
+ Reviewed by Megan Gardner.
+
+ Allow the contents of the clipboard to be programmatically requested by the page while pasting from trusted UI
+ (i.e. the paste menu item, or when WebKit API is called by the app to trigger the paste). This allows the
+ 'reading' part of the async clipboard API (`read` and `readText`) to be used when the user pastes in an editable
+ element, without having to fall back to showing the DOM paste access menu.
+
+ Note that this change should not have an effect on the pasteboard security model, since it only grants the page
+ programmatic access to the contents of the pasteboard in the case where access to the pasteboard has already
+ been granted by the user. Additionally, even in the event that the web process is compromised, even if the web
+ process can be tricked into believing it has been granted pasteboard access, the changes in r259151 will prevent
+ it from being able to request pasteboard data, unless the user (or the application, on behalf of the user) has
+ explicitly pasted via trusted API calls that are inaccessible from the web process.
+
+ Test: editing/async-clipboard/clipboard-read-while-pasting.html
+
+ * editing/Editor.cpp:
+ (WebCore::Editor::paste):
+ (WebCore::Editor::pasteAsPlainText):
+ (WebCore::Editor::pasteAsQuotation):
+
+ If `FromMenuOrKeyBinding::Yes` is passed in, set the `m_pastingFromMenuOrKeyBinding` flag to true during the
+ scope of the paste command.
+
+ * editing/Editor.h:
+ (WebCore::Editor::isPastingFromMenuOrKeyBinding const):
+ * editing/EditorCommand.cpp:
+ (WebCore::executePaste):
+ (WebCore::executePasteAndMatchStyle):
+ (WebCore::executePasteAsPlainText):
+ (WebCore::executePasteAsQuotation):
+
+ Pass in `FromMenuOrKeyBinding::Yes` when triggering the paste from a menu item or key binding.
+
+ * page/Frame.cpp:
+ (WebCore::Frame::requestDOMPasteAccess):
+
+ When pasting from menu or key binding, grant the page DOM paste access without requiring the DOM paste access
+ UI to be shown and confirmed.
+
2020-05-18 Per Arne Vollan <pvol...@apple.com>
[Win] Fix AppleWin build
Modified: trunk/Source/WebCore/editing/Editor.cpp (261824 => 261825)
--- trunk/Source/WebCore/editing/Editor.cpp 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Source/WebCore/editing/Editor.cpp 2020-05-18 19:05:27 UTC (rev 261825)
@@ -118,6 +118,7 @@
#include <pal/FileSizeFormatter.h>
#include <pal/system/Sound.h>
#include <pal/text/KillRing.h>
+#include <wtf/SetForScope.h>
#include <wtf/unicode/CharacterNames.h>
#if PLATFORM(MAC)
@@ -1444,13 +1445,15 @@
}
}
-void Editor::paste()
+void Editor::paste(FromMenuOrKeyBinding fromMenuOrKeyBinding)
{
- paste(*Pasteboard::createForCopyAndPaste());
+ paste(*Pasteboard::createForCopyAndPaste(), fromMenuOrKeyBinding);
}
-void Editor::paste(Pasteboard& pasteboard)
+void Editor::paste(Pasteboard& pasteboard, FromMenuOrKeyBinding fromMenuOrKeyBinding)
{
+ SetForScope<bool> pasteScope { m_pastingFromMenuOrKeyBinding, fromMenuOrKeyBinding == FromMenuOrKeyBinding::Yes };
+
if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::Paste))
return; // DHTML did the whole operation
if (!canPaste())
@@ -1463,8 +1466,10 @@
pasteAsPlainTextWithPasteboard(pasteboard);
}
-void Editor::pasteAsPlainText()
+void Editor::pasteAsPlainText(FromMenuOrKeyBinding fromMenuOrKeyBinding)
{
+ SetForScope<bool> pasteScope { m_pastingFromMenuOrKeyBinding, fromMenuOrKeyBinding == FromMenuOrKeyBinding::Yes };
+
if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::PasteAsPlainText))
return;
if (!canPaste())
@@ -1473,8 +1478,10 @@
pasteAsPlainTextWithPasteboard(*Pasteboard::createForCopyAndPaste());
}
-void Editor::pasteAsQuotation()
+void Editor::pasteAsQuotation(FromMenuOrKeyBinding fromMenuOrKeyBinding)
{
+ SetForScope<bool> pasteScope { m_pastingFromMenuOrKeyBinding, fromMenuOrKeyBinding == FromMenuOrKeyBinding::Yes };
+
if (!dispatchClipboardEvent(findEventTargetFromSelection(), ClipboardEventKind::PasteAsQuotation))
return;
if (!canPaste())
Modified: trunk/Source/WebCore/editing/Editor.h (261824 => 261825)
--- trunk/Source/WebCore/editing/Editor.h 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Source/WebCore/editing/Editor.h 2020-05-18 19:05:27 UTC (rev 261825)
@@ -189,10 +189,12 @@
WEBCORE_EXPORT void cut();
WEBCORE_EXPORT void copy();
- WEBCORE_EXPORT void paste();
- void paste(Pasteboard&);
- WEBCORE_EXPORT void pasteAsPlainText();
- void pasteAsQuotation();
+
+ enum class FromMenuOrKeyBinding : bool { No, Yes };
+ WEBCORE_EXPORT void paste(FromMenuOrKeyBinding = FromMenuOrKeyBinding::No);
+ void paste(Pasteboard&, FromMenuOrKeyBinding = FromMenuOrKeyBinding::No);
+ WEBCORE_EXPORT void pasteAsPlainText(FromMenuOrKeyBinding = FromMenuOrKeyBinding::No);
+ void pasteAsQuotation(FromMenuOrKeyBinding = FromMenuOrKeyBinding::No);
WEBCORE_EXPORT void performDelete();
WEBCORE_EXPORT void copyURL(const URL&, const String& title);
@@ -571,6 +573,8 @@
WEBCORE_EXPORT RefPtr<TextPlaceholderElement> insertTextPlaceholder(const IntSize&);
WEBCORE_EXPORT void removeTextPlaceholder(TextPlaceholderElement&);
+ bool isPastingFromMenuOrKeyBinding() const { return m_pastingFromMenuOrKeyBinding; }
+
private:
Document& document() const { return m_document; }
@@ -654,6 +658,7 @@
bool m_editorUIUpdateTimerShouldCheckSpellingAndGrammar { false };
bool m_editorUIUpdateTimerWasTriggeredByDictation { false };
bool m_isHandlingAcceptedCandidate { false };
+ bool m_pastingFromMenuOrKeyBinding { false };
#if ENABLE(TELEPHONE_NUMBER_DETECTION) && PLATFORM(MAC)
bool shouldDetectTelephoneNumbers() const;
Modified: trunk/Source/WebCore/editing/EditorCommand.cpp (261824 => 261825)
--- trunk/Source/WebCore/editing/EditorCommand.cpp 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Source/WebCore/editing/EditorCommand.cpp 2020-05-18 19:05:27 UTC (rev 261825)
@@ -905,7 +905,7 @@
{
if (source == CommandFromMenuOrKeyBinding) {
UserTypingGestureIndicator typingGestureIndicator(frame);
- frame.editor().paste();
+ frame.editor().paste(Editor::FromMenuOrKeyBinding::Yes);
return true;
}
@@ -936,7 +936,7 @@
{
if (source == CommandFromMenuOrKeyBinding) {
UserTypingGestureIndicator typingGestureIndicator(frame);
- frame.editor().pasteAsPlainText();
+ frame.editor().pasteAsPlainText(Editor::FromMenuOrKeyBinding::Yes);
return true;
}
@@ -951,7 +951,7 @@
{
if (source == CommandFromMenuOrKeyBinding) {
UserTypingGestureIndicator typingGestureIndicator(frame);
- frame.editor().pasteAsPlainText();
+ frame.editor().pasteAsPlainText(Editor::FromMenuOrKeyBinding::Yes);
return true;
}
@@ -966,7 +966,7 @@
{
if (source == CommandFromMenuOrKeyBinding) {
UserTypingGestureIndicator typingGestureIndicator(frame);
- frame.editor().pasteAsQuotation();
+ frame.editor().pasteAsQuotation(Editor::FromMenuOrKeyBinding::Yes);
return true;
}
Modified: trunk/Source/WebCore/page/Frame.cpp (261824 => 261825)
--- trunk/Source/WebCore/page/Frame.cpp 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Source/WebCore/page/Frame.cpp 2020-05-18 19:05:27 UTC (rev 261825)
@@ -539,9 +539,15 @@
if (m_settings->_javascript_CanAccessClipboard() && m_settings->DOMPasteAllowed())
return true;
- if (!m_settings->domPasteAccessRequestsEnabled() || !m_doc)
+ if (!m_doc)
return false;
+ if (editor().isPastingFromMenuOrKeyBinding())
+ return true;
+
+ if (!m_settings->domPasteAccessRequestsEnabled())
+ return false;
+
auto gestureToken = UserGestureIndicator::currentUserGesture();
if (!gestureToken || !gestureToken->processingUserGesture())
return false;
Modified: trunk/Tools/ChangeLog (261824 => 261825)
--- trunk/Tools/ChangeLog 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Tools/ChangeLog 2020-05-18 19:05:27 UTC (rev 261825)
@@ -1,3 +1,23 @@
+2020-05-18 Wenson Hsieh <wenson_hs...@apple.com>
+
+ Allow clipboard API access when pasting from a menu item or key binding
+ https://bugs.webkit.org/show_bug.cgi?id=211990
+ <rdar://problem/63308916>
+
+ Reviewed by Megan Gardner.
+
+ Add a UIScriptController method to trigger a paste from the application process.
+
+ * DumpRenderTree/cocoa/UIScriptControllerCocoa.h:
+ * DumpRenderTree/cocoa/UIScriptControllerCocoa.mm:
+ (WTR::UIScriptControllerCocoa::paste):
+ * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+ * TestRunnerShared/UIScriptContext/UIScriptController.h:
+ (WTR::UIScriptController::paste):
+ * WebKitTestRunner/cocoa/UIScriptControllerCocoa.h:
+ * WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm:
+ (WTR::UIScriptControllerCocoa::paste):
+
2020-05-18 Darin Adler <da...@apple.com>
Add iterator checking to ListHashSet
Modified: trunk/Tools/DumpRenderTree/cocoa/UIScriptControllerCocoa.h (261824 => 261825)
--- trunk/Tools/DumpRenderTree/cocoa/UIScriptControllerCocoa.h 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Tools/DumpRenderTree/cocoa/UIScriptControllerCocoa.h 2020-05-18 19:05:27 UTC (rev 261825)
@@ -34,6 +34,7 @@
class UIScriptControllerCocoa : public UIScriptController {
public:
void setContinuousSpellCheckingEnabled(bool) override;
+ void paste() override;
protected:
explicit UIScriptControllerCocoa(UIScriptContext&);
Modified: trunk/Tools/DumpRenderTree/cocoa/UIScriptControllerCocoa.mm (261824 => 261825)
--- trunk/Tools/DumpRenderTree/cocoa/UIScriptControllerCocoa.mm 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Tools/DumpRenderTree/cocoa/UIScriptControllerCocoa.mm 2020-05-18 19:05:27 UTC (rev 261825)
@@ -44,6 +44,11 @@
mainFrame.webView.continuousSpellCheckingEnabled = enabled;
}
+void UIScriptControllerCocoa::paste()
+{
+ [mainFrame.webView paste:nil];
+}
+
} // namespace WTR
#endif // PLATFORM(COCOA)
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (261824 => 261825)
--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2020-05-18 19:05:27 UTC (rev 261825)
@@ -270,6 +270,7 @@
readonly attribute boolean isPresentingModally;
void copyText(DOMString text);
+ void paste();
readonly attribute double contentOffsetX;
readonly attribute double contentOffsetY;
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (261824 => 261825)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2020-05-18 19:05:27 UTC (rev 261825)
@@ -106,6 +106,7 @@
virtual void resignFirstResponder() { notImplemented(); }
virtual void copyText(JSStringRef) { notImplemented(); }
+ virtual void paste() { notImplemented(); }
virtual void chooseMenuAction(JSStringRef, JSValueRef);
virtual void dismissMenu();
Modified: trunk/Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.h (261824 => 261825)
--- trunk/Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.h 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.h 2020-05-18 19:05:27 UTC (rev 261825)
@@ -54,6 +54,8 @@
void dismissMenu() override;
bool isShowingMenu() const override;
+ void paste() override;
+
void setContinuousSpellCheckingEnabled(bool) override;
protected:
Modified: trunk/Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm (261824 => 261825)
--- trunk/Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm 2020-05-18 18:56:41 UTC (rev 261824)
+++ trunk/Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm 2020-05-18 19:05:27 UTC (rev 261825)
@@ -35,6 +35,10 @@
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebViewPrivateForTesting.h>
+@interface WKWebView (WKWebViewInternal)
+- (void)paste:(id)sender;
+@end
+
namespace WTR {
UIScriptControllerCocoa::UIScriptControllerCocoa(UIScriptContext& context)
@@ -204,4 +208,9 @@
[webView() _setContinuousSpellCheckingEnabledForTesting:enabled];
}
+void UIScriptControllerCocoa::paste()
+{
+ [webView() paste:nil];
+}
+
} // namespace WTR