Title: [273184] trunk
Revision
273184
Author
wenson_hs...@apple.com
Date
2021-02-19 16:51:03 -0800 (Fri, 19 Feb 2021)

Log Message

[iOS] Specify a _UIDataOwner when reading or writing from the system pasteboard
https://bugs.webkit.org/show_bug.cgi?id=222072
<rdar://problem/74208576>

Reviewed by Devin Rousso.

Source/WebCore:

Add a static helper method to `PlatformPasteboard`, so that it can perform arbitrary pasteboard operations
within the context of a given `DataOwnerType`. We then use this static helper to wrap all pasteboard access
(reading, writing, etc.) inside calls to `+[UIPasteboard _performAsDataOwner:block:]` -- see WebKit ChangeLog
for more details.

Tests:  UIPasteboardTests.PerformAsDataOwnerWhenCopying
        UIPasteboardTests.PerformAsDataOwnerWhenPasting

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* platform/DataOwnerType.h: Added.

Add a new enum to represent a data owner type.

* platform/PlatformPasteboard.h:
* platform/ios/PlatformPasteboardIOS.mm:
(WebCore::PlatformPasteboard::performAsDataOwner):
* platform/libwpe/PlatformPasteboardLibWPE.cpp:
(WebCore::PlatformPasteboard::performAsDataOwner):
* platform/mac/PlatformPasteboardMac.mm:
(WebCore::PlatformPasteboard::performAsDataOwner):

Source/WebCore/PAL:

Import `UIPasteboard_Private.h` so that `PlatformPasteboardIOS.mm` can use the new SPI.

* pal/spi/ios/UIKitSPI.h:

Source/WebKit:

Adds WebKit2 support for tagging `PlatformPasteboard` with the content view's pasteboard data owner type. See
below for more details.

* Platform/spi/ios/UIKitSPI.h:

Import `UIPasteboard_Private.h` so that we know about `+_performAsDataOwner:block:` in the API tests.

* UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
(WebKit::WebPasteboardProxy::getPasteboardTypes):
(WebKit::WebPasteboardProxy::getPasteboardPathnamesForType):
(WebKit::WebPasteboardProxy::getPasteboardStringForType):
(WebKit::WebPasteboardProxy::getPasteboardStringsForType):
(WebKit::WebPasteboardProxy::getPasteboardBufferForType):
(WebKit::WebPasteboardProxy::getPasteboardChangeCount):
(WebKit::WebPasteboardProxy::getPasteboardColor):
(WebKit::WebPasteboardProxy::getPasteboardURL):
(WebKit::WebPasteboardProxy::addPasteboardTypes):
(WebKit::WebPasteboardProxy::setPasteboardTypes):
(WebKit::WebPasteboardProxy::setPasteboardURL):
(WebKit::WebPasteboardProxy::setPasteboardColor):
(WebKit::WebPasteboardProxy::setPasteboardStringForType):
(WebKit::WebPasteboardProxy::containsURLStringSuitableForLoading):

Make all of these methods use `dataOwner()` with either a `Read` or `Write` pasteboard access intent to grab the
data owner type from the view corresponding to the page identifier, and then wrap all pasteboard access within
`PlatformPasteboard`'s new `performAsDataOwner` static helper.

(WebKit::WebPasteboardProxy::urlStringSuitableForLoading):
(WebKit::WebPasteboardProxy::setPasteboardBufferForType):
(WebKit::WebPasteboardProxy::getNumberOfFiles):
(WebKit::WebPasteboardProxy::typesSafeForDOMToReadAndWrite):
(WebKit::WebPasteboardProxy::writeCustomData):
(WebKit::WebPasteboardProxy::allPasteboardItemInfo):
(WebKit::WebPasteboardProxy::informationForItemAtIndex):
(WebKit::WebPasteboardProxy::getPasteboardItemsCount):
(WebKit::WebPasteboardProxy::readStringFromPasteboard):
(WebKit::WebPasteboardProxy::readURLFromPasteboard):
(WebKit::WebPasteboardProxy::readBufferFromPasteboard):
(WebKit::WebPasteboardProxy::containsStringSafeForDOMToReadForType):
(WebKit::WebPasteboardProxy::writeURLToPasteboard):
(WebKit::WebPasteboardProxy::writeWebContentToPasteboard):
(WebKit::WebPasteboardProxy::writeImageToPasteboard):
(WebKit::WebPasteboardProxy::writeStringToPasteboard):
(WebKit::WebPasteboardProxy::updateSupportedTypeIdentifiers):
(WebKit::WebPasteboardProxy::determineDataOwner const):

Use the given page identifier in various pasteboard IPC endpoints in `WebPasteboardProxy` to ask `WebPageProxy`
for its pasteboard data owner type when reading or writing pasteboard data.

* UIProcess/PageClient.h:

Add a client hook to return a `DataOwnerType` enum, given a `PasteboardAccessIntent` -- that is, copy (write) or
paste (read).

(WebKit::PageClient::dataOwnerForPasteboard const):
* UIProcess/PasteboardAccessIntent.h: Added.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::dataOwnerForPasteboard const):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPasteboardProxy.h:
* UIProcess/WebPasteboardProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::dataOwnerForPasteboard const):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(coreDataOwnerType):
(-[WKContentView _dataOwnerForPasteboard:]):

Return `-_dataOwnerForPaste` or `-_dataOwnerForCopy` (depending on the `PasteboardAccessIntent`).

* WebKit.xcodeproj/project.pbxproj:

Source/WTF:

* wtf/PlatformHave.h:

Turn several compile-time guards previously in `PlatformPasteboardIOS.mm` into `HAVE()`-s.

Tools:

Add a couple of new API tests to verify that `+[UIPasteboard _performAsDataOwner:block:]` is invoked with the
expected data owner type when copying and pasting.

* TestWebKitAPI/Tests/ios/UIPasteboardTests.mm:
(+[TestUIPasteboard _performAsDataOwner:block:]):
(TestWebKitAPI::TEST):
* TestWebKitAPI/cocoa/TestWKWebView.h:
* TestWebKitAPI/cocoa/TestWKWebView.mm:
(-[WKWebView contentsAsString]):

Additionally add a helper method to grab a `WKWebView`'s contents as an `NSString`, just for convenience.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (273183 => 273184)


--- trunk/Source/WTF/ChangeLog	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WTF/ChangeLog	2021-02-20 00:51:03 UTC (rev 273184)
@@ -1,3 +1,15 @@
+2021-02-19  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Specify a _UIDataOwner when reading or writing from the system pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=222072
+        <rdar://problem/74208576>
+
+        Reviewed by Devin Rousso.
+
+        * wtf/PlatformHave.h:
+
+        Turn several compile-time guards previously in `PlatformPasteboardIOS.mm` into `HAVE()`-s.
+
 2021-02-16  Jiewen Tan  <jiewen_...@apple.com>
 
         PCM: Generate secret token and corresponding unlinkable token

Modified: trunk/Source/WTF/wtf/PlatformHave.h (273183 => 273184)


--- trunk/Source/WTF/wtf/PlatformHave.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WTF/wtf/PlatformHave.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -893,3 +893,15 @@
     || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 150000)
 #define HAVE_RSA_BSSA 1
 #endif
+
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV)
+#define HAVE_PASTEBOARD_ITEM_PROVIDERS 1
+#endif
+
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV) && !PLATFORM(MACCATALYST)
+#define HAVE_PASTEBOARD_PRESENTATION_STYLE_AND_TEAM_DATA 1
+#endif
+
+#if PLATFORM(IOS_FAMILY) && !PLATFORM(MACCATALYST)
+#define HAVE_NSURL_TITLE 1
+#endif

Modified: trunk/Source/WebCore/ChangeLog (273183 => 273184)


--- trunk/Source/WebCore/ChangeLog	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/ChangeLog	2021-02-20 00:51:03 UTC (rev 273184)
@@ -1,3 +1,33 @@
+2021-02-19  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Specify a _UIDataOwner when reading or writing from the system pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=222072
+        <rdar://problem/74208576>
+
+        Reviewed by Devin Rousso.
+
+        Add a static helper method to `PlatformPasteboard`, so that it can perform arbitrary pasteboard operations
+        within the context of a given `DataOwnerType`. We then use this static helper to wrap all pasteboard access
+        (reading, writing, etc.) inside calls to `+[UIPasteboard _performAsDataOwner:block:]` -- see WebKit ChangeLog
+        for more details.
+
+        Tests:  UIPasteboardTests.PerformAsDataOwnerWhenCopying
+                UIPasteboardTests.PerformAsDataOwnerWhenPasting
+
+        * Headers.cmake:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/DataOwnerType.h: Added.
+
+        Add a new enum to represent a data owner type.
+
+        * platform/PlatformPasteboard.h:
+        * platform/ios/PlatformPasteboardIOS.mm:
+        (WebCore::PlatformPasteboard::performAsDataOwner):
+        * platform/libwpe/PlatformPasteboardLibWPE.cpp:
+        (WebCore::PlatformPasteboard::performAsDataOwner):
+        * platform/mac/PlatformPasteboardMac.mm:
+        (WebCore::PlatformPasteboard::performAsDataOwner):
+
 2021-02-19  Chris Dumez  <cdu...@apple.com>
 
         Make format of release logging more consistent to facilitate grepping

Modified: trunk/Source/WebCore/Headers.cmake (273183 => 273184)


--- trunk/Source/WebCore/Headers.cmake	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/Headers.cmake	2021-02-20 00:51:03 UTC (rev 273184)
@@ -999,6 +999,7 @@
     platform/Cursor.h
     platform/DataListSuggestionPicker.h
     platform/DataListSuggestionsClient.h
+    platform/DataOwnerType.h
     platform/DateComponents.h
     platform/Decimal.h
     platform/DeferrableTask.h

Modified: trunk/Source/WebCore/PAL/ChangeLog (273183 => 273184)


--- trunk/Source/WebCore/PAL/ChangeLog	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/PAL/ChangeLog	2021-02-20 00:51:03 UTC (rev 273184)
@@ -1,3 +1,15 @@
+2021-02-18  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Specify a _UIDataOwner when reading or writing from the system pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=222072
+        <rdar://problem/74208576>
+
+        Reviewed by Devin Rousso.
+
+        Import `UIPasteboard_Private.h` so that `PlatformPasteboardIOS.mm` can use the new SPI.
+
+        * pal/spi/ios/UIKitSPI.h:
+
 2021-02-18  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         [GPU Process] Temporarily disable drawing OT-SVG glyphs in the GPU process until it can be implemented properly

Modified: trunk/Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h (273183 => 273184)


--- trunk/Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/PAL/pal/spi/ios/UIKitSPI.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -41,6 +41,7 @@
 #import <UIKit/UIFocusRingStyle.h>
 #import <UIKit/UIFont_Private.h>
 #import <UIKit/UIInterface_Private.h>
+#import <UIKit/UIPasteboard_Private.h>
 #import <UIKit/UIScreen_Private.h>
 #import <UIKit/UIViewController_Private.h>
 #import <UIKit/NSItemProvider+UIKitAdditions.h>

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (273183 => 273184)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-02-20 00:51:03 UTC (rev 273184)
@@ -5288,6 +5288,7 @@
 		F45775CE241437D5002DF1A0 /* InlinePathData.h in Headers */ = {isa = PBXBuildFile; fileRef = F45775CD241437D5002DF1A0 /* InlinePathData.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 */; };
+		F473845825DDE9FB006DE8DD /* DataOwnerType.h in Headers */ = {isa = PBXBuildFile; fileRef = F473845725DDE9FB006DE8DD /* DataOwnerType.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, ); }; };
 		F47A633D1FF6FD500081B3CC /* PromisedAttachmentInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F47A633C1FF6FD500081B3CC /* PromisedAttachmentInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -16650,6 +16651,7 @@
 		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>"; };
+		F473845725DDE9FB006DE8DD /* DataOwnerType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataOwnerType.h; sourceTree = "<group>"; };
 		F47A09CF20A939F600240FAE /* DisabledAdaptations.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisabledAdaptations.h; sourceTree = "<group>"; };
 		F47A09D420A9DD0400240FAE /* DisabledAdaptations.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisabledAdaptations.cpp; sourceTree = "<group>"; };
 		F47A5E3B195B8C8A00483100 /* StyleScrollSnapPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleScrollSnapPoints.h; sourceTree = "<group>"; };
@@ -27183,9 +27185,9 @@
 				BC5823F40C0A98DF0053F1B5 /* JSHTMLElementCustom.cpp */,
 				BCE1C43F0D9830F4003B02F2 /* JSLocationCustom.cpp */,
 				4B6B5CBE216434FB00603817 /* JSPaintWorkletGlobalScopeCustom.cpp */,
-				41733D7D25DFBFC500A136E5 /* JSRTCRtpSFrameTransformCustom.cpp */,
 				418C395D1C8F0AAB0051C8A3 /* JSReadableStreamSourceCustom.cpp */,
 				46BCBBBE2085005B00710638 /* JSRemoteDOMWindowCustom.cpp */,
+				41733D7D25DFBFC500A136E5 /* JSRTCRtpSFrameTransformCustom.cpp */,
 				7A3EBEAA21BF054C000D043D /* JSSVGViewSpecCustom.cpp */,
 			);
 			name = Custom;
@@ -27621,6 +27623,7 @@
 				F587868402DE3B8601EA4122 /* Cursor.h */,
 				E52CF54E20A35A2800DADA27 /* DataListSuggestionPicker.h */,
 				E52CF54C20A268AC00DADA27 /* DataListSuggestionsClient.h */,
+				F473845725DDE9FB006DE8DD /* DataOwnerType.h */,
 				A5732B08136A161D005C8D7C /* DateComponents.cpp */,
 				A5732B09136A161D005C8D7C /* DateComponents.h */,
 				37C738F11EDBDE87003F2B0B /* DateTimeChooser.h */,
@@ -31879,6 +31882,7 @@
 				E517670320B88C1400D41167 /* DataListSuggestionInformation.h in Headers */,
 				E52CF54F20A35A2800DADA27 /* DataListSuggestionPicker.h in Headers */,
 				E52CF54D20A268AC00DADA27 /* DataListSuggestionsClient.h in Headers */,
+				F473845825DDE9FB006DE8DD /* DataOwnerType.h in Headers */,
 				BC64641C11D7F416006455B0 /* DatasetDOMStringMap.h in Headers */,
 				85031B3E0A44EFC700F992E0 /* DataTransfer.h in Headers */,
 				81AC5999131636E60009A7E0 /* DataTransferItem.h in Headers */,

Added: trunk/Source/WebCore/platform/DataOwnerType.h (0 => 273184)


--- trunk/Source/WebCore/platform/DataOwnerType.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/DataOwnerType.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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
+
+namespace WebCore {
+
+enum class DataOwnerType : uint8_t {
+    Undefined,
+    User,
+    Enterprise,
+    Shared,
+};
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/platform/PlatformPasteboard.h (273183 => 273184)


--- trunk/Source/WebCore/platform/PlatformPasteboard.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/platform/PlatformPasteboard.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 Apple Inc.  All rights reserved.
+ * Copyright (C) 2012-2021 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,9 +23,9 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef PlatformPasteboard_h
-#define PlatformPasteboard_h
+#pragma once
 
+#include "DataOwnerType.h"
 #include <wtf/Forward.h>
 #include <wtf/Function.h>
 #include <wtf/RetainPtr.h>
@@ -65,6 +65,8 @@
     WEBCORE_EXPORT Optional<PasteboardItemInfo> informationForItemAtIndex(size_t index, int64_t changeCount);
     WEBCORE_EXPORT Optional<Vector<PasteboardItemInfo>> allPasteboardItemInfo(int64_t changeCount);
 
+    WEBCORE_EXPORT static void performAsDataOwner(DataOwnerType, Function<void()>&&);
+
     enum class IncludeImageTypes : bool { No, Yes };
     static String platformPasteboardTypeForSafeTypeForDOMToReadAndWrite(const String& domType, IncludeImageTypes = IncludeImageTypes::No);
 
@@ -126,6 +128,4 @@
 #endif
 };
 
-}
-
-#endif // !PlatformPasteboard_h
+} // namespace WebCore

Modified: trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm (273183 => 273184)


--- trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/platform/ios/PlatformPasteboardIOS.mm	2021-02-20 00:51:03 UTC (rev 273184)
@@ -86,6 +86,34 @@
     return nullptr;
 }
 
+void PlatformPasteboard::performAsDataOwner(DataOwnerType type, Function<void()>&& actions)
+{
+#if HAVE(PASTEBOARD_DATA_OWNER)
+    auto dataOwner = _UIDataOwnerUndefined;
+    switch (type) {
+    case DataOwnerType::Undefined:
+        dataOwner = _UIDataOwnerUndefined;
+        break;
+    case DataOwnerType::User:
+        dataOwner = _UIDataOwnerUser;
+        break;
+    case DataOwnerType::Enterprise:
+        dataOwner = _UIDataOwnerEnterprise;
+        break;
+    case DataOwnerType::Shared:
+        dataOwner = _UIDataOwnerShared;
+        break;
+    }
+
+    [PAL::getUIPasteboardClass() _performAsDataOwner:dataOwner block:^{
+        actions();
+    }];
+#else
+    UNUSED_PARAM(type);
+    actions();
+#endif
+}
+
 void PlatformPasteboard::getPathnamesForType(Vector<String>&, const String&) const
 {
 }

Modified: trunk/Source/WebCore/platform/libwpe/PlatformPasteboardLibWPE.cpp (273183 => 273184)


--- trunk/Source/WebCore/platform/libwpe/PlatformPasteboardLibWPE.cpp	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/platform/libwpe/PlatformPasteboardLibWPE.cpp	2021-02-20 00:51:03 UTC (rev 273184)
@@ -47,6 +47,11 @@
     ASSERT(m_pasteboard);
 }
 
+void PlatformPasteboard::performAsDataOwner(DataOwnerType, Function<void()>&& actions)
+{
+    actions();
+}
+
 void PlatformPasteboard::getTypes(Vector<String>& types)
 {
     struct wpe_pasteboard_string_vector pasteboardTypes = { nullptr, 0 };

Modified: trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm (273183 => 273184)


--- trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebCore/platform/mac/PlatformPasteboardMac.mm	2021-02-20 00:51:03 UTC (rev 273184)
@@ -52,6 +52,11 @@
     return [(__bridge NSString *)cfString.get() lengthOfBytesUsingEncoding:NSString.defaultCStringEncoding];
 }
 
+void PlatformPasteboard::performAsDataOwner(DataOwnerType, Function<void()>&& actions)
+{
+    actions();
+}
+
 PlatformPasteboard::PlatformPasteboard(const String& pasteboardName)
     : m_pasteboard([NSPasteboard pasteboardWithName:pasteboardName])
 {

Modified: trunk/Source/WebKit/ChangeLog (273183 => 273184)


--- trunk/Source/WebKit/ChangeLog	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/ChangeLog	2021-02-20 00:51:03 UTC (rev 273184)
@@ -1,3 +1,84 @@
+2021-02-19  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Specify a _UIDataOwner when reading or writing from the system pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=222072
+        <rdar://problem/74208576>
+
+        Reviewed by Devin Rousso.
+
+        Adds WebKit2 support for tagging `PlatformPasteboard` with the content view's pasteboard data owner type. See
+        below for more details.
+
+        * Platform/spi/ios/UIKitSPI.h:
+
+        Import `UIPasteboard_Private.h` so that we know about `+_performAsDataOwner:block:` in the API tests.
+
+        * UIProcess/Cocoa/WebPasteboardProxyCocoa.mm:
+        (WebKit::WebPasteboardProxy::getPasteboardTypes):
+        (WebKit::WebPasteboardProxy::getPasteboardPathnamesForType):
+        (WebKit::WebPasteboardProxy::getPasteboardStringForType):
+        (WebKit::WebPasteboardProxy::getPasteboardStringsForType):
+        (WebKit::WebPasteboardProxy::getPasteboardBufferForType):
+        (WebKit::WebPasteboardProxy::getPasteboardChangeCount):
+        (WebKit::WebPasteboardProxy::getPasteboardColor):
+        (WebKit::WebPasteboardProxy::getPasteboardURL):
+        (WebKit::WebPasteboardProxy::addPasteboardTypes):
+        (WebKit::WebPasteboardProxy::setPasteboardTypes):
+        (WebKit::WebPasteboardProxy::setPasteboardURL):
+        (WebKit::WebPasteboardProxy::setPasteboardColor):
+        (WebKit::WebPasteboardProxy::setPasteboardStringForType):
+        (WebKit::WebPasteboardProxy::containsURLStringSuitableForLoading):
+
+        Make all of these methods use `dataOwner()` with either a `Read` or `Write` pasteboard access intent to grab the
+        data owner type from the view corresponding to the page identifier, and then wrap all pasteboard access within
+        `PlatformPasteboard`'s new `performAsDataOwner` static helper.
+
+        (WebKit::WebPasteboardProxy::urlStringSuitableForLoading):
+        (WebKit::WebPasteboardProxy::setPasteboardBufferForType):
+        (WebKit::WebPasteboardProxy::getNumberOfFiles):
+        (WebKit::WebPasteboardProxy::typesSafeForDOMToReadAndWrite):
+        (WebKit::WebPasteboardProxy::writeCustomData):
+        (WebKit::WebPasteboardProxy::allPasteboardItemInfo):
+        (WebKit::WebPasteboardProxy::informationForItemAtIndex):
+        (WebKit::WebPasteboardProxy::getPasteboardItemsCount):
+        (WebKit::WebPasteboardProxy::readStringFromPasteboard):
+        (WebKit::WebPasteboardProxy::readURLFromPasteboard):
+        (WebKit::WebPasteboardProxy::readBufferFromPasteboard):
+        (WebKit::WebPasteboardProxy::containsStringSafeForDOMToReadForType):
+        (WebKit::WebPasteboardProxy::writeURLToPasteboard):
+        (WebKit::WebPasteboardProxy::writeWebContentToPasteboard):
+        (WebKit::WebPasteboardProxy::writeImageToPasteboard):
+        (WebKit::WebPasteboardProxy::writeStringToPasteboard):
+        (WebKit::WebPasteboardProxy::updateSupportedTypeIdentifiers):
+        (WebKit::WebPasteboardProxy::determineDataOwner const):
+
+        Use the given page identifier in various pasteboard IPC endpoints in `WebPasteboardProxy` to ask `WebPageProxy`
+        for its pasteboard data owner type when reading or writing pasteboard data.
+
+        * UIProcess/PageClient.h:
+
+        Add a client hook to return a `DataOwnerType` enum, given a `PasteboardAccessIntent` -- that is, copy (write) or
+        paste (read).
+
+        (WebKit::PageClient::dataOwnerForPasteboard const):
+        * UIProcess/PasteboardAccessIntent.h: Added.
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::dataOwnerForPasteboard const):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPasteboardProxy.h:
+        * UIProcess/WebPasteboardProxy.messages.in:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::dataOwnerForPasteboard const):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (coreDataOwnerType):
+        (-[WKContentView _dataOwnerForPasteboard:]):
+
+        Return `-_dataOwnerForPaste` or `-_dataOwnerForCopy` (depending on the `PasteboardAccessIntent`).
+
+        * WebKit.xcodeproj/project.pbxproj:
+
 2021-02-19  Chris Dumez  <cdu...@apple.com>
 
         Make format of release logging more consistent to facilitate grepping

Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (273183 => 273184)


--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -54,6 +54,7 @@
 #import <UIKit/UIKeyboard_Private.h>
 #import <UIKit/UILongPressGestureRecognizer_Private.h>
 #import <UIKit/UIMenuController_Private.h>
+#import <UIKit/UIPasteboard_Private.h>
 #import <UIKit/UIPeripheralHost.h>
 #import <UIKit/UIPeripheralHost_Private.h>
 #import <UIKit/UIPickerContentView_Private.h>

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebPasteboardProxyCocoa.mm	2021-02-20 00:51:03 UTC (rev 273184)
@@ -27,6 +27,7 @@
 #import "WebPasteboardProxy.h"
 
 #import "Connection.h"
+#import "PasteboardAccessIntent.h"
 #import "SandboxExtension.h"
 #import "WebPageProxy.h"
 #import "WebPreferences.h"
@@ -33,6 +34,7 @@
 #import "WebProcessMessages.h"
 #import "WebProcessProxy.h"
 #import <WebCore/Color.h>
+#import <WebCore/DataOwnerType.h>
 #import <WebCore/Pasteboard.h>
 #import <WebCore/PasteboardItemInfo.h>
 #import <WebCore/PlatformPasteboard.h>
@@ -142,9 +144,14 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler({ });
 
-    Vector<String> pasteboardTypes;
-    PlatformPasteboard(pasteboardName).getTypes(pasteboardTypes);
-    completionHandler(WTFMove(pasteboardTypes));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        Vector<String> pasteboardTypes;
+        PlatformPasteboard(pasteboardName).getTypes(pasteboardTypes);
+        completionHandler(WTFMove(pasteboardTypes));
+    });
 }
 
 void WebPasteboardProxy::getPasteboardPathnamesForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, Optional<PageIdentifier> pageID,
@@ -156,23 +163,27 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler({ }, { });
 
-    Vector<String> pathnames;
-    SandboxExtension::HandleArray sandboxExtensions;
-    if (webProcessProxyForConnection(connection)) {
-        PlatformPasteboard(pasteboardName).getPathnamesForType(pathnames, pasteboardType);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }, { }));
 
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        Vector<String> pathnames;
+        SandboxExtension::HandleArray sandboxExtensions;
+        if (webProcessProxyForConnection(connection)) {
+            PlatformPasteboard(pasteboardName).getPathnamesForType(pathnames, pasteboardType);
 #if PLATFORM(MAC)
-        // On iOS, files are copied into app's container upon paste.
-        sandboxExtensions.allocate(pathnames.size());
-        for (size_t i = 0; i < pathnames.size(); i++) {
-            auto& filename = pathnames[i];
-            if (![[NSFileManager defaultManager] fileExistsAtPath:filename])
-                continue;
-            SandboxExtension::createHandle(filename, SandboxExtension::Type::ReadOnly, sandboxExtensions[i]);
+            // On iOS, files are copied into app's container upon paste.
+            sandboxExtensions.allocate(pathnames.size());
+            for (size_t i = 0; i < pathnames.size(); i++) {
+                auto& filename = pathnames[i];
+                if (![[NSFileManager defaultManager] fileExistsAtPath:filename])
+                    continue;
+                SandboxExtension::createHandle(filename, SandboxExtension::Type::ReadOnly, sandboxExtensions[i]);
+            }
+#endif
         }
-#endif
-    }
-    completionHandler(WTFMove(pathnames), WTFMove(sandboxExtensions));
+        completionHandler(WTFMove(pathnames), WTFMove(sandboxExtensions));
+    });
 }
 
 void WebPasteboardProxy::getPasteboardStringForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, Optional<PageIdentifier> pageID, CompletionHandler<void(String&&)>&& completionHandler)
@@ -182,7 +193,12 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ });
 
-    completionHandler(PlatformPasteboard(pasteboardName).stringForType(pasteboardType));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).stringForType(pasteboardType));
+    });
 }
 
 void WebPasteboardProxy::getPasteboardStringsForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, Optional<PageIdentifier> pageID, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
@@ -192,7 +208,12 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ });
 
-    completionHandler(PlatformPasteboard(pasteboardName).allStringsForType(pasteboardType));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).allStringsForType(pasteboardType));
+    });
 }
 
 void WebPasteboardProxy::getPasteboardBufferForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, Optional<PageIdentifier> pageID, CompletionHandler<void(SharedMemory::IPCHandle&&)>&& completionHandler)
@@ -202,25 +223,37 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ });
 
-    RefPtr<SharedBuffer> buffer = PlatformPasteboard(pasteboardName).bufferForType(pasteboardType);
-    if (!buffer)
-        return completionHandler({ });
-    uint64_t size = buffer->size();
-    if (!size)
-        return completionHandler({ });
-    RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(size);
-    if (!sharedMemoryBuffer)
-        return completionHandler({ });
-    memcpy(sharedMemoryBuffer->data(), buffer->data(), size);
-    SharedMemory::Handle handle;
-    if (!sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly))
-        return completionHandler({ });
-    completionHandler(SharedMemory::IPCHandle { WTFMove(handle), size });
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto buffer = PlatformPasteboard(pasteboardName).bufferForType(pasteboardType);
+        if (!buffer)
+            return completionHandler({ });
+        uint64_t size = buffer->size();
+        if (!size)
+            return completionHandler({ });
+        RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(size);
+        if (!sharedMemoryBuffer)
+            return completionHandler({ });
+        memcpy(sharedMemoryBuffer->data(), buffer->data(), size);
+        SharedMemory::Handle handle;
+        if (!sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly))
+            return completionHandler({ });
+        completionHandler(SharedMemory::IPCHandle { WTFMove(handle), size });
+    });
 }
 
-void WebPasteboardProxy::getPasteboardChangeCount(const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
+void WebPasteboardProxy::getPasteboardChangeCount(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
 {
-    completionHandler(PlatformPasteboard(pasteboardName).changeCount());
+    MESSAGE_CHECK_COMPLETION(!pasteboardName.isEmpty(), completionHandler(0));
+
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).changeCount());
+    });
 }
 
 void WebPasteboardProxy::getPasteboardColor(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(WebCore::Color&&)>&& completionHandler)
@@ -228,7 +261,12 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ });
 
-    completionHandler(PlatformPasteboard(pasteboardName).color());
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).color());
+    });
 }
 
 void WebPasteboardProxy::getPasteboardURL(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(const String&)>&& completionHandler)
@@ -236,7 +274,12 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ });
 
-    completionHandler(PlatformPasteboard(pasteboardName).url().string());
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).url().string());
+    });
 }
 
 void WebPasteboardProxy::addPasteboardTypes(IPC::Connection& connection, const String& pasteboardName, const Vector<String>& pasteboardTypes, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
@@ -246,10 +289,15 @@
     for (auto& type : pasteboardTypes)
         MESSAGE_CHECK_COMPLETION(!type.isEmpty(), completionHandler(0));
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    auto newChangeCount = PlatformPasteboard(pasteboardName).addTypes(pasteboardTypes);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, previousChangeCount);
-    completionHandler(newChangeCount);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        auto newChangeCount = PlatformPasteboard(pasteboardName).addTypes(pasteboardTypes);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
+        completionHandler(newChangeCount);
+    });
 }
 
 void WebPasteboardProxy::setPasteboardTypes(IPC::Connection& connection, const String& pasteboardName, const Vector<String>& pasteboardTypes, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
@@ -259,10 +307,15 @@
     for (auto& type : pasteboardTypes)
         MESSAGE_CHECK_COMPLETION(!type.isEmpty(), completionHandler(0));
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    auto newChangeCount = PlatformPasteboard(pasteboardName).setTypes(pasteboardTypes);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
-    completionHandler(newChangeCount);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        auto newChangeCount = PlatformPasteboard(pasteboardName).setTypes(pasteboardTypes);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
+        completionHandler(newChangeCount);
+    });
 }
 
 void WebPasteboardProxy::setPasteboardURL(IPC::Connection& connection, const PasteboardURL& pasteboardURL, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
@@ -269,19 +322,24 @@
 {
     MESSAGE_CHECK_COMPLETION(!pasteboardName.isEmpty(), completionHandler(0));
 
-    if (auto* webProcessProxy = webProcessProxyForConnection(connection)) {
-        if (!pasteboardURL.url.isValid())
-            return completionHandler(0);
+    auto* process = webProcessProxyForConnection(connection);
+    MESSAGE_CHECK_COMPLETION(process, completionHandler(0));
 
-        if (!webProcessProxy->checkURLReceivedFromWebProcess(pasteboardURL.url.string(), CheckBackForwardList::No))
-            return completionHandler(0);
+    if (!pasteboardURL.url.isValid())
+        return completionHandler(0);
 
+    if (!process->checkURLReceivedFromWebProcess(pasteboardURL.url.string(), CheckBackForwardList::No))
+        return completionHandler(0);
+
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
         auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
         auto newChangeCount = PlatformPasteboard(pasteboardName).setURL(pasteboardURL);
         didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
-        return completionHandler(newChangeCount);
-    }
-    completionHandler(0);
+        completionHandler(newChangeCount);
+    });
 }
 
 void WebPasteboardProxy::setPasteboardColor(IPC::Connection& connection, const String& pasteboardName, const WebCore::Color& color, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
@@ -288,10 +346,15 @@
 {
     MESSAGE_CHECK_COMPLETION(!pasteboardName.isEmpty(), completionHandler(0));
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    auto newChangeCount = PlatformPasteboard(pasteboardName).setColor(color);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
-    completionHandler(newChangeCount);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        auto newChangeCount = PlatformPasteboard(pasteboardName).setColor(color);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
+        completionHandler(newChangeCount);
+    });
 }
 
 void WebPasteboardProxy::setPasteboardStringForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, const String& string, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
@@ -299,10 +362,15 @@
     MESSAGE_CHECK_COMPLETION(!pasteboardName.isEmpty(), completionHandler(0));
     MESSAGE_CHECK_COMPLETION(!pasteboardType.isEmpty(), completionHandler(0));
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    auto newChangeCount = PlatformPasteboard(pasteboardName).setStringForType(string, pasteboardType);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
-    completionHandler(newChangeCount);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        auto newChangeCount = PlatformPasteboard(pasteboardName).setStringForType(string, pasteboardType);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
+        completionHandler(newChangeCount);
+    });
 }
 
 void WebPasteboardProxy::containsURLStringSuitableForLoading(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(bool)>&& completionHandler)
@@ -310,7 +378,12 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler(false);
 
-    completionHandler(PlatformPasteboard(pasteboardName).containsURLStringSuitableForLoading());
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(false));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).containsURLStringSuitableForLoading());
+    });
 }
 
 void WebPasteboardProxy::urlStringSuitableForLoading(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(String&& url, String&& title)>&& completionHandler)
@@ -318,9 +391,14 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ }, { });
 
-    String title;
-    auto urlString = PlatformPasteboard(pasteboardName).urlStringSuitableForLoading(title);
-    completionHandler(WTFMove(urlString), WTFMove(title));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }, { }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        String title;
+        auto urlString = PlatformPasteboard(pasteboardName).urlStringSuitableForLoading(title);
+        completionHandler(WTFMove(urlString), WTFMove(title));
+    });
 }
 
 void WebPasteboardProxy::setPasteboardBufferForType(IPC::Connection& connection, const String& pasteboardName, const String& pasteboardType, const SharedMemory::IPCHandle& ipcHandle, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
@@ -328,20 +406,25 @@
     MESSAGE_CHECK_COMPLETION(!pasteboardName.isEmpty(), completionHandler(0));
     MESSAGE_CHECK_COMPLETION(!pasteboardType.isEmpty(), completionHandler(0));
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    if (ipcHandle.handle.isNull()) {
-        auto newChangeCount = PlatformPasteboard(pasteboardName).setBufferForType(nullptr, pasteboardType);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        if (ipcHandle.handle.isNull()) {
+            auto newChangeCount = PlatformPasteboard(pasteboardName).setBufferForType(nullptr, pasteboardType);
+            didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
+            return completionHandler(newChangeCount);
+        }
+
+        auto sharedMemoryBuffer = SharedMemory::map(ipcHandle.handle, SharedMemory::Protection::ReadOnly);
+        if (!sharedMemoryBuffer)
+            return completionHandler(0);
+        auto buffer = SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), static_cast<size_t>(ipcHandle.dataSize));
+        auto newChangeCount = PlatformPasteboard(pasteboardName).setBufferForType(buffer.ptr(), pasteboardType);
         didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
-        return completionHandler(newChangeCount);
-    }
-
-    RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::map(ipcHandle.handle, SharedMemory::Protection::ReadOnly);
-    if (!sharedMemoryBuffer)
-        return completionHandler(0);
-    auto buffer = SharedBuffer::create(static_cast<unsigned char *>(sharedMemoryBuffer->data()), static_cast<size_t>(ipcHandle.dataSize));
-    auto newChangeCount = PlatformPasteboard(pasteboardName).setBufferForType(buffer.ptr(), pasteboardType);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
-    completionHandler(newChangeCount);
+        completionHandler(newChangeCount);
+    });
 }
 
 void WebPasteboardProxy::getNumberOfFiles(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(uint64_t)>&& completionHandler)
@@ -349,7 +432,12 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler(0);
 
-    completionHandler(PlatformPasteboard(pasteboardName).numberOfFiles());
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).numberOfFiles());
+    });
 }
 
 void WebPasteboardProxy::typesSafeForDOMToReadAndWrite(IPC::Connection& connection, const String& pasteboardName, const String& origin, Optional<PageIdentifier> pageID, CompletionHandler<void(Vector<String>&&)>&& completionHandler)
@@ -359,7 +447,12 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler({ });
 
-    completionHandler(PlatformPasteboard(pasteboardName).typesSafeForDOMToReadAndWrite(origin));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).typesSafeForDOMToReadAndWrite(origin));
+    });
 }
 
 void WebPasteboardProxy::writeCustomData(IPC::Connection& connection, const Vector<PasteboardCustomData>& data, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(int64_t)>&& completionHandler)
@@ -366,10 +459,15 @@
 {
     MESSAGE_CHECK_COMPLETION(!pasteboardName.isEmpty(), completionHandler(0));
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    auto newChangeCount = PlatformPasteboard(pasteboardName).write(data);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
-    completionHandler(newChangeCount);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        auto newChangeCount = PlatformPasteboard(pasteboardName).write(data);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, newChangeCount);
+        completionHandler(newChangeCount);
+    });
 }
 
 void WebPasteboardProxy::allPasteboardItemInfo(IPC::Connection& connection, const String& pasteboardName, int64_t changeCount, Optional<PageIdentifier> pageID, CompletionHandler<void(Optional<Vector<PasteboardItemInfo>>&&)>&& completionHandler)
@@ -377,7 +475,12 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler({ });
 
-    completionHandler(PlatformPasteboard(pasteboardName).allPasteboardItemInfo(changeCount));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).allPasteboardItemInfo(changeCount));
+    });
 }
 
 void WebPasteboardProxy::informationForItemAtIndex(IPC::Connection& connection, size_t index, const String& pasteboardName, int64_t changeCount, Optional<PageIdentifier> pageID, CompletionHandler<void(Optional<PasteboardItemInfo>&&)>&& completionHandler)
@@ -385,7 +488,12 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler(WTF::nullopt);
 
-    completionHandler(PlatformPasteboard(pasteboardName).informationForItemAtIndex(index, changeCount));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(WTF::nullopt));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).informationForItemAtIndex(index, changeCount));
+    });
 }
 
 void WebPasteboardProxy::getPasteboardItemsCount(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(uint64_t)>&& completionHandler)
@@ -393,7 +501,12 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler(0);
 
-    completionHandler(PlatformPasteboard(pasteboardName).count());
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(0));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).count());
+    });
 }
 
 void WebPasteboardProxy::readStringFromPasteboard(IPC::Connection& connection, size_t index, const String& pasteboardType, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(String&&)>&& completionHandler)
@@ -403,7 +516,12 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ });
 
-    completionHandler(PlatformPasteboard(pasteboardName).readString(index, pasteboardType));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).readString(index, pasteboardType));
+    });
 }
 
 void WebPasteboardProxy::readURLFromPasteboard(IPC::Connection& connection, size_t index, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(String&& url, String&& title)>&& completionHandler)
@@ -411,9 +529,14 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ }, { });
 
-    String title;
-    String url = "" title).string();
-    completionHandler(WTFMove(url), WTFMove(title));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }, { }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        String title;
+        String url = "" title).string();
+        completionHandler(WTFMove(url), WTFMove(title));
+    });
 }
 
 void WebPasteboardProxy::readBufferFromPasteboard(IPC::Connection& connection, size_t index, const String& pasteboardType, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(SharedMemory::IPCHandle&&)>&& completionHandler)
@@ -423,20 +546,25 @@
     if (!canAccessPasteboardData(connection, pasteboardName))
         return completionHandler({ });
 
-    RefPtr<SharedBuffer> buffer = PlatformPasteboard(pasteboardName).readBuffer(index, pasteboardType);
-    if (!buffer)
-        return completionHandler({ });
-    uint64_t size = buffer->size();
-    if (!size)
-        return completionHandler({ });
-    RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(size);
-    if (!sharedMemoryBuffer)
-        return completionHandler({ });
-    memcpy(sharedMemoryBuffer->data(), buffer->data(), size);
-    SharedMemory::Handle handle;
-    if (!sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly))
-        return completionHandler({ });
-    completionHandler(SharedMemory::IPCHandle { WTFMove(handle), size });
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler({ }));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto buffer = PlatformPasteboard(pasteboardName).readBuffer(index, pasteboardType);
+        if (!buffer)
+            return completionHandler({ });
+        uint64_t size = buffer->size();
+        if (!size)
+            return completionHandler({ });
+        RefPtr<SharedMemory> sharedMemoryBuffer = SharedMemory::allocate(size);
+        if (!sharedMemoryBuffer)
+            return completionHandler({ });
+        memcpy(sharedMemoryBuffer->data(), buffer->data(), size);
+        SharedMemory::Handle handle;
+        if (!sharedMemoryBuffer->createHandle(handle, SharedMemory::Protection::ReadOnly))
+            return completionHandler({ });
+        completionHandler(SharedMemory::IPCHandle { WTFMove(handle), size });
+    });
 }
 
 void WebPasteboardProxy::containsStringSafeForDOMToReadForType(IPC::Connection& connection, const String& type, const String& pasteboardName, Optional<PageIdentifier> pageID, CompletionHandler<void(bool)>&& completionHandler)
@@ -444,7 +572,12 @@
     if (!canAccessPasteboardTypes(connection, pasteboardName))
         return completionHandler(false);
 
-    completionHandler(PlatformPasteboard(pasteboardName).containsStringSafeForDOMToReadForType(type));
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Read);
+    MESSAGE_CHECK_COMPLETION(dataOwner, completionHandler(false));
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        completionHandler(PlatformPasteboard(pasteboardName).containsStringSafeForDOMToReadForType(type));
+    });
 }
 
 #if PLATFORM(IOS_FAMILY)
@@ -453,11 +586,16 @@
 {
     MESSAGE_CHECK(!pasteboardName.isEmpty());
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    PlatformPasteboard(pasteboardName).write(url);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
-    if (auto process = webProcessProxyForConnection(connection))
-        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK(dataOwner);
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        PlatformPasteboard(pasteboardName).write(url);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+        if (auto process = webProcessProxyForConnection(connection))
+            process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    });
 }
 
 void WebPasteboardProxy::writeWebContentToPasteboard(IPC::Connection& connection, const WebCore::PasteboardWebContent& content, const String& pasteboardName, Optional<PageIdentifier> pageID)
@@ -464,11 +602,16 @@
 {
     MESSAGE_CHECK(!pasteboardName.isEmpty());
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    PlatformPasteboard(pasteboardName).write(content);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
-    if (auto process = webProcessProxyForConnection(connection))
-        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK(dataOwner);
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        PlatformPasteboard(pasteboardName).write(content);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+        if (auto process = webProcessProxyForConnection(connection))
+            process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    });
 }
 
 void WebPasteboardProxy::writeImageToPasteboard(IPC::Connection& connection, const WebCore::PasteboardImage& pasteboardImage, const String& pasteboardName, Optional<PageIdentifier> pageID)
@@ -475,11 +618,16 @@
 {
     MESSAGE_CHECK(!pasteboardName.isEmpty());
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    PlatformPasteboard(pasteboardName).write(pasteboardImage);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
-    if (auto process = webProcessProxyForConnection(connection))
-        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK(dataOwner);
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        PlatformPasteboard(pasteboardName).write(pasteboardImage);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+        if (auto process = webProcessProxyForConnection(connection))
+            process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    });
 }
 
 void WebPasteboardProxy::writeStringToPasteboard(IPC::Connection& connection, const String& pasteboardType, const String& text, const String& pasteboardName, Optional<PageIdentifier> pageID)
@@ -487,14 +635,19 @@
     MESSAGE_CHECK(!pasteboardName.isEmpty());
     MESSAGE_CHECK(!pasteboardType.isEmpty() || text.isEmpty());
 
-    auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
-    PlatformPasteboard(pasteboardName).write(pasteboardType, text);
-    didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
-    if (auto process = webProcessProxyForConnection(connection))
-        process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    auto dataOwner = determineDataOwner(connection, pasteboardName, pageID, PasteboardAccessIntent::Write);
+    MESSAGE_CHECK(dataOwner);
+
+    PlatformPasteboard::performAsDataOwner(*dataOwner, [&] {
+        auto previousChangeCount = PlatformPasteboard(pasteboardName).changeCount();
+        PlatformPasteboard(pasteboardName).write(pasteboardType, text);
+        didModifyContentsOfPasteboard(connection, pasteboardName, previousChangeCount, PlatformPasteboard(pasteboardName).changeCount());
+        if (auto process = webProcessProxyForConnection(connection))
+            process->send(Messages::WebProcess::DidWriteToPasteboardAsynchronously(pasteboardName), 0);
+    });
 }
 
-void WebPasteboardProxy::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName, Optional<PageIdentifier> pageID)
+void WebPasteboardProxy::updateSupportedTypeIdentifiers(const Vector<String>& identifiers, const String& pasteboardName, Optional<PageIdentifier>)
 {
     PlatformPasteboard(pasteboardName).updateSupportedTypeIdentifiers(identifiers);
 }
@@ -501,6 +654,34 @@
 
 #endif // PLATFORM(IOS_FAMILY)
 
+Optional<DataOwnerType> WebPasteboardProxy::determineDataOwner(IPC::Connection& connection, const String& pasteboardName, Optional<PageIdentifier> pageID, PasteboardAccessIntent intent) const
+{
+    MESSAGE_CHECK_WITH_RETURN_VALUE(!pasteboardName.isEmpty(), WTF::nullopt);
+
+    auto* process = webProcessProxyForConnection(connection);
+    MESSAGE_CHECK_WITH_RETURN_VALUE(process, WTF::nullopt);
+
+    if (!pageID)
+        return DataOwnerType::Undefined;
+
+#if HAVE(PASTEBOARD_DATA_OWNER)
+    Optional<DataOwnerType> result;
+    for (auto* page : process->pages()) {
+        if (page->webPageID() == *pageID) {
+            result = page->dataOwnerForPasteboard(intent);
+            break;
+        }
+    }
+    // If this message check is hit, then the incoming web page ID doesn't correspond to any page
+    // currently known to the UI process.
+    MESSAGE_CHECK_WITH_RETURN_VALUE(result.hasValue(), WTF::nullopt);
+    return result;
+#else
+    UNUSED_PARAM(intent);
+    return DataOwnerType::Undefined;
+#endif
+}
+
 void WebPasteboardProxy::PasteboardAccessInformation::grantAccess(WebProcessProxy& process, PasteboardAccessType type)
 {
     auto matchIndex = processes.findMatching([&](auto& processAndType) {

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -28,6 +28,7 @@
 #include "DataReference.h"
 #include "LayerTreeContext.h"
 #include "PDFPluginIdentifier.h"
+#include "PasteboardAccessIntent.h"
 #include "SameDocumentNavigationType.h"
 #include "ShareableBitmap.h"
 #include "WebColorPicker.h"
@@ -38,6 +39,7 @@
 #include <WebCore/AlternativeTextClient.h>
 #include <WebCore/ContactInfo.h>
 #include <WebCore/ContactsRequestData.h>
+#include <WebCore/DataOwnerType.h>
 #include <WebCore/DragActions.h>
 #include <WebCore/EditorClient.h>
 #include <WebCore/FocusDirection.h>
@@ -517,6 +519,10 @@
 
     virtual void setHasBlankOverlay(bool) { }
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+    virtual WebCore::DataOwnerType dataOwnerForPasteboard(PasteboardAccessIntent) const { return WebCore::DataOwnerType::Undefined; }
+#endif
+
 #if ENABLE(IMAGE_EXTRACTION)
     virtual void requestImageExtraction(const ShareableBitmap::Handle&, CompletionHandler<void(WebCore::ImageExtractionResult&&)>&& completion) { completion({ }); }
 #endif

Added: trunk/Source/WebKit/UIProcess/PasteboardAccessIntent.h (0 => 273184)


--- trunk/Source/WebKit/UIProcess/PasteboardAccessIntent.h	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/PasteboardAccessIntent.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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
+
+namespace WebKit {
+
+enum class PasteboardAccessIntent : bool {
+    Read,
+    Write,
+};
+
+} // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-02-20 00:51:03 UTC (rev 273184)
@@ -9621,6 +9621,15 @@
 }
 #endif
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+
+DataOwnerType WebPageProxy::dataOwnerForPasteboard(PasteboardAccessIntent intent) const
+{
+    return pageClient().dataOwnerForPasteboard(intent);
+}
+
+#endif
+
 #if ENABLE(ATTACHMENT_ELEMENT)
 
 void WebPageProxy::writePromisedAttachmentToPasteboard(WebCore::PromisedAttachmentInfo&& info)

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -45,6 +45,7 @@
 #include "NotificationPermissionRequestManagerProxy.h"
 #include "PDFPluginIdentifier.h"
 #include "PageLoadState.h"
+#include "PasteboardAccessIntent.h"
 #include "PluginProcessAttributes.h"
 #include "PolicyDecision.h"
 #include "ProcessTerminationReason.h"
@@ -285,6 +286,10 @@
 struct ImageExtractionResult;
 #endif
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+enum class DataOwnerType : uint8_t;
+#endif
+
 template<typename> class RectEdges;
 using FloatBoxExtent = RectEdges<float>;
 }
@@ -1079,6 +1084,10 @@
     bool useDarkAppearance() const;
     bool useElevatedUserInterfaceLevel() const;
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+    WebCore::DataOwnerType dataOwnerForPasteboard(PasteboardAccessIntent) const;
+#endif
+
 #if PLATFORM(COCOA)
     // Called by the web process through a message.
     void registerWebProcessAccessibilityToken(const IPC::DataReference&);

Modified: trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/WebPasteboardProxy.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -41,6 +41,7 @@
 }
 
 namespace WebCore {
+enum class DataOwnerType : uint8_t;
 class Color;
 class PasteboardCustomData;
 class SelectionData;
@@ -52,6 +53,7 @@
 
 namespace WebKit {
 
+enum class PasteboardAccessIntent : bool;
 class WebFrameProxy;
 class WebProcessProxy;
 
@@ -100,7 +102,7 @@
     void getPasteboardStringForType(IPC::Connection&, const String& pasteboardName, const String& pasteboardType, Optional<WebCore::PageIdentifier>, CompletionHandler<void(String&&)>&&);
     void getPasteboardStringsForType(IPC::Connection&, const String& pasteboardName, const String& pasteboardType, Optional<WebCore::PageIdentifier>, CompletionHandler<void(Vector<String>&&)>&&);
     void getPasteboardBufferForType(IPC::Connection&, const String& pasteboardName, const String& pasteboardType, Optional<WebCore::PageIdentifier>, CompletionHandler<void(SharedMemory::IPCHandle&&)>&&);
-    void getPasteboardChangeCount(const String& pasteboardName, Optional<WebCore::PageIdentifier>, CompletionHandler<void(int64_t)>&&);
+    void getPasteboardChangeCount(IPC::Connection&, const String& pasteboardName, Optional<WebCore::PageIdentifier>, CompletionHandler<void(int64_t)>&&);
     void getPasteboardColor(IPC::Connection&, const String& pasteboardName, Optional<WebCore::PageIdentifier>, CompletionHandler<void(WebCore::Color&&)>&&);
     void getPasteboardURL(IPC::Connection&, const String& pasteboardName, Optional<WebCore::PageIdentifier>, CompletionHandler<void(const String&)>&&);
     void addPasteboardTypes(IPC::Connection&, const String& pasteboardName, const Vector<String>& pasteboardTypes, Optional<WebCore::PageIdentifier>, CompletionHandler<void(int64_t)>&&);
@@ -149,6 +151,8 @@
     enum class PasteboardAccessType : uint8_t { Types, TypesAndData };
     Optional<PasteboardAccessType> accessType(IPC::Connection&, const String& pasteboardName) const;
     void grantAccess(WebProcessProxy&, const String& pasteboardName, PasteboardAccessType);
+
+    Optional<WebCore::DataOwnerType> determineDataOwner(IPC::Connection&, const String& pasteboardName, Optional<WebCore::PageIdentifier>, PasteboardAccessIntent) const;
 #endif
 
     WebProcessProxyList m_webProcessProxyList;

Modified: trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/WebPasteboardProxy.messages.in	2021-02-20 00:51:03 UTC (rev 273184)
@@ -47,7 +47,7 @@
     GetPasteboardStringForType(String pasteboardName, String pasteboardType, Optional<WebCore::PageIdentifier> pageID) -> (String string) Synchronous WantsConnection
     GetPasteboardStringsForType(String pasteboardName, String pasteboardType, Optional<WebCore::PageIdentifier> pageID) -> (Vector<String> strings) Synchronous WantsConnection
     GetPasteboardBufferForType(String pasteboardName, String pasteboardType, Optional<WebCore::PageIdentifier> pageID) -> (WebKit::SharedMemory::IPCHandle handle) Synchronous WantsConnection
-    GetPasteboardChangeCount(String pasteboardName, Optional<WebCore::PageIdentifier> pageID) -> (int64_t changeCount) Synchronous
+    GetPasteboardChangeCount(String pasteboardName, Optional<WebCore::PageIdentifier> pageID) -> (int64_t changeCount) Synchronous WantsConnection
     GetPasteboardColor(String pasteboardName, Optional<WebCore::PageIdentifier> pageID) -> (WebCore::Color color) Synchronous WantsConnection
     GetPasteboardURL(String pasteboardName, Optional<WebCore::PageIdentifier> pageID) -> (String urlString) Synchronous WantsConnection
     AddPasteboardTypes(String pasteboardName, Vector<String> pasteboardTypes, Optional<WebCore::PageIdentifier> pageID) -> (int64_t changeCount) Synchronous WantsConnection

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -126,6 +126,10 @@
     RefPtr<WebDataListSuggestionsDropdown> createDataListSuggestionsDropdown(WebPageProxy&) final;
 #endif
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+    WebCore::DataOwnerType dataOwnerForPasteboard(PasteboardAccessIntent) const final;
+#endif
+
 #if ENABLE(DATE_AND_TIME_INPUT_TYPES)
     RefPtr<WebDateTimePicker> createDateTimePicker(WebPageProxy&) final;
 #endif

Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm	2021-02-20 00:51:03 UTC (rev 273184)
@@ -459,6 +459,15 @@
 
 #endif // ENABLE(IOS_TOUCH_EVENTS)
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+
+WebCore::DataOwnerType PageClientImpl::dataOwnerForPasteboard(PasteboardAccessIntent intent) const
+{
+    return [m_contentView _dataOwnerForPasteboard:intent];
+}
+
+#endif
+
 RefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy&)
 {
     return nullptr;

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -37,6 +37,7 @@
 #import "FrameInfoData.h"
 #import "GestureTypes.h"
 #import "InteractionInformationAtPosition.h"
+#import "PasteboardAccessIntent.h"
 #import "SyntheticEditingCommandType.h"
 #import "TextCheckingController.h"
 #import "TransactionID.h"
@@ -57,6 +58,7 @@
 #import <UIKit/UIView.h>
 #import <WebCore/ActivityState.h>
 #import <WebCore/Color.h>
+#import <WebCore/DataOwnerType.h>
 #import <WebCore/FloatQuad.h>
 #import <WebCore/MediaControlsContextMenuItem.h>
 #import <WebCore/PointerID.h>
@@ -700,6 +702,10 @@
 - (BOOL)_formControlRefreshEnabled;
 #endif
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+- (WebCore::DataOwnerType)_dataOwnerForPasteboard:(WebKit::PasteboardAccessIntent)intent;
+#endif
+
 @end
 
 @interface WKContentView (WKTesting)

Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (273183 => 273184)


--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm	2021-02-20 00:51:03 UTC (rev 273184)
@@ -7468,6 +7468,38 @@
     return WebCore::IOSApplication::isDataActivation();
 }
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+
+static WebCore::DataOwnerType coreDataOwnerType(_UIDataOwner platformType)
+{
+    switch (platformType) {
+    case _UIDataOwnerUser:
+        return WebCore::DataOwnerType::User;
+    case _UIDataOwnerEnterprise:
+        return WebCore::DataOwnerType::Enterprise;
+    case _UIDataOwnerShared:
+        return WebCore::DataOwnerType::Shared;
+    case _UIDataOwnerUndefined:
+        return WebCore::DataOwnerType::Undefined;
+    }
+    ASSERT_NOT_REACHED();
+    return WebCore::DataOwnerType::Undefined;
+}
+
+- (WebCore::DataOwnerType)_dataOwnerForPasteboard:(WebKit::PasteboardAccessIntent)intent
+{
+    if (intent == WebKit::PasteboardAccessIntent::Read)
+        return coreDataOwnerType(self._dataOwnerForPaste);
+
+    if (intent == WebKit::PasteboardAccessIntent::Write)
+        return coreDataOwnerType(self._dataOwnerForCopy);
+
+    ASSERT_NOT_REACHED();
+    return WebCore::DataOwnerType::Undefined;
+}
+
+#endif // HAVE(PASTEBOARD_DATA_OWNER)
+
 - (RetainPtr<UIView>)_createPreviewContainerWithLayerName:(NSString *)layerName
 {
     auto container = adoptNS([[UIView alloc] init]);

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (273183 => 273184)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-02-20 00:51:03 UTC (rev 273184)
@@ -1995,6 +1995,7 @@
 		F44291961FA5942A002CC93E /* _WKAttachmentInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = F44291951FA5942A002CC93E /* _WKAttachmentInternal.h */; };
 		F44815642387820000982657 /* WKDeferringGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = F44815622387820000982657 /* WKDeferringGestureRecognizer.h */; };
 		F44DFEB21E9E752F0038D196 /* WebIconUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */; };
+		F4660BC225DEF08100E86598 /* PasteboardAccessIntent.h in Headers */ = {isa = PBXBuildFile; fileRef = F4660BC125DEF08100E86598 /* PasteboardAccessIntent.h */; };
 		F48D2A8521583A7E00C6752B /* AppKitSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = F48D2A8421583A0200C6752B /* AppKitSPI.h */; };
 		F496A4311F58A272004C1757 /* DragDropInteractionState.h in Headers */ = {isa = PBXBuildFile; fileRef = F496A42F1F58A272004C1757 /* DragDropInteractionState.h */; };
 		F4A6D6BC254CA3E900B65FAA /* SharedDisplayListHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = F4A6D6BB254CA3E900B65FAA /* SharedDisplayListHandle.h */; };
@@ -5857,6 +5858,7 @@
 		F44815632387820000982657 /* WKDeferringGestureRecognizer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = WKDeferringGestureRecognizer.mm; path = ios/WKDeferringGestureRecognizer.mm; sourceTree = "<group>"; };
 		F44DFEB01E9E752F0038D196 /* WebIconUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebIconUtilities.h; path = ios/WebIconUtilities.h; sourceTree = "<group>"; };
 		F44DFEB11E9E752F0038D196 /* WebIconUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebIconUtilities.mm; path = ios/WebIconUtilities.mm; sourceTree = "<group>"; };
+		F4660BC125DEF08100E86598 /* PasteboardAccessIntent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PasteboardAccessIntent.h; sourceTree = "<group>"; };
 		F48D2A8421583A0200C6752B /* AppKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppKitSPI.h; sourceTree = "<group>"; };
 		F496A42F1F58A272004C1757 /* DragDropInteractionState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DragDropInteractionState.h; path = ios/DragDropInteractionState.h; sourceTree = "<group>"; };
 		F496A4301F58A272004C1757 /* DragDropInteractionState.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = DragDropInteractionState.mm; path = ios/DragDropInteractionState.mm; sourceTree = "<group>"; };
@@ -9750,6 +9752,7 @@
 				BC6EDAA5111271C600E7678B /* PageClient.h */,
 				1AC75379183A9FDA0072CB15 /* PageLoadState.cpp */,
 				1AC7537A183A9FDB0072CB15 /* PageLoadState.h */,
+				F4660BC125DEF08100E86598 /* PasteboardAccessIntent.h */,
 				832ED1891E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.cpp */,
 				832ED18A1E2FE13B006BA64A /* PerActivityStateCPUUsageSampler.h */,
 				37716A59195B910500EE8B1B /* ProcessAssertion.cpp */,
@@ -11889,6 +11892,7 @@
 				0FCB4E6218BBE3D9000FCFC9 /* PageClientImplMac.h in Headers */,
 				1AC7537C183A9FDB0072CB15 /* PageLoadState.h in Headers */,
 				1A8B66B01BC43C860082DF77 /* PageLoadStateObserver.h in Headers */,
+				F4660BC225DEF08100E86598 /* PasteboardAccessIntent.h in Headers */,
 				C574A58112E66681002DFE98 /* PasteboardTypes.h in Headers */,
 				A1798B512230A10E000764BD /* PaymentAuthorizationController.h in Headers */,
 				A1798B3E222D97A2000764BD /* PaymentAuthorizationPresenter.h in Headers */,

Modified: trunk/Tools/ChangeLog (273183 => 273184)


--- trunk/Tools/ChangeLog	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Tools/ChangeLog	2021-02-20 00:51:03 UTC (rev 273184)
@@ -1,3 +1,23 @@
+2021-02-19  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS] Specify a _UIDataOwner when reading or writing from the system pasteboard
+        https://bugs.webkit.org/show_bug.cgi?id=222072
+        <rdar://problem/74208576>
+
+        Reviewed by Devin Rousso.
+
+        Add a couple of new API tests to verify that `+[UIPasteboard _performAsDataOwner:block:]` is invoked with the
+        expected data owner type when copying and pasting.
+
+        * TestWebKitAPI/Tests/ios/UIPasteboardTests.mm:
+        (+[TestUIPasteboard _performAsDataOwner:block:]):
+        (TestWebKitAPI::TEST):
+        * TestWebKitAPI/cocoa/TestWKWebView.h:
+        * TestWebKitAPI/cocoa/TestWKWebView.mm:
+        (-[WKWebView contentsAsString]):
+
+        Additionally add a helper method to grab a `WKWebView`'s contents as an `NSString`, just for convenience.
+
 2021-02-19  Alex Christensen  <achristen...@webkit.org>
 
         NSError returned by WebKit API should actually conform to NSSecureCoding

Modified: trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm (273183 => 273184)


--- trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Tools/TestWebKitAPI/Tests/ios/UIPasteboardTests.mm	2021-02-20 00:51:03 UTC (rev 273184)
@@ -27,6 +27,7 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+#import "ClassMethodSwizzler.h"
 #import "PlatformUtilities.h"
 #import "TestWKWebView.h"
 #import "UIKitSPI.h"
@@ -48,6 +49,26 @@
         NSLog(@"Expected JSON: %@ to match values: %@", jsonString, expected);
 }
 
+#if HAVE(PASTEBOARD_DATA_OWNER)
+
+static _UIDataOwner gLastKnownDataOwner = _UIDataOwnerUndefined;
+
+@interface TestUIPasteboard : NSObject
++ (void)_performAsDataOwner:(_UIDataOwner)owner block:(dispatch_block_t)block;
+@end
+
+@implementation TestUIPasteboard
+
++ (void)_performAsDataOwner:(_UIDataOwner)owner block:(dispatch_block_t)block
+{
+    block();
+    gLastKnownDataOwner = owner;
+}
+
+@end
+
+#endif // HAVE(PASTEBOARD_DATA_OWNER)
+
 #endif // PLATFORM(IOS)
 
 namespace TestWebKitAPI {
@@ -348,6 +369,50 @@
     EXPECT_WK_STREQ("0", [webView stringByEvaluatingJavaScript:@"document.querySelector('img').width"]);
     EXPECT_WK_STREQ("174", [webView stringByEvaluatingJavaScript:@"document.querySelector('img').height"]);
 }
+
+#if HAVE(PASTEBOARD_DATA_OWNER)
+
+TEST(UIPasteboardTests, PerformAsDataOwnerWhenCopying)
+{
+    auto swizzler = ClassMethodSwizzler {
+        UIPasteboard.class,
+        @selector(_performAsDataOwner:block:),
+        [TestUIPasteboard methodForSelector:@selector(_performAsDataOwner:block:)]
+    };
+
+    auto webView = setUpWebViewForPasteboardTests(@"simple");
+    [webView _setDataOwnerForCopy:_UIDataOwnerShared];
+    [webView _setDataOwnerForPaste:_UIDataOwnerEnterprise];
+    [webView selectAll:nil];
+    [webView copy:nil];
+    [webView waitForNextPresentationUpdate];
+
+    EXPECT_EQ(gLastKnownDataOwner, _UIDataOwnerShared);
+    EXPECT_WK_STREQ(UIPasteboard.generalPasteboard.string, "Simple HTML file.");
+}
+
+TEST(UIPasteboardTests, PerformAsDataOwnerWhenPasting)
+{
+    auto swizzler = ClassMethodSwizzler {
+        UIPasteboard.class,
+        @selector(_performAsDataOwner:block:),
+        [TestUIPasteboard methodForSelector:@selector(_performAsDataOwner:block:)]
+    };
+
+    auto webView = setUpWebViewForPasteboardTests(@"autofocus-contenteditable");
+    [webView _setDataOwnerForCopy:_UIDataOwnerShared];
+    [webView _setDataOwnerForPaste:_UIDataOwnerEnterprise];
+
+    UIPasteboard.generalPasteboard.string = @"Foo bar";
+    [webView paste:nil];
+    [webView waitForNextPresentationUpdate];
+
+    EXPECT_EQ(gLastKnownDataOwner, _UIDataOwnerEnterprise);
+    EXPECT_WK_STREQ([webView contentsAsString], "Foo bar\n");
+}
+
+#endif // HAVE(PASTEBOARD_DATA_OWNER)
+
 #endif // PLATFORM(IOS)
 
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h (273183 => 273184)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h	2021-02-20 00:51:03 UTC (rev 273184)
@@ -48,6 +48,7 @@
 @end
 
 @interface WKWebView (TestWebKitAPI)
+@property (nonatomic, readonly) NSString *contentsAsString;
 @property (nonatomic, readonly) NSArray<NSString *> *tagsInBody;
 - (void)loadTestPageNamed:(NSString *)pageName;
 - (void)synchronouslyGoBack;

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm (273183 => 273184)


--- trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2021-02-20 00:46:44 UTC (rev 273183)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm	2021-02-20 00:51:03 UTC (rev 273184)
@@ -130,6 +130,18 @@
     return success;
 }
 
+- (NSString *)contentsAsString
+{
+    __block bool done = false;
+    __block RetainPtr<NSString> result;
+    [self _getContentsAsStringWithCompletionHandler:^(NSString *contents, NSError *error) {
+        result = contents;
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    return result.autorelease();
+}
+
 - (NSArray<NSString *> *)tagsInBody
 {
     return [self objectByEvaluatingJavaScript:@"Array.from(document.body.getElementsByTagName('*')).map(e => e.tagName)"];
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to