[Clipboard API] Implement getType() for ClipboardItems created from bindings
https://bugs.webkit.org/show_bug.cgi?id=202943

Reviewed by Tim Horton.

Source/WebCore:

Adds basic support for ClipboardItem.getType(), in the case where the ClipboardItems are created by the page. To
achieve this, we introduce ClipboardItemDataSource, which represents the data source backing a given clipboard
item. This backing may either consist of a list of types and their corresponding DOMPromises (for ClipboardItems
that come from the page), or may consist of a list of items that will ask the platformr pasteboard for their
data (to be supported in a future patch).

See below for more details.

Test: editing/async-clipboard/clipboard-item-basic.html

* Modules/async-clipboard/Clipboard.h:
* Modules/async-clipboard/ClipboardItem.cpp:
(WebCore::clipboardItemPresentationStyle):
(WebCore::ClipboardItem::ClipboardItem):

Pass in the parent Clipboard object for ClipboardItems that are backed by the platform pasteboard (which are
returned by Clipboard.read()). (Note that this doesn't make any difference until this codepath is actually
exercised when we add support for Clipboard.read()).

(WebCore::ClipboardItem::create):
(WebCore::ClipboardItem::types const):
(WebCore::ClipboardItem::getType):

Plumb types() and getType() to the clipboard item's datasource.

(WebCore::ClipboardItem::navigator):

Make navigator() return the parent Clipboard object's navigator.

* Modules/async-clipboard/ClipboardItem.h:
* Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp: Added.
(WebCore::blobFromString):
(WebCore::ClipboardItemBindingsDataSource::ClipboardItemBindingsDataSource):

Store the given list of types and DOM promises.

(WebCore::ClipboardItemBindingsDataSource::types const):
(WebCore::ClipboardItemBindingsDataSource::getType):

Implement getType() by finding the matching promised type in the item's array of types, and waiting for the
promise to either resolve or reject. If the promise resolves to either a string or blob, we deliver the result
back to the page by resolving the promise returned by getType(). Otherwise, we reject it.

* Modules/async-clipboard/ClipboardItemBindingsDataSource.h:
* Modules/async-clipboard/ClipboardItemDataSource.h:
(WebCore::ClipboardItemDataSource::ClipboardItemDataSource):
* Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp:

Add a stub implementation of a clipboard item data source that is backed by data in the platform pasteboard. In
a future patch, this will implement getType() by calling out to the platform pasteboard.

(WebCore::ClipboardItemPasteboardDataSource::ClipboardItemPasteboardDataSource):
(WebCore::ClipboardItemPasteboardDataSource::types const):
(WebCore::ClipboardItemPasteboardDataSource::getType):
* Modules/async-clipboard/ClipboardItemPasteboardDataSource.h:
* Modules/mediastream/RTCRtpReceiver.cpp:
* Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp:

Unrelated build fixes, due to changes in unified source groupings.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/network/mac/UTIUtilities.mm:

More build fixes, due to changes in unified source groupings.

LayoutTests:

Add a new layout test to verify that we can create and ask ClipboardItems for data. Exercises the following
corner cases:
- Promise rejection when returning item data.
- Resolving promises to incorrect data types.
- Setting types to custom strings (including emojis and non-ASCII characters).
- Returning values with emojis and non-ASCII characters.
- Resolving promises using both Blobs and DOMStrings.
- Delayed promise rejection/resolution (using setTimeout).

* editing/async-clipboard/clipboard-item-basic-expected.txt: Added.
* editing/async-clipboard/clipboard-item-basic.html: Added.
* editing/async-clipboard/resources/async-clipboard-helpers.js: Added.

Add a resource file with some helper functions for creating blobs, and loading images and text from blobs.

* platform/win/TestExpectations:

Temporarily mark a test as failing; I'll fix this and some other failing tests in a followup. See
<https://webkit.org/b/202940>.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@251134 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 0737706..40721cf 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,30 @@
+2019-10-15  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Clipboard API] Implement getType() for ClipboardItems created from bindings
+        https://bugs.webkit.org/show_bug.cgi?id=202943
+
+        Reviewed by Tim Horton.
+
+        Add a new layout test to verify that we can create and ask ClipboardItems for data. Exercises the following
+        corner cases:
+        - Promise rejection when returning item data.
+        - Resolving promises to incorrect data types.
+        - Setting types to custom strings (including emojis and non-ASCII characters).
+        - Returning values with emojis and non-ASCII characters.
+        - Resolving promises using both Blobs and DOMStrings.
+        - Delayed promise rejection/resolution (using setTimeout).
+
+        * editing/async-clipboard/clipboard-item-basic-expected.txt: Added.
+        * editing/async-clipboard/clipboard-item-basic.html: Added.
+        * editing/async-clipboard/resources/async-clipboard-helpers.js: Added.
+
+        Add a resource file with some helper functions for creating blobs, and loading images and text from blobs.
+
+        * platform/win/TestExpectations:
+
+        Temporarily mark a test as failing; I'll fix this and some other failing tests in a followup. See
+        <https://webkit.org/b/202940>.
+
 2019-10-15  Rob Buis  <rbuis@igalia.com>
 
         Remove duplicate MathML tests
diff --git a/LayoutTests/editing/async-clipboard/clipboard-item-basic-expected.txt b/LayoutTests/editing/async-clipboard/clipboard-item-basic-expected.txt
new file mode 100644
index 0000000..c0fac2f
--- /dev/null
+++ b/LayoutTests/editing/async-clipboard/clipboard-item-basic-expected.txt
@@ -0,0 +1,60 @@
+Tests the ability to create and extract data from ClipboardItems.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+PASS Created new ClipboardItem with 1 type(s)
+PASS commaSeparated(item.types) is "text/plain"
+PASS blob.size is 3
+PASS blob.type is "text/plain"
+PASS text is "foo"
+PASS Caught expected exception. (calling getType('text/html'))
+PASS Caught expected exception. (calling getType('foo bar'))
+
+PASS Created new ClipboardItem with 1 type(s)
+PASS commaSeparated(item.types) is "text/html"
+PASS blob.size is 20
+PASS blob.type is "text/html"
+PASS text is "<strong>bar</strong>"
+
+PASS Created new ClipboardItem with 1 type(s)
+PASS commaSeparated(item.types) is "text/uri-list"
+PASS blob.size is 37
+PASS blob.type is "text/uri-list"
+PASS text is "https://www.w3.org/TR/clipboard-apis/"
+
+PASS Created new ClipboardItem with 1 type(s)
+PASS commaSeparated(item.types) is "image/png"
+PASS blob.size is 979
+PASS blob.type is "image/png"
+PASS image.width is 60
+PASS image.height is 60
+
+PASS Created new ClipboardItem with 4 type(s)
+PASS commaSeparated(item.types) is "image/png, text/html, text/uri-list, text/plain"
+PASS image.width is 60
+PASS image.height is 60
+PASS html is "<strong>Hello</strong><script>console.log(\"world\")</script>"
+PASS url is "https://www.w3.org/TR/clipboard-apis/"
+PASS text is "Async 馃搵 API"
+
+PASS Created new ClipboardItem with 5 type(s)
+PASS commaSeparated(item.types) is "text/plain, text/html, image/png, 馃馃馃, 诪拽讜专 讛砖诐 注讘专讬转"
+PASS text is "璎濊瑵"
+PASS customText1 is "诪拽讜专 讛砖诐 注讘专讬转"
+PASS customText2 is "馃馃馃"
+PASS Caught expected exception. (calling getType('text/html'))
+PASS Caught expected exception. (calling getType('image/png'))
+
+PASS Created new ClipboardItem with 5 type(s)
+PASS commaSeparated(item.types) is "!@#$%, image/png, text/html, text/uri-list, text/plain"
+PASS Caught expected exception. (calling getType('!@#$%'))
+PASS Caught expected exception. (calling getType('image/png'))
+PASS Caught expected exception. (calling getType('text/html'))
+PASS Caught expected exception. (calling getType('text/uri-list'))
+PASS Caught expected exception. (calling getType('text/plain'))
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/async-clipboard/clipboard-item-basic.html b/LayoutTests/editing/async-clipboard/clipboard-item-basic.html
new file mode 100644
index 0000000..fdebdb3
--- /dev/null
+++ b/LayoutTests/editing/async-clipboard/clipboard-item-basic.html
@@ -0,0 +1,211 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ experimental:asyncClipboardAPIEnabled=true ] -->
+<html>
+    <meta charset="utf8">
+    <head>
+        <script src="../../resources/js-test.js"></script>
+        <script src="./resources/async-clipboard-helpers.js"></script>
+    </head>
+    <script>
+        jsTestIsAsync = true;
+
+        function commaSeparated(types) {
+            return types.join(", ");
+        }
+
+        function tryToCreateClipboardItem(data) {
+            try {
+                debug("");
+                const item = new ClipboardItem(data);
+                testPassed(`Created new ClipboardItem with ${Object.keys(data).length} type(s)`);
+                return item;
+            } catch (exception) {
+                testFailed(`Caught exception while creating ClipboardItem: ${exception}`);
+                return null;
+            }
+        }
+
+        async function doWithoutExpectingException(callback) {
+            try {
+                await callback();
+            } catch (exception) {
+                testFailed(`Caught unexpected exception: ${exception}`);
+            }
+        }
+
+        async function doExpectingException(callback, message) {
+            try {
+                await callback();
+                testFailed(`Expected exception (${message})`);
+            } catch (exception) {
+                testPassed(`Caught expected exception. (${message})`);
+            }
+        }
+
+        async function runTest()
+        {
+            description("Tests the ability to create and extract data from ClipboardItems.");
+
+            await (async function() {
+                item = tryToCreateClipboardItem({
+                    "text/plain" : Promise.resolve("foo")
+                });
+
+                await doWithoutExpectingException(async () => {
+                    shouldBeEqualToString("commaSeparated(item.types)", "text/plain");
+                    blob = await item.getType("text/plain");
+                    shouldBe("blob.size", "3");
+                    shouldBeEqualToString("blob.type", "text/plain");
+                    text = await loadText(blob);
+                    shouldBeEqualToString("text", "foo");
+                });
+
+                await doExpectingException(async () => {
+                    await item.getType("text/html");
+                }, "calling getType('text/html')");
+
+                await doExpectingException(async () => {
+                    await item.getType("foo bar");
+                }, "calling getType('foo bar')");
+            })();
+
+            await (async function() {
+                item = tryToCreateClipboardItem({
+                    "text/html" : Promise.resolve(textBlob("<strong>bar</strong>", "text/html"))
+                });
+
+                await doWithoutExpectingException(async () => {
+                    shouldBeEqualToString("commaSeparated(item.types)", "text/html");
+                    blob = await item.getType("text/html");
+                    shouldBe("blob.size", "20");
+                    shouldBeEqualToString("blob.type", "text/html");
+                    text = await loadText(blob);
+                    shouldBeEqualToString("text", "<strong>bar</strong>");
+                });
+            })();
+
+            await (async function() {
+                item = tryToCreateClipboardItem({
+                    "text/uri-list" : new Promise(resolve => {
+                        setTimeout(() => resolve("https://www.w3.org/TR/clipboard-apis/"), 50);
+                    })
+                });
+
+                await doWithoutExpectingException(async () => {
+                    shouldBeEqualToString("commaSeparated(item.types)", "text/uri-list");
+                    blob = await item.getType("text/uri-list");
+                    shouldBe("blob.size", "37");
+                    shouldBeEqualToString("blob.type", "text/uri-list");
+                    text = await loadText(blob);
+                    shouldBeEqualToString("text", "https://www.w3.org/TR/clipboard-apis/");
+                });
+            })();
+
+            await (async function() {
+                item = tryToCreateClipboardItem({
+                    "image/png" : new Promise(resolve => {
+                        setTimeout(() => resolve(imageBlob()), 50);
+                    })
+                });
+
+                await doWithoutExpectingException(async () => {
+                    shouldBeEqualToString("commaSeparated(item.types)", "image/png");
+                    blob = await item.getType("image/png");
+                    shouldBe("blob.size", "979");
+                    shouldBeEqualToString("blob.type", "image/png");
+                    image = await loadImage(blob);
+                    shouldBe("image.width", "60");
+                    shouldBe("image.height", "60");
+                });
+            })();
+
+            await (async function() {
+                item = tryToCreateClipboardItem({
+                    "image/png" : Promise.resolve(imageBlob()),
+                    "text/html" : Promise.resolve(textBlob(`<strong>Hello</strong><script>console.log("world")</${"script"}>`, "text/html")),
+                    "text/uri-list" : Promise.resolve(textBlob("https://www.w3.org/TR/clipboard-apis/", "text/uri-list")),
+                    "text/plain" : Promise.resolve("Async 馃搵 API")
+                });
+
+                await doWithoutExpectingException(async () => {
+                    shouldBeEqualToString("commaSeparated(item.types)", "image/png, text/html, text/uri-list, text/plain");
+                    image = await loadImage(await item.getType("image/png"));
+                    shouldBe("image.width", "60");
+                    shouldBe("image.height", "60");
+                    html = await loadText(await item.getType("text/html"));
+                    shouldBeEqualToString("html", `<strong>Hello</strong><script>console.log("world")</${"script"}>`)
+                    url = await loadText(await item.getType("text/uri-list"));
+                    shouldBeEqualToString("url", "https://www.w3.org/TR/clipboard-apis/");
+                    text = await loadText(await item.getType("text/plain"));
+                    shouldBeEqualToString("text", "Async 馃搵 API");
+                });
+            })();
+
+            await (async function() {
+                item = tryToCreateClipboardItem({
+                    "text/plain" : Promise.resolve("璎濊瑵"),
+                    "text/html" : new Promise((_, reject) => setTimeout(() => reject(imageBlob()), 50)),
+                    "image/png" : new Promise((_, reject) => setTimeout(() => reject(imageBlob()), 50)),
+                    "馃馃馃" : Promise.resolve("诪拽讜专 讛砖诐 注讘专讬转"),
+                    "诪拽讜专 讛砖诐 注讘专讬转" : Promise.resolve("馃馃馃")
+                });
+
+                await doWithoutExpectingException(async () => {
+                    shouldBeEqualToString("commaSeparated(item.types)", "text/plain, text/html, image/png, 馃馃馃, 诪拽讜专 讛砖诐 注讘专讬转");
+                    text = await loadText(await item.getType("text/plain"));
+                    shouldBeEqualToString("text", "璎濊瑵");
+                    customText1 = await loadText(await item.getType("馃馃馃"));
+                    shouldBeEqualToString("customText1", "诪拽讜专 讛砖诐 注讘专讬转");
+                    customText2 = await loadText(await item.getType("诪拽讜专 讛砖诐 注讘专讬转"));
+                    shouldBeEqualToString("customText2", "馃馃馃");
+                });
+
+                await doExpectingException(async () => {
+                    await item.getType("text/html");
+                }, "calling getType('text/html')");
+
+                await doExpectingException(async () => {
+                    await item.getType("image/png");
+                }, "calling getType('image/png')");
+            })();
+
+            await (async function() {
+                item = tryToCreateClipboardItem({
+                    "!@#$%" : Promise.resolve(-2),
+                    "image/png" : Promise.resolve(new Image),
+                    "text/html" : Promise.resolve(null),
+                    "text/uri-list" : Promise.resolve(undefined),
+                    "text/plain" : Promise.resolve([])
+                });
+
+                await doWithoutExpectingException(async () => {
+                    shouldBeEqualToString("commaSeparated(item.types)", "!@#$%, image/png, text/html, text/uri-list, text/plain");
+                });
+
+                await doExpectingException(async () => {
+                    await item.getType("!@#$%");
+                }, "calling getType('!@#$%')");
+
+                await doExpectingException(async () => {
+                    await item.getType("image/png");
+                }, "calling getType('image/png')");
+
+                await doExpectingException(async () => {
+                    await item.getType("text/html");
+                }, "calling getType('text/html')");
+
+                await doExpectingException(async () => {
+                    await item.getType("text/uri-list");
+                }, "calling getType('text/uri-list')");
+
+                await doExpectingException(async () => {
+                    await item.getType("text/plain");
+                }, "calling getType('text/plain')");
+            })();
+
+            finishJSTest();
+        }
+
+        addEventListener("load", runTest);
+    </script>
+    <body></body>
+</html>
diff --git a/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js b/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js
new file mode 100644
index 0000000..3507289
--- /dev/null
+++ b/LayoutTests/editing/async-clipboard/resources/async-clipboard-helpers.js
@@ -0,0 +1,31 @@
+function sampleBase64PNGImageData() {
+    // A 60 by 60 solid red square.
+    return "iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAAAXNSR0IArs4c6QAAAJZlWElmTU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAACQAAAAAQAAAJAAAAABAASShgAHAAAAEgAAAISgAQADAAAAAQABAACgAgAEAAAAAQAAADygAwAEAAAAAQAAADwAAAAAQVNDSUkAAABTY3JlZW5zaG90CUg0mwAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAdRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpVc2VyQ29tbWVudD5TY3JlZW5zaG90PC9leGlmOlVzZXJDb21tZW50PgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+NjA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4K9+BmbAAAABxpRE9UAAAAAgAAAAAAAAAeAAAAKAAAAB4AAAAeAAAAls/GUI8AAABiSURBVGgF7NIxAQAgDMRA6ogd/7pAQByEdPzt/zr37Ls+uqmwXDthOfBKOGHZAr20DBR1EsYksiBhGSjqJIxJZEHCMlDUSRiTyIKEZaCokzAmkQUJy0BRJ2FMIgsSloGizgMAAP//Y4b2JQAAAGBJREFU7dIxAQAgDMRA6ogd/7pAQByEdPzt/zr37Ls+uqmwXDthOfBKOGHZAr20DBR1EsYksiBhGSjqJIxJZEHCMlDUSRiTyIKEZaCokzAmkQUJy0BRJ2FMIgsSloGizgOl3pDZBBa0hwAAAABJRU5ErkJggg";
+}
+
+function imageBlob(base64String = sampleBase64PNGImageData()) {
+    return textBlob(atob(base64String), "image/png");
+}
+
+function textBlob(data, type = "text/plain") {
+    const array = [...data].map(char => char.charCodeAt(0));
+    return new Blob([new Uint8Array(array)], { "type" : type });
+}
+
+function loadText(blob) {
+    return new Promise((resolve, reject) => {
+        const reader = new FileReader;
+        reader.addEventListener("load", () => resolve(reader.result), { once: true });
+        reader.addEventListener("error", reject, { once: true });
+        reader.readAsText(blob);
+    });
+}
+
+function loadImage(blob) {
+    return new Promise((resolve, reject) => {
+        const image = new Image;
+        image.addEventListener("load", () => resolve(image), { once: true });
+        image.addEventListener("error", reject, { once: true });
+        image.src = URL.createObjectURL(blob);
+    });
+}
diff --git a/LayoutTests/platform/win/TestExpectations b/LayoutTests/platform/win/TestExpectations
index 41a8b97..ec2cf5c 100644
--- a/LayoutTests/platform/win/TestExpectations
+++ b/LayoutTests/platform/win/TestExpectations
@@ -4471,6 +4471,7 @@
 webkit.org/b/202939 fast/workers/worker-exception-during-navigation.html [ Failure Pass ]
 
 webkit.org/b/202940 editing/async-clipboard/clipboard-interfaces.html [ Failure ]
+webkit.org/b/202940 editing/async-clipboard/clipboard-item-basic.html [ Failure ]
 
 webkit.org/b/202945 fast/css/invalidation-errors-2.html [ Failure ]
 webkit.org/b/202945 fast/css/invalidation-errors.html [ Failure ]
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 8b3ae3d..9a8fa5c 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,76 @@
+2019-10-15  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [Clipboard API] Implement getType() for ClipboardItems created from bindings
+        https://bugs.webkit.org/show_bug.cgi?id=202943
+
+        Reviewed by Tim Horton.
+
+        Adds basic support for ClipboardItem.getType(), in the case where the ClipboardItems are created by the page. To
+        achieve this, we introduce ClipboardItemDataSource, which represents the data source backing a given clipboard
+        item. This backing may either consist of a list of types and their corresponding DOMPromises (for ClipboardItems
+        that come from the page), or may consist of a list of items that will ask the platformr pasteboard for their
+        data (to be supported in a future patch).
+
+        See below for more details.
+
+        Test: editing/async-clipboard/clipboard-item-basic.html
+
+        * Modules/async-clipboard/Clipboard.h:
+        * Modules/async-clipboard/ClipboardItem.cpp:
+        (WebCore::clipboardItemPresentationStyle):
+        (WebCore::ClipboardItem::ClipboardItem):
+
+        Pass in the parent Clipboard object for ClipboardItems that are backed by the platform pasteboard (which are
+        returned by Clipboard.read()). (Note that this doesn't make any difference until this codepath is actually
+        exercised when we add support for Clipboard.read()).
+
+        (WebCore::ClipboardItem::create):
+        (WebCore::ClipboardItem::types const):
+        (WebCore::ClipboardItem::getType):
+
+        Plumb types() and getType() to the clipboard item's datasource.
+
+        (WebCore::ClipboardItem::navigator):
+
+        Make navigator() return the parent Clipboard object's navigator.
+
+        * Modules/async-clipboard/ClipboardItem.h:
+        * Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp: Added.
+        (WebCore::blobFromString):
+        (WebCore::ClipboardItemBindingsDataSource::ClipboardItemBindingsDataSource):
+
+        Store the given list of types and DOM promises.
+
+        (WebCore::ClipboardItemBindingsDataSource::types const):
+        (WebCore::ClipboardItemBindingsDataSource::getType):
+
+        Implement getType() by finding the matching promised type in the item's array of types, and waiting for the
+        promise to either resolve or reject. If the promise resolves to either a string or blob, we deliver the result
+        back to the page by resolving the promise returned by getType(). Otherwise, we reject it.
+
+        * Modules/async-clipboard/ClipboardItemBindingsDataSource.h:
+        * Modules/async-clipboard/ClipboardItemDataSource.h:
+        (WebCore::ClipboardItemDataSource::ClipboardItemDataSource):
+        * Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp:
+
+        Add a stub implementation of a clipboard item data source that is backed by data in the platform pasteboard. In
+        a future patch, this will implement getType() by calling out to the platform pasteboard.
+
+        (WebCore::ClipboardItemPasteboardDataSource::ClipboardItemPasteboardDataSource):
+        (WebCore::ClipboardItemPasteboardDataSource::types const):
+        (WebCore::ClipboardItemPasteboardDataSource::getType):
+        * Modules/async-clipboard/ClipboardItemPasteboardDataSource.h:
+        * Modules/mediastream/RTCRtpReceiver.cpp:
+        * Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp:
+
+        Unrelated build fixes, due to changes in unified source groupings.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/network/mac/UTIUtilities.mm:
+
+        More build fixes, due to changes in unified source groupings.
+
 2019-10-15  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][IFC] Add support for text-transform: uppercase/lowercase
diff --git a/Source/WebCore/Modules/async-clipboard/Clipboard.h b/Source/WebCore/Modules/async-clipboard/Clipboard.h
index 282033a..1373f4d 100644
--- a/Source/WebCore/Modules/async-clipboard/Clipboard.h
+++ b/Source/WebCore/Modules/async-clipboard/Clipboard.h
@@ -36,7 +36,7 @@
 class DeferredPromise;
 class Navigator;
 
-class Clipboard final : public RefCounted<Clipboard>, public EventTargetWithInlineData {
+class Clipboard final : public RefCounted<Clipboard>, public EventTargetWithInlineData, public CanMakeWeakPtr<Clipboard> {
     WTF_MAKE_ISO_ALLOCATED(Clipboard);
 public:
     static Ref<Clipboard> create(Navigator&);
diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItem.cpp b/Source/WebCore/Modules/async-clipboard/ClipboardItem.cpp
index 9b3ec3c..9c7a2e3 100644
--- a/Source/WebCore/Modules/async-clipboard/ClipboardItem.cpp
+++ b/Source/WebCore/Modules/async-clipboard/ClipboardItem.cpp
@@ -26,18 +26,40 @@
 #include "config.h"
 #include "ClipboardItem.h"
 
-#include "JSDOMPromise.h"
-#include "JSDOMPromiseDeferred.h"
+#include "ClipboardItemBindingsDataSource.h"
+#include "ClipboardItemPasteboardDataSource.h"
 #include "Navigator.h"
+#include "PasteboardItemInfo.h"
 
 namespace WebCore {
 
 ClipboardItem::~ClipboardItem() = default;
 
-ClipboardItem::ClipboardItem(Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&& items, const Options& options)
-    : m_presentationStyle(options.presentationStyle)
+static ClipboardItem::PresentationStyle clipboardItemPresentationStyle(const PasteboardItemInfo& info)
 {
-    UNUSED_PARAM(items);
+    switch (info.preferredPresentationStyle) {
+    case PasteboardItemPresentationStyle::Unspecified:
+        return ClipboardItem::PresentationStyle::Unspecified;
+    case PasteboardItemPresentationStyle::Inline:
+        return ClipboardItem::PresentationStyle::Inline;
+    case PasteboardItemPresentationStyle::Attachment:
+        return ClipboardItem::PresentationStyle::Attachment;
+    }
+    ASSERT_NOT_REACHED();
+    return ClipboardItem::PresentationStyle::Unspecified;
+}
+
+ClipboardItem::ClipboardItem(Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&& items, const Options& options)
+    : m_dataSource(makeUnique<ClipboardItemBindingsDataSource>(*this, WTFMove(items)))
+    , m_presentationStyle(options.presentationStyle)
+{
+}
+
+ClipboardItem::ClipboardItem(Clipboard& clipboard, const PasteboardItemInfo& info, size_t index)
+    : m_clipboard(makeWeakPtr(clipboard))
+    , m_dataSource(makeUnique<ClipboardItemPasteboardDataSource>(*this, info, index))
+    , m_presentationStyle(clipboardItemPresentationStyle(info))
+{
 }
 
 Ref<ClipboardItem> ClipboardItem::create(Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&& data, const Options& options)
@@ -45,22 +67,24 @@
     return adoptRef(*new ClipboardItem(WTFMove(data), options));
 }
 
+Ref<ClipboardItem> ClipboardItem::create(Clipboard& clipboard, const PasteboardItemInfo& info, size_t index)
+{
+    return adoptRef(*new ClipboardItem(clipboard, info, index));
+}
+
 Vector<String> ClipboardItem::types() const
 {
-    return { };
+    return m_dataSource->types();
 }
 
 void ClipboardItem::getType(const String& type, Ref<DeferredPromise>&& promise)
 {
-    UNUSED_PARAM(type);
-    promise->reject(NotSupportedError);
+    m_dataSource->getType(type, WTFMove(promise));
 }
 
 Navigator* ClipboardItem::navigator()
 {
-    // FIXME: When support for Clipboard.read() is implemented, this should instead return the associated Clipboard
-    // object's navigator, if it is associated with a Clipboard.
-    return nullptr;
+    return m_clipboard ? m_clipboard->navigator() : nullptr;
 }
 
 } // namespace WebCore
diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItem.h b/Source/WebCore/Modules/async-clipboard/ClipboardItem.h
index bbd7f61..98e96ff 100644
--- a/Source/WebCore/Modules/async-clipboard/ClipboardItem.h
+++ b/Source/WebCore/Modules/async-clipboard/ClipboardItem.h
@@ -29,13 +29,18 @@
 #include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
 #include <wtf/Vector.h>
+#include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
+class Blob;
+class Clipboard;
+class ClipboardItemDataSource;
 class DeferredPromise;
 class DOMPromise;
 class Navigator;
+struct PasteboardItemInfo;
 
 class ClipboardItem : public RefCounted<ClipboardItem> {
 public:
@@ -48,6 +53,7 @@
     };
 
     static Ref<ClipboardItem> create(Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&&, const Options&);
+    static Ref<ClipboardItem> create(Clipboard&, const PasteboardItemInfo&, size_t index);
 
     Vector<String> types() const;
     void getType(const String&, Ref<DeferredPromise>&&);
@@ -55,9 +61,14 @@
     PresentationStyle presentationStyle() const { return m_presentationStyle; };
     Navigator* navigator();
 
+protected:
+    WeakPtr<Clipboard> m_clipboard;
+
 private:
     ClipboardItem(Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&&, const Options&);
+    ClipboardItem(Clipboard&, const PasteboardItemInfo&, size_t index);
 
+    std::unique_ptr<ClipboardItemDataSource> m_dataSource;
     PresentationStyle m_presentationStyle { PresentationStyle::Unspecified };
 };
 
diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp
new file mode 100644
index 0000000..5038141
--- /dev/null
+++ b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "ClipboardItemBindingsDataSource.h"
+
+#include "Blob.h"
+#include "JSBlob.h"
+#include "JSDOMPromise.h"
+#include "JSDOMPromiseDeferred.h"
+#include "SharedBuffer.h"
+#include <wtf/Function.h>
+
+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))
+{
+}
+
+ClipboardItemBindingsDataSource::~ClipboardItemBindingsDataSource() = default;
+
+Vector<String> ClipboardItemBindingsDataSource::types() const
+{
+    return m_itemPromises.map([&] (auto& typeAndItem) {
+        return typeAndItem.key;
+    });
+}
+
+void ClipboardItemBindingsDataSource::getType(const String& type, Ref<DeferredPromise>&& promise)
+{
+    auto matchIndex = m_itemPromises.findMatching([&] (auto& item) {
+        return type == item.key;
+    });
+
+    if (matchIndex == notFound) {
+        promise->reject(NotFoundError);
+        return;
+    }
+
+    auto itemPromise = m_itemPromises[matchIndex].value;
+    itemPromise->whenSettled([itemPromise, promise = makeRefPtr(promise.get()), type] () mutable {
+        if (itemPromise->status() != DOMPromise::Status::Fulfilled) {
+            promise->reject(AbortError);
+            return;
+        }
+
+        auto result = itemPromise->result();
+        if (!result) {
+            promise->reject(TypeError);
+            return;
+        }
+
+        String string;
+        result.getString(itemPromise->globalObject()->globalExec(), string);
+        if (!string.isNull()) {
+            promise->resolve<IDLInterface<Blob>>(blobFromString(string, type));
+            return;
+        }
+
+        if (!result.isObject()) {
+            promise->reject(TypeError);
+            return;
+        }
+
+        if (auto blob = JSBlob::toWrapped(result.getObject()->vm(), result.getObject()))
+            promise->resolve<IDLInterface<Blob>>(*blob);
+        else
+            promise->reject(TypeError);
+    });
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h
new file mode 100644
index 0000000..6fd8dda
--- /dev/null
+++ b/Source/WebCore/Modules/async-clipboard/ClipboardItemBindingsDataSource.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+
+#include "ClipboardItemDataSource.h"
+
+namespace WebCore {
+
+class DOMPromise;
+
+class ClipboardItemBindingsDataSource : public ClipboardItemDataSource {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ClipboardItemBindingsDataSource(ClipboardItem&, Vector<KeyValuePair<String, RefPtr<DOMPromise>>>&&);
+    ~ClipboardItemBindingsDataSource();
+
+private:
+    Vector<String> types() const final;
+    void getType(const String&, Ref<DeferredPromise>&&) final;
+
+    Vector<KeyValuePair<String, RefPtr<DOMPromise>>> m_itemPromises;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItemDataSource.h b/Source/WebCore/Modules/async-clipboard/ClipboardItemDataSource.h
new file mode 100644
index 0000000..92a6d1f
--- /dev/null
+++ b/Source/WebCore/Modules/async-clipboard/ClipboardItemDataSource.h
@@ -0,0 +1,54 @@
+/*
+ * 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
+
+#include <wtf/CompletionHandler.h>
+#include <wtf/Ref.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class DeferredPromise;
+class ClipboardItem;
+
+class ClipboardItemDataSource {
+public:
+    ClipboardItemDataSource(ClipboardItem& item)
+        : m_item(item)
+    {
+    }
+
+    virtual ~ClipboardItemDataSource() = default;
+
+    virtual Vector<String> types() const = 0;
+    virtual void getType(const String&, Ref<DeferredPromise>&&) = 0;
+
+protected:
+    ClipboardItem& m_item;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp b/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp
new file mode 100644
index 0000000..7b9ead1
--- /dev/null
+++ b/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "ClipboardItemPasteboardDataSource.h"
+
+#include "PasteboardItemInfo.h"
+
+namespace WebCore {
+
+ClipboardItemPasteboardDataSource::ClipboardItemPasteboardDataSource(ClipboardItem& item, const PasteboardItemInfo& info, size_t itemIndex)
+    : ClipboardItemDataSource(item)
+    , m_types(info.webSafeTypesByFidelity)
+    , m_itemIndex(itemIndex)
+    , m_initialChangeCount(info.changeCount)
+{
+}
+
+ClipboardItemPasteboardDataSource::~ClipboardItemPasteboardDataSource() = default;
+
+Vector<String> ClipboardItemPasteboardDataSource::types() const
+{
+    return m_types;
+}
+
+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);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.h b/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.h
new file mode 100644
index 0000000..a021530
--- /dev/null
+++ b/Source/WebCore/Modules/async-clipboard/ClipboardItemPasteboardDataSource.h
@@ -0,0 +1,49 @@
+/*
+ * 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
+
+#include "ClipboardItemDataSource.h"
+
+namespace WebCore {
+
+struct PasteboardItemInfo;
+
+class ClipboardItemPasteboardDataSource : public ClipboardItemDataSource {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ClipboardItemPasteboardDataSource(ClipboardItem&, const PasteboardItemInfo&, size_t itemIndex);
+    ~ClipboardItemPasteboardDataSource();
+
+private:
+    Vector<String> types() const final;
+    void getType(const String&, Ref<DeferredPromise>&&) final;
+
+    Vector<String> m_types;
+    size_t m_itemIndex { 0 };
+    int m_initialChangeCount { 0 };
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/Modules/mediastream/RTCRtpReceiver.cpp b/Source/WebCore/Modules/mediastream/RTCRtpReceiver.cpp
index 09e891f..42c4c07 100644
--- a/Source/WebCore/Modules/mediastream/RTCRtpReceiver.cpp
+++ b/Source/WebCore/Modules/mediastream/RTCRtpReceiver.cpp
@@ -33,6 +33,7 @@
 
 #if ENABLE(WEB_RTC)
 
+#include "JSDOMPromiseDeferred.h"
 #include "PeerConnectionBackend.h"
 #include "RTCRtpCapabilities.h"
 #include <wtf/IsoMallocInlines.h>
diff --git a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp
index 147d292..907d682 100644
--- a/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp
+++ b/Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCCertificateGenerator.cpp
@@ -27,8 +27,10 @@
 
 #if USE(LIBWEBRTC)
 
+#include "JSDOMPromiseDeferred.h"
 #include "JSRTCCertificate.h"
 #include "LibWebRTCMacros.h"
+#include "RTCCertificate.h"
 
 ALLOW_UNUSED_PARAMETERS_BEGIN
 
diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt
index 8a4983b..0da6279 100644
--- a/Source/WebCore/Sources.txt
+++ b/Source/WebCore/Sources.txt
@@ -35,6 +35,8 @@
 
 Modules/async-clipboard/Clipboard.cpp
 Modules/async-clipboard/ClipboardItem.cpp
+Modules/async-clipboard/ClipboardItemBindingsDataSource.cpp
+Modules/async-clipboard/ClipboardItemPasteboardDataSource.cpp
 Modules/async-clipboard/NavigatorClipboard.cpp
 
 Modules/beacon/NavigatorBeacon.cpp
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index cbd44b6..ca2a4ea 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -4886,6 +4886,7 @@
 		F44EBBD91DB5D21400277334 /* StaticRange.h in Headers */ = {isa = PBXBuildFile; fileRef = F44EBBD81DB5D21400277334 /* StaticRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F45C231E1995B73B00A6E2E3 /* AxisScrollSnapOffsets.h in Headers */ = {isa = PBXBuildFile; fileRef = F45C231C1995B73B00A6E2E3 /* AxisScrollSnapOffsets.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F46729281E0DE68500ACC3D8 /* ScrollSnapOffsetsInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F46729251E0DE5AB00ACC3D8 /* ScrollSnapOffsetsInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		F46C447E234654540039A79D /* ClipboardItemBindingsDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = F46C447C234654540039A79D /* ClipboardItemBindingsDataSource.h */; };
 		F478755419983AFF0024A287 /* ScrollSnapAnimatorState.h in Headers */ = {isa = PBXBuildFile; fileRef = F478755219983AFF0024A287 /* ScrollSnapAnimatorState.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F47A09D120A93A9700240FAE /* DisabledAdaptations.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A09CF20A939F600240FAE /* DisabledAdaptations.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F47A5E3E195B8C8A00483100 /* StyleScrollSnapPoints.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4901,6 +4902,8 @@
 		F4B422C4220C0568009E1E7D /* DOMPasteAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = F4B422C2220C0000009E1E7D /* DOMPasteAccess.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4BFB9851E1DDF9B00862C24 /* DumpEditingHistory.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389831E1DDF2B0076B7EA /* DumpEditingHistory.js */; };
 		F4BFB9861E1DDF9B00862C24 /* EditingHistoryUtil.js in Copy Scripts */ = {isa = PBXBuildFile; fileRef = F48389841E1DDF2B0076B7EA /* EditingHistoryUtil.js */; };
+		F4D07558234D822D00881E73 /* ClipboardItemDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = F46C447A2346535E0039A79D /* ClipboardItemDataSource.h */; };
+		F4D07559234D823300881E73 /* ClipboardItemPasteboardDataSource.h in Headers */ = {isa = PBXBuildFile; fileRef = F46C44802346547A0039A79D /* ClipboardItemPasteboardDataSource.h */; };
 		F4D43D662188038B00ECECAC /* SerializedAttachmentData.h in Headers */ = {isa = PBXBuildFile; fileRef = F4D43D64218802E600ECECAC /* SerializedAttachmentData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4E57EDC213F3F5F004EA98E /* FontAttributeChanges.h in Headers */ = {isa = PBXBuildFile; fileRef = F4E57EDA213F3F5F004EA98E /* FontAttributeChanges.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		F4E57EE1213F434A004EA98E /* WebCoreNSFontManagerExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = F4E57EDF213F434A004EA98E /* WebCoreNSFontManagerExtras.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -15205,6 +15208,11 @@
 		F45C231C1995B73B00A6E2E3 /* AxisScrollSnapOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AxisScrollSnapOffsets.h; sourceTree = "<group>"; };
 		F4628A9E234D3BBF00BC884C /* PlatformPasteboardCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformPasteboardCocoa.mm; sourceTree = "<group>"; };
 		F46729251E0DE5AB00ACC3D8 /* ScrollSnapOffsetsInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollSnapOffsetsInfo.h; sourceTree = "<group>"; };
+		F46C447A2346535E0039A79D /* ClipboardItemDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClipboardItemDataSource.h; sourceTree = "<group>"; };
+		F46C447C234654540039A79D /* ClipboardItemBindingsDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClipboardItemBindingsDataSource.h; sourceTree = "<group>"; };
+		F46C447D234654540039A79D /* ClipboardItemBindingsDataSource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ClipboardItemBindingsDataSource.cpp; sourceTree = "<group>"; };
+		F46C44802346547A0039A79D /* ClipboardItemPasteboardDataSource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClipboardItemPasteboardDataSource.h; sourceTree = "<group>"; };
+		F46C44812346547A0039A79D /* ClipboardItemPasteboardDataSource.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ClipboardItemPasteboardDataSource.cpp; sourceTree = "<group>"; };
 		F478755219983AFF0024A287 /* ScrollSnapAnimatorState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollSnapAnimatorState.h; sourceTree = "<group>"; };
 		F478755319983AFF0024A287 /* ScrollSnapAnimatorState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollSnapAnimatorState.mm; sourceTree = "<group>"; };
 		F47A09CF20A939F600240FAE /* DisabledAdaptations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisabledAdaptations.h; sourceTree = "<group>"; };
@@ -26853,6 +26861,11 @@
 				F440E775233D94D60063F9AB /* ClipboardItem.cpp */,
 				F440E770233D94D40063F9AB /* ClipboardItem.h */,
 				F440E777233D94D70063F9AB /* ClipboardItem.idl */,
+				F46C447D234654540039A79D /* ClipboardItemBindingsDataSource.cpp */,
+				F46C447C234654540039A79D /* ClipboardItemBindingsDataSource.h */,
+				F46C447A2346535E0039A79D /* ClipboardItemDataSource.h */,
+				F46C44812346547A0039A79D /* ClipboardItemPasteboardDataSource.cpp */,
+				F46C44802346547A0039A79D /* ClipboardItemPasteboardDataSource.h */,
 				F440E773233D94D50063F9AB /* NavigatorClipboard.cpp */,
 				F440E76F233D94D30063F9AB /* NavigatorClipboard.h */,
 				F440E771233D94D40063F9AB /* NavigatorClipboard.idl */,
@@ -28831,6 +28844,9 @@
 				7C3A91E61C963B8800D1A7E3 /* ClipboardAccessPolicy.h in Headers */,
 				85031B400A44EFC700F992E0 /* ClipboardEvent.h in Headers */,
 				F440E77B233D94D70063F9AB /* ClipboardItem.h in Headers */,
+				F46C447E234654540039A79D /* ClipboardItemBindingsDataSource.h in Headers */,
+				F4D07558234D822D00881E73 /* ClipboardItemDataSource.h in Headers */,
+				F4D07559234D823300881E73 /* ClipboardItemPasteboardDataSource.h in Headers */,
 				FB92DF4B15FED08700994433 /* ClipPathOperation.h in Headers */,
 				580371621A66F00A00BAF519 /* ClipRect.h in Headers */,
 				97AABD1314FA09D5007457AE /* CloseEvent.h in Headers */,
diff --git a/Source/WebCore/platform/network/mac/UTIUtilities.mm b/Source/WebCore/platform/network/mac/UTIUtilities.mm
index 65b28d0..142911a 100644
--- a/Source/WebCore/platform/network/mac/UTIUtilities.mm
+++ b/Source/WebCore/platform/network/mac/UTIUtilities.mm
@@ -27,6 +27,7 @@
 #import "UTIUtilities.h"
 #import <wtf/MainThread.h>
 #import <wtf/TinyLRUCache.h>
+#import <wtf/text/StringHash.h>
 #import <wtf/text/WTFString.h>
 
 #if PLATFORM(IOS_FAMILY)