Skip to content

Commit 332ea58

Browse files
carlosjeurissenxeenon
authored andcommitted
Add support for runtime.getDocumentId()
https://bugs.webkit.org/show_bug.cgi?id=305380 Reviewed by Timothy Hatcher. Implement the `runtime.getDocumentId()` method as proposed by the WECG. * Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIRuntimeCocoa.mm: (WebKit::WebExtensionAPIRuntime::getDocumentId): * Source/WebKit/WebProcess/Extensions/API/WebExtensionAPIRuntime.h: * Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPIRuntime.idl: * Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIRuntime.mm: (TestWebKitAPI::TEST(WKWebExtensionAPIRuntime, GetFrameId)): (TestWebKitAPI::TEST(WKWebExtensionAPIRuntime, GetDocumentId)): Canonical link: https://commits.webkit.org/305912@main
1 parent c764abb commit 332ea58

File tree

4 files changed

+78
-0
lines changed

4 files changed

+78
-0
lines changed

Source/WebKit/WebProcess/Extensions/API/Cocoa/WebExtensionAPIRuntimeCocoa.mm

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,25 @@ - (instancetype)initWithAggregator:(WebKit::ReplyCallbackAggregator&)aggregator
267267
return toWebAPI(toWebExtensionFrameIdentifier(*frame));
268268
}
269269

270+
String WebExtensionAPIRuntime::getDocumentId(JSValue *target, NSString **outExceptionString)
271+
{
272+
// Documentation: https://github.com/w3c/webextensions/blob/main/proposals/runtime_get_document_id.md
273+
274+
RefPtr frame = target ? WebFrame::contentFrameForWindowOrFrameElement(target.context.JSGlobalContextRef, target.JSValueRef) : nullptr;
275+
if (!frame) {
276+
*outExceptionString = toErrorString(nullString(), @"target", @"is not a valid window or frame element").createNSString().autorelease();
277+
return String();
278+
}
279+
280+
auto documentIdentifier = toDocumentIdentifier(*frame);
281+
if (!documentIdentifier) {
282+
*outExceptionString = toErrorString(nullString(), nullString(), @"an unexpected error occurred").createNSString().autorelease();
283+
return String();
284+
}
285+
286+
return documentIdentifier.value().toString();
287+
}
288+
270289
void WebExtensionAPIRuntime::setUninstallURL(URL, Ref<WebExtensionCallbackHandler>&& callback)
271290
{
272291
// Documentation: https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/setUninstallURL

Source/WebKit/WebProcess/Extensions/API/WebExtensionAPIRuntime.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class WebExtensionAPIRuntime : public WebExtensionAPIObject, public WebExtension
7373
void getPlatformInfo(Ref<WebExtensionCallbackHandler>&&);
7474
void getBackgroundPage(Ref<WebExtensionCallbackHandler>&&);
7575
double getFrameId(JSValue *);
76+
String getDocumentId(JSValue *, NSString **outExceptionString);
7677

7778
void setUninstallURL(URL, Ref<WebExtensionCallbackHandler>&&);
7879

Source/WebKit/WebProcess/Extensions/Interfaces/WebExtensionAPIRuntime.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
[NSDictionary] any getManifest();
3535
DOMString getVersion();
3636
double getFrameId(any target);
37+
[RaisesException] DOMString getDocumentId(any target);
3738

3839
[MainWorldOnly] void getPlatformInfo([Optional, CallbackHandler] function callback);
3940
[MainWorldOnly] void getBackgroundPage([Optional, CallbackHandler] function callback);

Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebExtensionAPIRuntime.mm

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,63 @@
405405
[manager run];
406406
}
407407

408+
TEST(WKWebExtensionAPIRuntime, GetDocumentId)
409+
{
410+
TestWebKitAPI::HTTPServer server({
411+
{ "/"_s, { { { "Content-Type"_s, "text/html"_s } }, "<iframe src='/subframe'></iframe>"_s } },
412+
{ "/subframe"_s, { { { "Content-Type"_s, "text/html"_s } }, "Subframe Content"_s } },
413+
}, TestWebKitAPI::HTTPServer::Protocol::Http);
414+
415+
auto *urlRequest = server.requestWithLocalhost();
416+
417+
auto *backgroundScript = Util::constructScript(@[
418+
@"browser.test.sendMessage('Load Tab')"
419+
]);
420+
421+
auto *contentScript = Util::constructScript(@[
422+
@"function isValidDocId(input) {",
423+
@" return typeof input === 'string' && input.length > 0",
424+
@"}",
425+
426+
@"if (window.top === window) {",
427+
@" browser.test.assertThrows(() => browser.runtime.getDocumentId(), /required argument is missing/, 'Method should throw on incorrect input undefined')",
428+
@" browser.test.assertThrows(() => browser.runtime.getDocumentId(null), /value is invalid, because an object is expected/, 'Method should throw on incorrect input type')",
429+
@" browser.test.assertThrows(() => browser.runtime.getDocumentId('test'), /value is invalid, because an object is expected/, 'Method should throw on incorrect input type')",
430+
@" browser.test.assertThrows(() => browser.runtime.getDocumentId({}), /not a valid window or frame element/, 'Method should throw on incorrect input objects')",
431+
432+
@" const mainDocId = browser.runtime.getDocumentId(window)",
433+
@" browser.test.assertTrue(isValidDocId(mainDocId), 'Main document should return a valid documentId')",
434+
435+
@" const frameElement = document.querySelector('iframe')",
436+
@" const subFrameElementDocId = browser.runtime.getDocumentId(frameElement)",
437+
@" browser.test.assertTrue(isValidDocId(subFrameElementDocId), 'Subframe element should return a valid documentId')",
438+
439+
@" const subFrameWindow = frameElement.contentWindow",
440+
@" const subFrameWindowDocId = browser.runtime.getDocumentId(subFrameWindow)",
441+
@" browser.test.assertEq(subFrameElementDocId, subFrameWindowDocId, 'DocumentId from element and window should match')",
442+
@" browser.test.assertTrue(mainDocId !== subFrameWindowDocId, 'Main documentId and subframe documentId should be different')",
443+
@"} else {",
444+
@" const subFrameDocId = browser.runtime.getDocumentId(window)",
445+
@" browser.test.assertTrue(isValidDocId(subFrameDocId), 'Subframe document should return a valid documentId')",
446+
447+
@" const topDocId = browser.runtime.getDocumentId(window.top)",
448+
@" browser.test.assertTrue(isValidDocId(topDocId), 'Subframe should be able to retrieve the top window documentId')",
449+
@"}",
450+
451+
@"browser.test.notifyPass()"
452+
]);
453+
454+
auto manager = Util::loadExtension(runtimeContentScriptManifest, @{ @"background.js": backgroundScript, @"content.js": contentScript });
455+
456+
[manager.get().context setPermissionStatus:WKWebExtensionContextPermissionStatusGrantedExplicitly forURL:urlRequest.URL];
457+
458+
[manager runUntilTestMessage:@"Load Tab"];
459+
460+
[manager.get().defaultTab.webView loadRequest:urlRequest];
461+
462+
[manager run];
463+
}
464+
408465
TEST(WKWebExtensionAPIRuntime, LastError)
409466
{
410467
auto *backgroundScript = Util::constructScript(@[

0 commit comments

Comments
 (0)