Diff
Modified: trunk/LayoutTests/ChangeLog (251278 => 251279)
--- trunk/LayoutTests/ChangeLog 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/LayoutTests/ChangeLog 2019-10-18 14:24:07 UTC (rev 251279)
@@ -1,3 +1,39 @@
+2019-10-17 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Clipboard API] Support navigator.clipboard.read()
+ https://bugs.webkit.org/show_bug.cgi?id=203021
+
+ Reviewed by Ryosuke Niwa.
+
+ * editing/async-clipboard/clipboard-change-data-while-reading-expected.txt: Added.
+ * editing/async-clipboard/clipboard-change-data-while-reading.html: Added.
+
+ Add a new layout test to verify that if the platform pasteboard changes in the middle of a DOM paste access
+ request, the promise returned by Clipboard.read() should reject, and the page should not receive any clipboard
+ items.
+
+ * editing/async-clipboard/clipboard-read-basic-expected.txt: Added.
+ * editing/async-clipboard/clipboard-read-basic.html: Added.
+
+ Add a new layout test to exercise Clipboard.read(). Since we don't support reading data from clipboard items
+ yet, this only checks the types of each pasteboard item. This test additionally ensures that the ClipboardItems
+ returned from the API are the same between calls to Clipboard.read() if the data hasn't changed.
+
+ * editing/async-clipboard/resources/async-clipboard-helpers.js:
+ (writeToClipboardUsingDataTransfer):
+
+ Add a new helper to synchronously write data to the clipboard using execCommand and DataTransfer API.
+
+ (async.triggerProgrammaticPaste):
+
+ Add a new helper to trigger programmatic paste by activating the given element or location. Also receives an
+ array of options (which, for now, just supports a single option to change the pasteboard when granting DOM paste
+ access).
+
+ * platform/ios-wk1/TestExpectations: Skip clipboard-change-data-while-reading.html for now in WebKit1.
+ * platform/mac-wk1/TestExpectations: Skip clipboard-change-data-while-reading.html for now in WebKit1.
+ * platform/win/TestExpectations: Skip the new layout tests on Windows for now.
+
2019-10-17 Chris Dumez <cdu...@apple.com>
Don't put pages that have not reached the non-visually empty layout milestone in the back/forward cache
Added: trunk/LayoutTests/editing/async-clipboard/clipboard-change-data-while-reading-expected.txt (0 => 251279)
--- trunk/LayoutTests/editing/async-clipboard/clipboard-change-data-while-reading-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/async-clipboard/clipboard-change-data-while-reading-expected.txt 2019-10-18 14:24:07 UTC (rev 251279)
@@ -0,0 +1,10 @@
+This test verifies that if platform pasteboard contents are changed immediately after granting programmatic clipboard access during Clipboard.read(), the promise should be rejected. This test needs to be run in WebKitTestRunner or DumpRenderTree.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS Failed to read clipboard items with NotAllowedError.
+PASS finishedReading became true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/editing/async-clipboard/clipboard-change-data-while-reading.html (0 => 251279)
--- trunk/LayoutTests/editing/async-clipboard/clipboard-change-data-while-reading.html (rev 0)
+++ trunk/LayoutTests/editing/async-clipboard/clipboard-change-data-while-reading.html 2019-10-18 14:24:07 UTC (rev 251279)
@@ -0,0 +1,64 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ domPasteAllowed=false useFlexibleViewport=true experimental:AsyncClipboardAPIEnabled=true ] -->
+<html>
+ <meta charset="utf8">
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <script src=""
+ <script src=""
+ <script src=""
+ <style>
+ button {
+ width: 100%;
+ height: 100px;
+ }
+
+ iframe {
+ width: 100%;
+ height: 100px;
+ }
+ </style>
+ </head>
+ <script>
+ jsTestIsAsync = true;
+ finishedReading = false;
+
+ async function runTest() {
+ description("This test verifies that if platform pasteboard contents are changed immediately after granting programmatic clipboard access during Clipboard.read(), the promise should be rejected. This test needs to be run in WebKitTestRunner or DumpRenderTree.");
+
+ const copyElement = document.getElementById("copy");
+ const pasteElement = document.getElementById("paste");
+ pasteElement.addEventListener("click", async event => {
+ try {
+ testFailed(`Did not expect to read ${(await navigator.clipboard.read()).length} item(s).`);
+ } catch (exception) {
+ testPassed(`Failed to read clipboard items with ${exception.name}.`);
+ } finally {
+ finishedReading = true;
+ }
+ });
+
+ await UIHelper.activateElement(copyElement);
+ await triggerProgrammaticPaste(pasteElement, ["ChangePasteboardWhenGrantingAccess"]);
+ await new Promise(resolve => shouldBecomeEqual("finishedReading", "true", resolve));
+
+ [pasteElement, copyElement].map(element => element.remove());
+ finishJSTest();
+ }
+
+ addEventListener("load", runTest);
+ </script>
+ <body>
+ <iframe id="copy" src="" id='copy' style='text-align: center; font-size: 24px; width: 100%; height: 100%; line-height: 80px;'>Click here to copy</button>
+ <p id='text' style='text-align: center; font-size: 24px; width: 100%; height: 100%; line-height: 80px;'>This is some text to copy.</p>
+ <script>
+ copy.addEventListener('click', () => {
+ getSelection().selectAllChildren(text);
+ document.execCommand('Copy');
+ getSelection().removeAllRanges();
+ });
+ </script>"></iframe>
+ <div><button id="paste">Paste</button></div>
+ <div id="description"></div>
+ <div id="console"></div>
+ </body>
+</html>
Added: trunk/LayoutTests/editing/async-clipboard/clipboard-read-basic-expected.txt (0 => 251279)
--- trunk/LayoutTests/editing/async-clipboard/clipboard-read-basic-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/async-clipboard/clipboard-read-basic-expected.txt 2019-10-18 14:24:07 UTC (rev 251279)
@@ -0,0 +1,21 @@
+This test verifies that clipboard items can be read with their expected types, and that the wrapper for clipboard items is the same between calls to Clipboard.read. This test requires WebKitTestRunner or DumpRenderTree.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS sortedTypes.length is 3
+PASS sortedTypes[0] is "text/html"
+PASS sortedTypes[1] is "text/plain"
+PASS sortedTypes[2] is "text/uri-list"
+PASS item.foo is undefined
+PASS readCount became 1
+PASS sortedTypes.length is 3
+PASS sortedTypes[0] is "text/html"
+PASS sortedTypes[1] is "text/plain"
+PASS sortedTypes[2] is "text/uri-list"
+PASS item.foo is "bar"
+PASS readCount became 2
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/editing/async-clipboard/clipboard-read-basic.html (0 => 251279)
--- trunk/LayoutTests/editing/async-clipboard/clipboard-read-basic.html (rev 0)
+++ trunk/LayoutTests/editing/async-clipboard/clipboard-read-basic.html 2019-10-18 14:24:07 UTC (rev 251279)
@@ -0,0 +1,74 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true experimental:AsyncClipboardAPIEnabled=true ] -->
+<html>
+ <meta charset="utf8">
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+ <script src=""
+ <script src=""
+ <script src=""
+ <style>
+ button {
+ width: 100px;
+ padding: 1em;
+ }
+ </style>
+ </head>
+ <script>
+ jsTestIsAsync = true;
+
+ description("This test verifies that clipboard items can be read with their expected types, and that the wrapper for clipboard items is the same between calls to Clipboard.read. This test requires WebKitTestRunner or DumpRenderTree.");
+
+ async function runTest() {
+ const copyButton = document.getElementById("copy");
+ const pasteButton = document.getElementById("paste");
+ copyButton.addEventListener("click", event => {
+ writeToClipboardUsingDataTransfer({
+ "text/html": "<a href=''>apple.com</a>",
+ "text/plain": "apple.com",
+ "text/uri-list": "https://apple.com/",
+ });
+ event.preventDefault();
+ });
+
+ pasteButton.addEventListener("click", async event => {
+ for (const item of await navigator.clipboard.read()) {
+ window.item = item;
+ window.sortedTypes = item.types.slice(0);
+ sortedTypes.sort();
+ shouldBe("sortedTypes.length", "3");
+ shouldBeEqualToString("sortedTypes[0]", "text/html");
+ shouldBeEqualToString("sortedTypes[1]", "text/plain");
+ shouldBeEqualToString("sortedTypes[2]", "text/uri-list");
+ if (isFirstTimeReading)
+ shouldBe("item.foo", "undefined");
+ else
+ shouldBeEqualToString("item.foo", "bar");
+ item.foo = "bar";
+ window.item = window.sortedTypes = null;
+ }
+ ++readCount;
+ });
+
+ readCount = 0;
+ isFirstTimeReading = true;
+ await UIHelper.activateElement(copyButton);
+ await UIHelper.activateElement(pasteButton);
+ await new Promise(resolve => shouldBecomeEqual("readCount", "1", resolve));
+
+ GCController.collect();
+
+ isFirstTimeReading = false;
+ await UIHelper.activateElement(pasteButton);
+ await new Promise(resolve => shouldBecomeEqual("readCount", "2", resolve));
+
+ [pasteButton, copyButton].map(button => button.remove());
+ finishJSTest();
+ }
+
+ addEventListener("load", runTest);
+ </script>
+ <body>
+ <button id="copy">Copy</button>
+ <button id="paste">Paste</button>
+ </body>
+</html>
Modified: trunk/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js (251278 => 251279)
--- trunk/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js 2019-10-18 14:24:07 UTC (rev 251279)
@@ -29,3 +29,52 @@
image.src = ""
});
}
+
+function writeToClipboardUsingDataTransfer(data) {
+ const input = document.createElement("input");
+ document.body.appendChild(input);
+ input.value = "a";
+ input.setSelectionRange(0, 1);
+ input.addEventListener("copy", event => {
+ for (const type of Object.keys(data))
+ event.clipboardData.setData(type, data[type]);
+ event.preventDefault();
+ }, { once: true });
+ document.execCommand("copy");
+ input.remove();
+}
+
+
+async function triggerProgrammaticPaste(locationOrElement, options = []) {
+ let x, y;
+ if (locationOrElement instanceof Element)
+ [x, y] = [locationOrElement.offsetLeft + locationOrElement.offsetWidth / 2, locationOrElement.offsetTop + locationOrElement.offsetHeight / 2];
+ else
+ [x, y] = [locationOrElement.x, locationOrElement.y];
+
+ return new Promise(resolve => {
+ testRunner.runUIScript(`
+ (() => {
+ doneCount = 0;
+ function checkDone() {
+ if (++doneCount === 3)
+ uiController.uiScriptComplete();
+ }
+
+ uiController.didHideMenuCallback = checkDone;
+
+ function resolveDOMPasteRequest() {
+ if (${options.includes("ChangePasteboardWhenGrantingAccess")})
+ uiController.copyText("*** this text should never appear in a passing layout test ***");
+ uiController.chooseMenuAction("Paste", checkDone);
+ }
+
+ if (uiController.isShowingMenu)
+ resolveDOMPasteRequest();
+ else
+ uiController.didShowMenuCallback = resolveDOMPasteRequest;
+
+ uiController.activateAtPoint(${x}, ${y}, checkDone);
+ })()`, resolve);
+ });
+}
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (251278 => 251279)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2019-10-18 14:24:07 UTC (rev 251279)
@@ -1,3 +1,14 @@
+2019-10-17 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Clipboard API] Support navigator.clipboard.read()
+ https://bugs.webkit.org/show_bug.cgi?id=203021
+
+ Reviewed by Ryosuke Niwa.
+
+ Rebaseline a web platform test, now that Clipboard.read() no longer immediately rejects.
+
+ * web-platform-tests/clipboard-apis/async-navigator-clipboard-basics.https-expected.txt:
+
2019-10-17 Rob Buis <rb...@igalia.com>
Remove duplicate MathML tests
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/clipboard-apis/async-navigator-clipboard-basics.https-expected.txt (251278 => 251279)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/clipboard-apis/async-navigator-clipboard-basics.https-expected.txt 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/clipboard-apis/async-navigator-clipboard-basics.https-expected.txt 2019-10-18 14:24:07 UTC (rev 251279)
@@ -6,6 +6,6 @@
PASS navigator.clipboard.write(DOMString) fails (expect DataTransfer)
FAIL navigator.clipboard.writeText(DOMString) succeeds promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS navigator.clipboard.writeText() fails (expect DOMString)
-FAIL navigator.clipboard.read() succeeds promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL navigator.clipboard.read() succeeds assert_true: expected true got false
FAIL navigator.clipboard.readText() succeeds promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
Modified: trunk/LayoutTests/platform/ios-wk1/TestExpectations (251278 => 251279)
--- trunk/LayoutTests/platform/ios-wk1/TestExpectations 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/LayoutTests/platform/ios-wk1/TestExpectations 2019-10-18 14:24:07 UTC (rev 251279)
@@ -31,6 +31,9 @@
fast/forms/datalist [ WontFix ]
imported/w3c/web-platform-tests/html/semantics/forms/the-datalist-element [ WontFix ]
+# DOM paste access requests are not implemented in WebKit1.
+editing/async-clipboard/clipboard-change-data-while-reading.html [ Skip ]
+
# testRunner.queueLoad() does not support loading data URLs in iOS WK1
http/tests/security/contentSecurityPolicy/navigate-self-to-data-url.html [ Skip ]
Modified: trunk/LayoutTests/platform/mac-wk1/TestExpectations (251278 => 251279)
--- trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/LayoutTests/platform/mac-wk1/TestExpectations 2019-10-18 14:24:07 UTC (rev 251279)
@@ -65,6 +65,9 @@
fast/forms/datalist [ WontFix ]
imported/w3c/web-platform-tests/html/semantics/forms/the-datalist-element [ WontFix ]
+# DOM paste access requests are not implemented in WebKit1.
+editing/async-clipboard/clipboard-change-data-while-reading.html [ Skip ]
+
imported/w3c/web-platform-tests/websockets/Close-1000-reason.any.html [ Pass Failure ]
imported/w3c/web-platform-tests/websockets/Close-1000-reason.any.worker.html [ Pass Failure ]
imported/w3c/web-platform-tests/websockets/binary/001.html [ Pass Failure ]
Modified: trunk/LayoutTests/platform/win/TestExpectations (251278 => 251279)
--- trunk/LayoutTests/platform/win/TestExpectations 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/LayoutTests/platform/win/TestExpectations 2019-10-18 14:24:07 UTC (rev 251279)
@@ -1189,6 +1189,9 @@
http/tests/security/clipboard/copy-paste-html-cross-origin-iframe-in-same-origin.html [ Skip ]
http/tests/security/clipboard/copy-paste-html-across-origin-strips-mso-list.html [ Skip ]
+webkit.org/b/203100 editing/async-clipboard/clipboard-read-basic.html [ Skip ]
+webkit.org/b/203100 editing/async-clipboard/clipboard-change-data-while-reading.html [ Skip ]
+
webkit.org/b/140783 [ Release ] editing/pasteboard/copy-standalone-image.html [ Failure ImageOnlyFailure ]
webkit.org/b/140783 [ Debug ] editing/pasteboard/copy-standalone-image.html [ Skip ] # Debug Assertion
webkit.org/b/140786 editing/pasteboard/copy-backslash-with-euc.html [ Skip ] # Causes later tests to fail
Modified: trunk/Source/WebCore/ChangeLog (251278 => 251279)
--- trunk/Source/WebCore/ChangeLog 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/ChangeLog 2019-10-18 14:24:07 UTC (rev 251279)
@@ -1,3 +1,69 @@
+2019-10-17 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Clipboard API] Support navigator.clipboard.read()
+ https://bugs.webkit.org/show_bug.cgi?id=203021
+
+ Reviewed by Ryosuke Niwa.
+
+ Add support for navigator.clipboard.read(), which returns a promise that resolves to a list of ClipboardItems.
+ See below for more details.
+
+ Tests: editing/async-clipboard/clipboard-change-data-while-reading.html
+ editing/async-clipboard/clipboard-read-basic.html
+
+ * Modules/async-clipboard/Clipboard.cpp:
+ (WebCore::Clipboard::read):
+
+ Implement read(). This makes two calls to the platform pasteboard: the first to get the current change count,
+ and if the change count is different from the changeCount used for the last read() call (or there are no
+ existing clipboard items being tracked), then we request pasteboard item information for all items on the
+ pasteboard, and use this information to create new clipboard items. Otherwise, if the changeCount is still valid
+ for the current list of clipboard items, simply return these clipboard items.
+
+ If the changeCount ends up being different in between the initial changeCount request and when the pasteboard
+ item information is received, we immediately bail with a NotAllowedError. The new layout test
+ clipboard-change-data-while-reading.html exercises this scenario.
+
+ (WebCore::Clipboard::getType):
+ (WebCore::Clipboard::frame const):
+ * Modules/async-clipboard/Clipboard.h:
+ * Modules/async-clipboard/ClipboardItem.cpp:
+ (WebCore::ClipboardItem::blobFromString):
+ (WebCore::ClipboardItem::ClipboardItem):
+ (WebCore::ClipboardItem::create):
+ (WebCore::ClipboardItem::navigator):
+
+ Refactor this so that each clipboard item itself has a WeakPtr to its Navigator. This avoids having to follow
+ the weak pointer to the Clipboard to get to the Clipboard's navigator during garbage collection when computing
+ reachability from opaque roots, since this may happen on a background (GC) thread.
+
+ (WebCore::ClipboardItem::clipboard):
+ * Modules/async-clipboard/ClipboardItem.h:
+ * Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp:
+ (WebCore::ClipboardItemBindingsDataSource::getType):
+ (WebCore::blobFromString): Deleted.
+
+ Move this to ClipboardItem, and make it a static method.
+
+ * Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp:
+ (WebCore::ClipboardItemPasteboardDataSource::ClipboardItemPasteboardDataSource):
+ (WebCore::ClipboardItemPasteboardDataSource::getType):
+ * Modules/async-clipboard/ClipboardItemPasteboardDataSource.h:
+
+ Move a couple of member variables (index and changeCount) out of ClipboardItem. Instead of having each
+ ClipboardItem keep track of this information, have the Clipboard that owns the ClipboardItem keep this
+ information. This means that reading data from ClipboardItem will (in a future patch) work by having the item
+ ask its Clipboard object to read data on its behalf.
+
+ * platform/Pasteboard.cpp:
+ (WebCore::Pasteboard::allPasteboardItemInfo const):
+ (WebCore::Pasteboard::pasteboardItemInfo const):
+ (WebCore::Pasteboard::readString):
+ (WebCore::Pasteboard::readBuffer):
+ (WebCore::Pasteboard::readURL):
+
+ Add some null checks to handle the case where there is no pasteboard strategy.
+
2019-10-17 Chris Dumez <cdu...@apple.com>
Don't put pages that have not reached the non-visually empty layout milestone in the back/forward cache
Modified: trunk/Source/WebCore/Modules/async-clipboard/Clipboard.cpp (251278 => 251279)
--- trunk/Source/WebCore/Modules/async-clipboard/Clipboard.cpp 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/Modules/async-clipboard/Clipboard.cpp 2019-10-18 14:24:07 UTC (rev 251279)
@@ -26,10 +26,14 @@
#include "config.h"
#include "Clipboard.h"
+#include "Blob.h"
#include "ClipboardItem.h"
+#include "Frame.h"
+#include "JSClipboardItem.h"
#include "JSDOMPromise.h"
#include "JSDOMPromiseDeferred.h"
#include "Navigator.h"
+#include "Pasteboard.h"
#include <wtf/IsoMallocInlines.h>
namespace WebCore {
@@ -46,6 +50,8 @@
{
}
+Clipboard::~Clipboard() = default;
+
Navigator* Clipboard::navigator()
{
return m_navigator.get();
@@ -74,6 +80,54 @@
void Clipboard::read(Ref<DeferredPromise>&& promise)
{
+ auto rejectPromiseAndClearActiveSession = [&] {
+ m_activeSession = WTF::nullopt;
+ promise->reject(NotAllowedError);
+ };
+
+ auto frame = makeRefPtr(this->frame());
+ if (!frame) {
+ rejectPromiseAndClearActiveSession();
+ return;
+ }
+
+ auto pasteboard = Pasteboard::createForCopyAndPaste();
+ int changeCountAtStart = pasteboard->changeCount();
+
+ if (!frame->requestDOMPasteAccess()) {
+ rejectPromiseAndClearActiveSession();
+ return;
+ }
+
+ if (!m_activeSession || m_activeSession->changeCount != changeCountAtStart) {
+ auto allInfo = pasteboard->allPasteboardItemInfo();
+ if (allInfo.isEmpty()) {
+ rejectPromiseAndClearActiveSession();
+ return;
+ }
+
+ Vector<Ref<ClipboardItem>> clipboardItems;
+ clipboardItems.reserveInitialCapacity(allInfo.size());
+ for (auto& itemInfo : allInfo) {
+ // FIXME: This should be refactored such that the initial changeCount is delivered to the client, where it is then checked
+ // against the current changeCount of the platform pasteboard. For instance, in WebKit2, this would relocate the changeCount
+ // check to the UI process instead of the web content process.
+ if (itemInfo.changeCount != changeCountAtStart) {
+ rejectPromiseAndClearActiveSession();
+ return;
+ }
+ clipboardItems.uncheckedAppend(ClipboardItem::create(*this, itemInfo));
+ }
+ m_activeSession = {{ WTFMove(pasteboard), WTFMove(clipboardItems), changeCountAtStart }};
+ }
+
+ promise->resolve<IDLSequence<IDLInterface<ClipboardItem>>>(m_activeSession->items);
+}
+
+void Clipboard::getType(ClipboardItem& item, const String& type, Ref<DeferredPromise>&& promise)
+{
+ UNUSED_PARAM(item);
+ UNUSED_PARAM(type);
promise->reject(NotSupportedError);
}
@@ -83,4 +137,9 @@
promise->reject(NotSupportedError);
}
+Frame* Clipboard::frame() const
+{
+ return m_navigator ? m_navigator->frame() : nullptr;
}
+
+}
Modified: trunk/Source/WebCore/Modules/async-clipboard/Clipboard.h (251278 => 251279)
--- trunk/Source/WebCore/Modules/async-clipboard/Clipboard.h 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/Modules/async-clipboard/Clipboard.h 2019-10-18 14:24:07 UTC (rev 251279)
@@ -34,16 +34,20 @@
class ClipboardItem;
class DeferredPromise;
+class Frame;
class Navigator;
+class Pasteboard;
class Clipboard final : public RefCounted<Clipboard>, public EventTargetWithInlineData, public CanMakeWeakPtr<Clipboard> {
WTF_MAKE_ISO_ALLOCATED(Clipboard);
public:
static Ref<Clipboard> create(Navigator&);
+ ~Clipboard();
EventTargetInterface eventTargetInterface() const final;
ScriptExecutionContext* scriptExecutionContext() const final;
+ Frame* frame() const;
Navigator* navigator();
using RefCounted::ref;
@@ -55,12 +59,21 @@
void read(Ref<DeferredPromise>&&);
void write(const Vector<RefPtr<ClipboardItem>>& data, Ref<DeferredPromise>&&);
+ void getType(ClipboardItem&, const String& type, Ref<DeferredPromise>&&);
+
private:
Clipboard(Navigator&);
+ struct Session {
+ std::unique_ptr<Pasteboard> pasteboard;
+ Vector<Ref<ClipboardItem>> items;
+ int changeCount;
+ };
+
void refEventTarget() final { ref(); }
void derefEventTarget() final { deref(); }
+ Optional<Session> m_activeSession;
WeakPtr<Navigator> m_navigator;
};
Modified: trunk/Source/WebCore/Modules/async-clipboard/ClipboardItem.cpp (251278 => 251279)
--- trunk/Source/WebCore/Modules/async-clipboard/ClipboardItem.cpp 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/Modules/async-clipboard/ClipboardItem.cpp 2019-10-18 14:24:07 UTC (rev 251279)
@@ -26,15 +26,23 @@
#include "config.h"
#include "ClipboardItem.h"
+#include "Blob.h"
#include "ClipboardItemBindingsDataSource.h"
#include "ClipboardItemPasteboardDataSource.h"
#include "Navigator.h"
#include "PasteboardItemInfo.h"
+#include "SharedBuffer.h"
namespace WebCore {
ClipboardItem::~ClipboardItem() = default;
+Ref<Blob> ClipboardItem::blobFromString(const String& stringData, const String& type)
+{
+ auto utf8 = stringData.utf8();
+ return Blob::create(SharedBuffer::create(utf8.data(), utf8.length()), Blob::normalizedContentType(type));
+}
+
static ClipboardItem::PresentationStyle clipboardItemPresentationStyle(const PasteboardItemInfo& info)
{
switch (info.preferredPresentationStyle) {
@@ -55,9 +63,10 @@
{
}
-ClipboardItem::ClipboardItem(Clipboard& clipboard, const PasteboardItemInfo& info, size_t index)
+ClipboardItem::ClipboardItem(Clipboard& clipboard, const PasteboardItemInfo& info)
: m_clipboard(makeWeakPtr(clipboard))
- , m_dataSource(makeUnique<ClipboardItemPasteboardDataSource>(*this, info, index))
+ , m_navigator(makeWeakPtr(clipboard.navigator()))
+ , m_dataSource(makeUnique<ClipboardItemPasteboardDataSource>(*this, info))
, m_presentationStyle(clipboardItemPresentationStyle(info))
{
}
@@ -67,9 +76,9 @@
return adoptRef(*new ClipboardItem(WTFMove(data), options));
}
-Ref<ClipboardItem> ClipboardItem::create(Clipboard& clipboard, const PasteboardItemInfo& info, size_t index)
+Ref<ClipboardItem> ClipboardItem::create(Clipboard& clipboard, const PasteboardItemInfo& info)
{
- return adoptRef(*new ClipboardItem(clipboard, info, index));
+ return adoptRef(*new ClipboardItem(clipboard, info));
}
Vector<String> ClipboardItem::types() const
@@ -84,7 +93,12 @@
Navigator* ClipboardItem::navigator()
{
- return m_clipboard ? m_clipboard->navigator() : nullptr;
+ return m_navigator.get();
}
+Clipboard* ClipboardItem::clipboard()
+{
+ return m_clipboard.get();
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/async-clipboard/ClipboardItem.h (251278 => 251279)
--- trunk/Source/WebCore/Modules/async-clipboard/ClipboardItem.h 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/Modules/async-clipboard/ClipboardItem.h 2019-10-18 14:24:07 UTC (rev 251279)
@@ -53,7 +53,8 @@
};
static Ref<ClipboardItem> create(Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&&, const Options&);
- static Ref<ClipboardItem> create(Clipboard&, const PasteboardItemInfo&, size_t index);
+ static Ref<ClipboardItem> create(Clipboard&, const PasteboardItemInfo&);
+ static Ref<Blob> blobFromString(const String& stringData, const String& type);
Vector<String> types() const;
void getType(const String&, Ref<DeferredPromise>&&);
@@ -60,14 +61,14 @@
PresentationStyle presentationStyle() const { return m_presentationStyle; };
Navigator* navigator();
+ Clipboard* clipboard();
-protected:
- WeakPtr<Clipboard> m_clipboard;
-
private:
ClipboardItem(Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&&, const Options&);
- ClipboardItem(Clipboard&, const PasteboardItemInfo&, size_t index);
+ ClipboardItem(Clipboard&, const PasteboardItemInfo&);
+ WeakPtr<Clipboard> m_clipboard;
+ WeakPtr<Navigator> m_navigator;
std::unique_ptr<ClipboardItemDataSource> m_dataSource;
PresentationStyle m_presentationStyle { PresentationStyle::Unspecified };
};
Modified: trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp (251278 => 251279)
--- trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp 2019-10-18 14:24:07 UTC (rev 251279)
@@ -35,12 +35,6 @@
namespace WebCore {
-static Ref<Blob> blobFromString(const String& stringData, const String& type)
-{
- auto utf8 = stringData.utf8();
- return Blob::create(SharedBuffer::create(utf8.data(), utf8.length()), Blob::normalizedContentType(type));
-}
-
ClipboardItemBindingsDataSource::ClipboardItemBindingsDataSource(ClipboardItem& item, Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&& itemPromises)
: ClipboardItemDataSource(item)
, m_itemPromises(WTFMove(itemPromises))
@@ -83,7 +77,7 @@
String string;
result.getString(itemPromise->globalObject()->globalExec(), string);
if (!string.isNull()) {
- promise->resolve<IDLInterface<Blob>>(blobFromString(string, type));
+ promise->resolve<IDLInterface<Blob>>(ClipboardItem::blobFromString(string, type));
return;
}
Modified: trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp (251278 => 251279)
--- trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp 2019-10-18 14:24:07 UTC (rev 251279)
@@ -30,11 +30,9 @@
namespace WebCore {
-ClipboardItemPasteboardDataSource::ClipboardItemPasteboardDataSource(ClipboardItem& item, const PasteboardItemInfo& info, size_t itemIndex)
+ClipboardItemPasteboardDataSource::ClipboardItemPasteboardDataSource(ClipboardItem& item, const PasteboardItemInfo& info)
: ClipboardItemDataSource(item)
, m_types(info.webSafeTypesByFidelity)
- , m_itemIndex(itemIndex)
- , m_initialChangeCount(info.changeCount)
{
}
@@ -47,11 +45,10 @@
void ClipboardItemPasteboardDataSource::getType(const String& type, Ref<DeferredPromise>&& promise)
{
- // FIXME: Not implemented.
- UNUSED_PARAM(m_initialChangeCount);
- UNUSED_PARAM(m_itemIndex);
- UNUSED_PARAM(type);
- promise->reject(NotSupportedError);
+ if (auto clipboard = makeRefPtr(m_item.clipboard()))
+ clipboard->getType(m_item, type, WTFMove(promise));
+ else
+ promise->reject(NotAllowedError);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.h (251278 => 251279)
--- trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.h 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.h 2019-10-18 14:24:07 UTC (rev 251279)
@@ -34,7 +34,7 @@
class ClipboardItemPasteboardDataSource : public ClipboardItemDataSource {
WTF_MAKE_FAST_ALLOCATED;
public:
- ClipboardItemPasteboardDataSource(ClipboardItem&, const PasteboardItemInfo&, size_t itemIndex);
+ ClipboardItemPasteboardDataSource(ClipboardItem&, const PasteboardItemInfo&);
~ClipboardItemPasteboardDataSource();
private:
@@ -42,8 +42,6 @@
void getType(const String&, Ref<DeferredPromise>&&) final;
Vector<String> m_types;
- size_t m_itemIndex { 0 };
- int m_initialChangeCount { 0 };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/Pasteboard.cpp (251278 => 251279)
--- trunk/Source/WebCore/platform/Pasteboard.cpp 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Source/WebCore/platform/Pasteboard.cpp 2019-10-18 14:24:07 UTC (rev 251279)
@@ -64,27 +64,37 @@
Vector<PasteboardItemInfo> Pasteboard::allPasteboardItemInfo() const
{
- return platformStrategies()->pasteboardStrategy()->allPasteboardItemInfo(name());
+ if (auto* strategy = platformStrategies()->pasteboardStrategy())
+ return strategy->allPasteboardItemInfo(name());
+ return { };
}
PasteboardItemInfo Pasteboard::pasteboardItemInfo(size_t index) const
{
- return platformStrategies()->pasteboardStrategy()->informationForItemAtIndex(index, name());
+ if (auto* strategy = platformStrategies()->pasteboardStrategy())
+ return strategy->informationForItemAtIndex(index, name());
+ return { };
}
String Pasteboard::readString(size_t index, const String& type)
{
- return platformStrategies()->pasteboardStrategy()->readStringFromPasteboard(index, type, name());
+ if (auto* strategy = platformStrategies()->pasteboardStrategy())
+ return strategy->readStringFromPasteboard(index, type, name());
+ return { };
}
RefPtr<WebCore::SharedBuffer> Pasteboard::readBuffer(size_t index, const String& type)
{
- return platformStrategies()->pasteboardStrategy()->readBufferFromPasteboard(index, type, name());
+ if (auto* strategy = platformStrategies()->pasteboardStrategy())
+ return strategy->readBufferFromPasteboard(index, type, name());
+ return nullptr;
}
URL Pasteboard::readURL(size_t index, String& title)
{
- return platformStrategies()->pasteboardStrategy()->readURLFromPasteboard(index, name(), title);
+ if (auto* strategy = platformStrategies()->pasteboardStrategy())
+ return strategy->readURLFromPasteboard(index, name(), title);
+ return { };
}
};
Modified: trunk/Tools/ChangeLog (251278 => 251279)
--- trunk/Tools/ChangeLog 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/ChangeLog 2019-10-18 14:24:07 UTC (rev 251279)
@@ -1,3 +1,60 @@
+2019-10-17 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [Clipboard API] Support navigator.clipboard.read()
+ https://bugs.webkit.org/show_bug.cgi?id=203021
+
+ Reviewed by Ryosuke Niwa.
+
+ Make adjustments to WebKitTestRunner and DumpRenderTree to support the new layout tests. See below for more
+ details.
+
+ * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
+ * DumpRenderTree/mac/DumpRenderTreePasteboard.mm:
+ (-[LocalPasteboard pasteboardItems]):
+
+ Fixes an existing issue with the mock NSPasteboard used for layout tests. Currently, our logic for converting
+ the contents of the platform pasteboard to NSPasteboardItem simply writes the pasteboard data as-is to
+ NSPasteboardItems. However, these pasteboard types may be legacy pasteboard types, in which case
+ NSPasteboardItem will simply handle the call to `-setData:forType:` as a no-op. AppKit has logic in this
+ scenario to canonicalize these legacy pasteboard types to their modern counterparts, but this is absent in
+ DumpRenderTreePasteboard and WebKitTestRunnerPasteboard.
+
+ Address this by teaching the mock pasteboards to convert legacy types to modern types when generating platform
+ pasteboard items.
+
+ * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+ * TestRunnerShared/UIScriptContext/UIScriptController.h:
+ (WTR::UIScriptController::copyText):
+
+ Add a new UIScriptController method to write a string to the platform pasteboard. This patch adds support for
+ this new testing hook on macOS and iOS, in WebKit2 (WebKitTestRunner).
+
+ * TestRunnerShared/mac/NSPasteboardAdditions.h: Copied from Tools/WebKitTestRunner/mac/UIScriptControllerMac.h.
+ * TestRunnerShared/mac/NSPasteboardAdditions.mm: Added.
+ (+[NSPasteboard _modernPasteboardType:]):
+
+ Add a helper to convert legacy pasteboard types (and dynamic UTIs that map to legacy pasteboard types) to
+ modern pasteboard types, suitable for writing to NSPasteboardItems on macOS.
+
+ * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
+ * WebKitTestRunner/ios/UIScriptControllerIOS.h:
+ * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+ (WTR::UIScriptControllerIOS::copyText):
+ * WebKitTestRunner/mac/UIScriptControllerMac.h:
+ * WebKitTestRunner/mac/UIScriptControllerMac.mm:
+ (WTR::UIScriptControllerMac::copyText):
+ * WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm:
+
+ Apply the same fix for WebKitTestRunner's mock NSPasteboard.
+
+ (-[LocalPasteboard _clearContentsWithoutUpdatingChangeCount]):
+ (-[LocalPasteboard clearContents]):
+
+ Make -clearContents clear out all the contents on the mock pasteboard, instead of crashing in AppKit.
+
+ (-[LocalPasteboard declareTypes:owner:]):
+ (-[LocalPasteboard pasteboardItems]):
+
2019-10-17 Mark Lam <mark....@apple.com>
Use constexpr in more places and remove some unnecessary external linkage.
Modified: trunk/Tools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj (251278 => 251279)
--- trunk/Tools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj 2019-10-18 14:24:07 UTC (rev 251279)
@@ -161,6 +161,7 @@
F44A531E21B89A5000DBB99C /* InstanceMethodSwizzler.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44A531C21B89A4500DBB99C /* InstanceMethodSwizzler.mm */; };
F4C3578D20E8444E00FA0748 /* LayoutTestSpellChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4C3578820E8442700FA0748 /* LayoutTestSpellChecker.mm */; };
F4D423611DD5048200678290 /* TextInputControllerIOS.m in Sources */ = {isa = PBXBuildFile; fileRef = F4D4235F1DD5045300678290 /* TextInputControllerIOS.m */; };
+ F4FED32023582158003C139C /* NSPasteboardAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4FED31F23582158003C139C /* NSPasteboardAdditions.mm */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -433,6 +434,8 @@
F4C3578920E8442700FA0748 /* LayoutTestSpellChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LayoutTestSpellChecker.h; sourceTree = "<group>"; };
F4D4235F1DD5045300678290 /* TextInputControllerIOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TextInputControllerIOS.m; path = ios/TextInputControllerIOS.m; sourceTree = "<group>"; };
F4D423601DD5046900678290 /* TextInputController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextInputController.h; sourceTree = "<group>"; };
+ F4FED31E23582158003C139C /* NSPasteboardAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSPasteboardAdditions.h; path = mac/NSPasteboardAdditions.h; sourceTree = "<group>"; };
+ F4FED31F23582158003C139C /* NSPasteboardAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NSPasteboardAdditions.mm; path = mac/NSPasteboardAdditions.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -706,6 +709,7 @@
isa = PBXGroup;
children = (
F4B6C31820E84382008AC225 /* cocoa */,
+ F4FED31623581EF3003C139C /* mac */,
A17A5A2B22A880D80065C5F0 /* spi */,
3148A0551E6F90F400D3B316 /* IOSLayoutTestCommunication.cpp */,
3148A0561E6F90F400D3B316 /* IOSLayoutTestCommunication.h */,
@@ -875,6 +879,15 @@
name = ios;
sourceTree = "<group>";
};
+ F4FED31623581EF3003C139C /* mac */ = {
+ isa = PBXGroup;
+ children = (
+ F4FED31E23582158003C139C /* NSPasteboardAdditions.h */,
+ F4FED31F23582158003C139C /* NSPasteboardAdditions.mm */,
+ );
+ name = mac;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -1185,6 +1198,7 @@
E1B7816511AF31B7007E1BC2 /* MockGeolocationProvider.mm in Sources */,
31117B3D15D9A56A00163BC8 /* MockWebNotificationProvider.mm in Sources */,
BCA18B720C9B08DB00114369 /* NavigationController.m in Sources */,
+ F4FED32023582158003C139C /* NSPasteboardAdditions.mm in Sources */,
BCA18B320C9B01B400114369 /* ObjCController.m in Sources */,
BCA18B7E0C9B08F100114369 /* ObjCPlugin.m in Sources */,
BCA18B800C9B08F100114369 /* ObjCPluginFunction.m in Sources */,
Modified: trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm (251278 => 251279)
--- trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/DumpRenderTree/mac/DumpRenderTreePasteboard.mm 2019-10-18 14:24:07 UTC (rev 251279)
@@ -34,6 +34,8 @@
#if PLATFORM(MAC)
#import "DumpRenderTreeMac.h"
+#import "NSPasteboardAdditions.h"
+#import <WebCore/LegacyNSPasteboardTypes.h>
#import <WebKit/WebTypesInternal.h>
#import <objc/runtime.h>
#import <wtf/Assertions.h>
@@ -243,7 +245,7 @@
for (const auto& typeAndData : _data) {
NSData *data = "" NSData *)typeAndData.value.get();
NSString *type = (__bridge NSString *)typeAndData.key.get();
- [item setData:data forType:type];
+ [item setData:data forType:[NSPasteboard _modernPasteboardType:type]];
}
return @[ item.get() ];
}
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (251278 => 251279)
--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2019-10-18 14:24:07 UTC (rev 251279)
@@ -262,6 +262,8 @@
void resignFirstResponder();
readonly attribute boolean isPresentingModally;
+ void copyText(DOMString text);
+
readonly attribute double contentOffsetX;
readonly attribute double contentOffsetY;
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (251278 => 251279)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2019-10-18 14:24:07 UTC (rev 251279)
@@ -105,6 +105,8 @@
virtual void becomeFirstResponder() { notImplemented(); }
virtual void resignFirstResponder() { notImplemented(); }
+ virtual void copyText(JSStringRef) { notImplemented(); }
+
virtual void chooseMenuAction(JSStringRef, JSValueRef);
virtual void dismissMenu();
Copied: trunk/Tools/TestRunnerShared/mac/NSPasteboardAdditions.h (from rev 251278, trunk/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.h) (0 => 251279)
--- trunk/Tools/TestRunnerShared/mac/NSPasteboardAdditions.h (rev 0)
+++ trunk/Tools/TestRunnerShared/mac/NSPasteboardAdditions.h 2019-10-18 14:24:07 UTC (rev 251279)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if PLATFORM(MAC)
+
+#import <AppKit/AppKit.h>
+
+@interface NSPasteboard (TestRunnerAdditions)
+
++ (NSPasteboardType)_modernPasteboardType:(NSString *)type;
+
+@end
+
+#endif // PLATFORM(MAC)
Added: trunk/Tools/TestRunnerShared/mac/NSPasteboardAdditions.mm (0 => 251279)
--- trunk/Tools/TestRunnerShared/mac/NSPasteboardAdditions.mm (rev 0)
+++ trunk/Tools/TestRunnerShared/mac/NSPasteboardAdditions.mm 2019-10-18 14:24:07 UTC (rev 251279)
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "NSPasteboardAdditions.h"
+
+#if PLATFORM(MAC)
+
+#import <CoreServices/CoreServices.h>
+#import <WebCore/LegacyNSPasteboardTypes.h>
+#import <wtf/RetainPtr.h>
+
+@implementation NSPasteboard (TestRunnerAdditions)
+
++ (NSPasteboardType)_modernPasteboardType:(NSString *)type
+{
+ if (UTTypeIsDynamic((__bridge CFStringRef)type)) {
+ if (auto legacyType = adoptNS((__bridge NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)type, kUTTagClassNSPboardType)))
+ type = legacyType.autorelease();
+ }
+
+ if ([type isEqualToString:WebCore::legacyStringPasteboardType()])
+ return NSPasteboardTypeString;
+
+ if ([type isEqualToString:WebCore::legacyHTMLPasteboardType()])
+ return NSPasteboardTypeHTML;
+
+ if ([type isEqualToString:WebCore::legacyTIFFPasteboardType()])
+ return NSPasteboardTypeTIFF;
+
+ if ([type isEqualToString:WebCore::legacyURLPasteboardType()])
+ return NSPasteboardTypeURL;
+
+ if ([type isEqualToString:WebCore::legacyPDFPasteboardType()])
+ return NSPasteboardTypePDF;
+
+ if ([type isEqualToString:WebCore::legacyRTFDPasteboardType()])
+ return NSPasteboardTypeRTFD;
+
+ if ([type isEqualToString:WebCore::legacyRTFPasteboardType()])
+ return NSPasteboardTypeRTF;
+
+ if ([type isEqualToString:WebCore::legacyColorPasteboardType()])
+ return NSPasteboardTypeColor;
+
+ if ([type isEqualToString:WebCore::legacyFontPasteboardType()])
+ return NSPasteboardTypeFont;
+
+ return type;
+}
+
+@end
+
+#endif // PLATFORM(MAC)
Modified: trunk/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj (251278 => 251279)
--- trunk/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj 2019-10-18 14:24:07 UTC (rev 251279)
@@ -155,6 +155,7 @@
F44A531821B899E500DBB99C /* InstanceMethodSwizzler.mm in Sources */ = {isa = PBXBuildFile; fileRef = F44A531621B899DA00DBB99C /* InstanceMethodSwizzler.mm */; };
F46240B1217013E500917B16 /* UIScriptControllerCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = F46240AF2170128300917B16 /* UIScriptControllerCocoa.mm */; };
F4C3578C20E8444600FA0748 /* LayoutTestSpellChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4C3578A20E8444000FA0748 /* LayoutTestSpellChecker.mm */; };
+ F4FED324235823A3003C139C /* NSPasteboardAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = F4FED3222358215E003C139C /* NSPasteboardAdditions.mm */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -412,6 +413,8 @@
F46240AF2170128300917B16 /* UIScriptControllerCocoa.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = UIScriptControllerCocoa.mm; sourceTree = "<group>"; };
F4C3578A20E8444000FA0748 /* LayoutTestSpellChecker.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = LayoutTestSpellChecker.mm; path = ../TestRunnerShared/cocoa/LayoutTestSpellChecker.mm; sourceTree = "<group>"; };
F4C3578B20E8444000FA0748 /* LayoutTestSpellChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LayoutTestSpellChecker.h; path = ../TestRunnerShared/cocoa/LayoutTestSpellChecker.h; sourceTree = "<group>"; };
+ F4FED3212358215E003C139C /* NSPasteboardAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSPasteboardAdditions.h; path = ../TestRunnerShared/mac/NSPasteboardAdditions.h; sourceTree = "<group>"; };
+ F4FED3222358215E003C139C /* NSPasteboardAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NSPasteboardAdditions.mm; path = ../TestRunnerShared/mac/NSPasteboardAdditions.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -522,6 +525,7 @@
children = (
0F18E71B1D6BC4E60027E547 /* Bindings */,
F4B6C31620E84369008AC225 /* cocoa */,
+ F4FED31D23582120003C139C /* mac */,
0F73B5471BA782FE004B3EF4 /* UIScriptContext */,
3148A0531E6F85B600D3B316 /* IOSLayoutTestCommunication.cpp */,
3148A0541E6F85B600D3B316 /* IOSLayoutTestCommunication.h */,
@@ -890,6 +894,15 @@
name = cocoa;
sourceTree = "<group>";
};
+ F4FED31D23582120003C139C /* mac */ = {
+ isa = PBXGroup;
+ children = (
+ F4FED3212358215E003C139C /* NSPasteboardAdditions.h */,
+ F4FED3222358215E003C139C /* NSPasteboardAdditions.mm */,
+ );
+ name = mac;
+ sourceTree = "<group>";
+ };
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
@@ -1140,6 +1153,7 @@
files = (
5670B8281386FCA5002EB355 /* EventSenderProxy.mm in Sources */,
BC793400118F7C84005EA8E2 /* main.mm in Sources */,
+ F4FED324235823A3003C139C /* NSPasteboardAdditions.mm in Sources */,
BC7934E811906846005EA8E2 /* PlatformWebViewMac.mm in Sources */,
E1C642C317CBCC7300D66A3C /* PoseAsClass.mm in Sources */,
BC8C795C11D2785D004535A1 /* TestControllerMac.mm in Sources */,
Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h (251278 => 251279)
--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.h 2019-10-18 14:24:07 UTC (rev 251279)
@@ -134,6 +134,7 @@
JSObjectRef calendarType() const override;
void setHardwareKeyboardAttached(bool) override;
void setAllowsViewportShrinkToFit(bool) override;
+ void copyText(JSStringRef) override;
void setDidStartFormControlInteractionCallback(JSValueRef) override;
void setDidEndFormControlInteractionCallback(JSValueRef) override;
Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm (251278 => 251279)
--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2019-10-18 14:24:07 UTC (rev 251279)
@@ -1208,6 +1208,11 @@
});
}
+void UIScriptControllerIOS::copyText(JSStringRef text)
+{
+ UIPasteboard.generalPasteboard.string = text->string();
}
+}
+
#endif // PLATFORM(IOS_FAMILY)
Modified: trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.h (251278 => 251279)
--- trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.h 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.h 2019-10-18 14:24:07 UTC (rev 251279)
@@ -52,6 +52,7 @@
void toggleCapsLock(JSValueRef) override;
NSView *platformContentView() const override;
void clearAllCallbacks() override;
+ void copyText(JSStringRef) override;
void chooseMenuAction(JSStringRef, JSValueRef) override;
Modified: trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm (251278 => 251279)
--- trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm 2019-10-18 14:24:07 UTC (rev 251279)
@@ -225,4 +225,11 @@
});
}
+void UIScriptControllerMac::copyText(JSStringRef text)
+{
+ NSPasteboard *pasteboard = NSPasteboard.generalPasteboard;
+ [pasteboard declareTypes:[NSArray arrayWithObject:NSPasteboardTypeString] owner:nil];
+ [pasteboard setString:text->string() forType:NSPasteboardTypeString];
+}
+
} // namespace WTR
Modified: trunk/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm (251278 => 251279)
--- trunk/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm 2019-10-18 10:40:34 UTC (rev 251278)
+++ trunk/Tools/WebKitTestRunner/mac/WebKitTestRunnerPasteboard.mm 2019-10-18 14:24:07 UTC (rev 251279)
@@ -25,11 +25,12 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#include "WebKitTestRunnerPasteboard.h"
+#import "config.h"
+#import "WebKitTestRunnerPasteboard.h"
-#include <objc/runtime.h>
-#include <wtf/RetainPtr.h>
+#import "NSPasteboardAdditions.h"
+#import <objc/runtime.h>
+#import <wtf/RetainPtr.h>
@interface LocalPasteboard : NSPasteboard
{
@@ -123,11 +124,22 @@
{
}
-- (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner
+- (void)_clearContentsWithoutUpdatingChangeCount
{
[typesArray removeAllObjects];
[typesSet removeAllObjects];
[dataByType removeAllObjects];
+}
+
+- (NSInteger)clearContents
+{
+ [self _clearContentsWithoutUpdatingChangeCount];
+ return ++changeCount;
+}
+
+- (NSInteger)declareTypes:(NSArray *)newTypes owner:(id)newOwner
+{
+ [self _clearContentsWithoutUpdatingChangeCount];
return [self addTypes:newTypes owner:newOwner];
}
@@ -202,7 +214,7 @@
{
auto item = adoptNS([[NSPasteboardItem alloc] init]);
for (NSString *type in dataByType)
- [item setData:dataByType[type] forType:type];
+ [item setData:dataByType[type] forType:[NSPasteboard _modernPasteboardType:type]];
return @[ item.get() ];
}