Skip to content

Commit

Permalink
Pass frameID along to grantAccessToCurrentPasteboardData
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=273575
rdar://127383912

Reviewed by Sihui Liu.

We need to start passing along frame info whenever granting access to pasteboard
data because under site isolation, a frame may have a different process than the
main frame. This is nessesary to work towards drag and drop.

This change also gets paste in a site isolated iframe working. We currently change
the process to grant pasteboard only in the no callback executeEditCommand case, as that
is what paste uses and already sends a message to the focused or main frame.

Added API test for paste.

* Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm:
(WebKit::WebPageProxy::grantAccessToCurrentPasteboardData):
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::executeEditCommand):
(WebKit::WebPageProxy::performDragOperation):
(WebKit::WebPageProxy::willPerformPasteCommand):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _handleDOMPasteRequestWithResult:]):
* Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::willPerformPasteCommand):
* Source/WebKit/UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::platformDidSelectItemFromActiveContextMenu):
(WebKit::WebPageProxy::willPerformPasteCommand):
* Source/WebKit/UIProcess/mac/WebViewImpl.mm:
(WebKit::WebViewImpl::requestDOMPasteAccess):
(WebKit::WebViewImpl::handleDOMPasteRequestForCategoryWithResult):

Canonical link: https://commits.webkit.org/278480@main
  • Loading branch information
Pascoe committed May 7, 2024
1 parent 36dbfb8 commit ba6e612
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 13 deletions.
11 changes: 8 additions & 3 deletions Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,17 @@ static bool exceedsRenderTreeSizeSizeThreshold(uint64_t thresholdSize, uint64_t
m_websiteDataStore->loadRecentSearches(name, WTFMove(completionHandler));
}

void WebPageProxy::grantAccessToCurrentPasteboardData(const String& pasteboardName)
void WebPageProxy::grantAccessToCurrentPasteboardData(const String& pasteboardName, std::optional<FrameIdentifier> frameID)
{
if (!hasRunningProcess())
return;

WebPasteboardProxy::singleton().grantAccessToCurrentData(m_process.get(), pasteboardName);
if (frameID) {
if (auto* frame = WebFrameProxy::webFrame(*frameID)) {
WebPasteboardProxy::singleton().grantAccessToCurrentData(frame->process(), pasteboardName);
return;
}
}
WebPasteboardProxy::singleton().grantAccessToCurrentData(m_process, pasteboardName);
}

void WebPageProxy::beginSafeBrowsingCheck(const URL& url, bool forMainFrameNavigation, WebFramePolicyListenerProxy& listener)
Expand Down
4 changes: 2 additions & 2 deletions Source/WebKit/UIProcess/WebPageProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3103,7 +3103,7 @@ void WebPageProxy::executeEditCommand(const String& commandName, const String& a
return;

if (auto pasteAccessCategory = pasteAccessCategoryForCommand(commandName))
willPerformPasteCommand(*pasteAccessCategory);
willPerformPasteCommand(*pasteAccessCategory, focusedFrame->frameID());

if (commandName == ignoreSpellingCommandName)
++m_pendingLearnOrIgnoreWordMessageCount;
Expand Down Expand Up @@ -13229,7 +13229,7 @@ void WebPageProxy::platformDidSelectItemFromActiveContextMenu(const WebContextMe

#if !PLATFORM(COCOA)

void WebPageProxy::willPerformPasteCommand(DOMPasteAccessCategory)
void WebPageProxy::willPerformPasteCommand(DOMPasteAccessCategory, std::optional<FrameIdentifier>)
{
}

Expand Down
4 changes: 2 additions & 2 deletions Source/WebKit/UIProcess/WebPageProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -2125,7 +2125,7 @@ class WebPageProxy final : public API::ObjectImpl<API::Object::Type::Page>, publ
void clearServiceWorkerEntitlementOverride(CompletionHandler<void()>&&);

#if PLATFORM(COCOA)
void grantAccessToCurrentPasteboardData(const String& pasteboardName);
void grantAccessToCurrentPasteboardData(const String& pasteboardName, std::optional<WebCore::FrameIdentifier> = std::nullopt);
#endif

#if PLATFORM(MAC)
Expand Down Expand Up @@ -2673,7 +2673,7 @@ class WebPageProxy final : public API::ObjectImpl<API::Object::Type::Page>, publ
#endif

void requestDOMPasteAccess(WebCore::DOMPasteAccessCategory, const WebCore::IntRect&, const String&, CompletionHandler<void(WebCore::DOMPasteAccessResponse)>&&);
void willPerformPasteCommand(WebCore::DOMPasteAccessCategory);
void willPerformPasteCommand(WebCore::DOMPasteAccessCategory, std::optional<WebCore::FrameIdentifier> = std::nullopt);

// Back/Forward list management
void backForwardAddItem(BackForwardListItemState&&);
Expand Down
4 changes: 2 additions & 2 deletions Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1545,12 +1545,12 @@ static RecommendDesktopClassBrowsingForRequest desktopClassBrowsingRecommendedFo

#endif

void WebPageProxy::willPerformPasteCommand(DOMPasteAccessCategory pasteAccessCategory)
void WebPageProxy::willPerformPasteCommand(DOMPasteAccessCategory pasteAccessCategory, std::optional<FrameIdentifier> frameID)
{
switch (pasteAccessCategory) {
case DOMPasteAccessCategory::General:
case DOMPasteAccessCategory::Fonts:
grantAccessToCurrentPasteboardData(UIPasteboardNameGeneral);
grantAccessToCurrentPasteboardData(UIPasteboardNameGeneral, frameID);
return;
}
}
Expand Down
7 changes: 3 additions & 4 deletions Source/WebKit/UIProcess/mac/WebPageProxyMac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -637,15 +637,14 @@ static inline bool expectsLegacyImplicitRubberBandControl()

#endif

void WebPageProxy::willPerformPasteCommand(DOMPasteAccessCategory pasteAccessCategory)
void WebPageProxy::willPerformPasteCommand(DOMPasteAccessCategory pasteAccessCategory, std::optional<FrameIdentifier> frameID)
{
switch (pasteAccessCategory) {
case DOMPasteAccessCategory::General:
grantAccessToCurrentPasteboardData(NSPasteboardNameGeneral);
grantAccessToCurrentPasteboardData(NSPasteboardNameGeneral, frameID);
return;

case DOMPasteAccessCategory::Fonts:
grantAccessToCurrentPasteboardData(NSPasteboardNameFont);
grantAccessToCurrentPasteboardData(NSPasteboardNameFont, frameID);
return;
}
}
Expand Down
63 changes: 63 additions & 0 deletions Tools/TestWebKitAPI/Tests/WebKitCocoa/SiteIsolation.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,69 @@ HTTPServer server({
EXPECT_WK_STREQ("dragleave", events[2]);
EXPECT_WK_STREQ("dragend", events[3]);
}

void writeImageDataToPasteboard(NSString *type, NSData *data)
{
[NSPasteboard.generalPasteboard declareTypes:@[type] owner:nil];
[NSPasteboard.generalPasteboard setData:data forType:type];
}

TEST(SiteIsolation, PasteGIF)
{
auto mainframeHTML = "<script>"
" window.events = [];"
" addEventListener('message', function(event) {"
" window.events.push(event.data);"
" });"
"</script>"
"<iframe width='300' height='300' src='https://domain2.com/subframe'></iframe>"_s;

auto subframeHTML = "<body>"
"<div id='editor' contenteditable style=\"height:100%; width: 100%;\"></div>"
"<script>"
"const editor = document.getElementById('editor');"
"editor.focus();"
"editor.addEventListener('paste', (event) => { window.parent.postMessage(event.clipboardData.files[0].name, '*'); });"
"</script>"
"</body>"_s;

HTTPServer server({
{ "/mainframe"_s, { mainframeHTML } },
{ "/subframe"_s, { subframeHTML } }
}, HTTPServer::Protocol::HttpsProxy);

auto navigationDelegate = adoptNS([TestNavigationDelegate new]);
[navigationDelegate allowAnyTLSCertificate];
auto configuration = server.httpsProxyConfiguration();
enableSiteIsolation(configuration);
auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration]);
webView.get().navigationDelegate = navigationDelegate.get();

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://domain1.com/mainframe"]]];
[navigationDelegate waitForDidFinishNavigation];

CGPoint eventLocationInWindow = [webView convertPoint:CGPointMake(20, 20) toView:nil];
[webView mouseEnterAtPoint:eventLocationInWindow];
[webView mouseMoveToPoint:eventLocationInWindow withFlags:0];
[webView mouseDownAtPoint:eventLocationInWindow simulatePressure:NO];
[webView mouseUpAtPoint:eventLocationInWindow];
[webView waitForPendingMouseEvents];

auto *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sunset-in-cupertino-400px" ofType:@"gif" inDirectory:@"TestWebKitAPI.resources"]];
writeImageDataToPasteboard((__bridge NSString *)kUTTypeGIF, data);
[webView paste:nil];

[webView mouseEnterAtPoint:eventLocationInWindow];
[webView mouseMoveToPoint:eventLocationInWindow withFlags:0];
[webView mouseDownAtPoint:eventLocationInWindow simulatePressure:NO];
[webView mouseUpAtPoint:eventLocationInWindow];
[webView waitForPendingMouseEvents];

NSArray<NSString *> *events = [webView objectByEvaluatingJavaScript:@"window.events"];
EXPECT_EQ(1U, events.count);
EXPECT_WK_STREQ("image.gif", events[0]);
}

#endif

TEST(SiteIsolation, ShutDownFrameProcessesAfterNavigation)
Expand Down

0 comments on commit ba6e612

Please sign in to comment.