Skip to content

[WebDriver][BiDi] Enumerate dedicated worker realms in script.getRealms - #73149

Open
sergedeh wants to merge 2 commits into
WebKit:mainfrom
sergedeh:eng/WebDriver-BiDi-Implement-worker-realm-support-for-script-getRealms
Open

sergedeh wants to merge 2 commits into
WebKit:mainfrom
sergedeh:eng/WebDriver-BiDi-Implement-worker-realm-support-for-script-getRealms

Conversation

@sergedeh

@sergedeh sergedeh commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

[WebDriver][BiDi] Enumerate dedicated worker realms in script.getRealms
https://bugs.webkit.org/show_bug.cgi?id=304300

Reviewed by NOBODY (OOPS!).

Teach script.getRealms to enumerate execution-ready dedicated workers that
are owned directly by automated top-level documents.

Keep lifecycle notifications as the only worker-realm registration path. Use
the WebProcess lifecycle registry to report candidate worker and owner
identities after verifying that the owner document and owner realm are still
current. The snapshot contains identity only; it neither supplies realm
metadata nor creates UIProcess state.

In UIProcess, treat lifecycle registration as the source of truth. Enumerate
each controlled main page once, retain the page and its main-frame process
across the asynchronous reply, and then revalidate the context-to-page
mapping, owner frame, process, and process-qualified worker and owner realm
identifiers. Return only candidates that exactly match an already registered
dedicated-worker realm, and deduplicate repeated candidates. Enumeration never
registers a realm or changes lifecycle bookkeeping.

Extract named helpers for current owner-window validation and exact dedicated
worker matching. Treat an identical duplicate lifecycle notification as an
idempotent no-op after validating its ownership, so it cannot emit a second
creation event or replace the registered origin.

Group WorkerInspectorProxy's automation state in an OptionSet. Keep the owner
frame, process-qualified document identifier, and eventual origin together in
AutomationOwnerData while preserving the ordered create/destroy pair for a
worker that terminates before becoming execution-ready.

Apply the context and realm-type filters before serializing protocol
RealmInfo values. Serialize origin and owner information from the registered
lifecycle RealmInfo. Dedicated-worker realms have no browsing context.

Extend the WebKitAutomationSession request-session test with a local dedicated
worker and a second controlled browsing context. The test verifies type and
context filtering, non-empty stable realm identifiers, serialized origin,
owner linkage, unfiltered enumeration without duplicates, and removal after
the owner navigates to a new document.

Imported WPT files are unchanged. The current upstream realmCreated worker
test expects the full worker script URL rather than the serialized worker
origin. Keep that test expected-failing with an explanatory note, but remove
b/304300 from the expectation because this patch resolves the WebKit bug.

Iframe-owned and nested dedicated workers, shared workers, service workers,
worklets, and worker-realm script execution remain follow-up work.

  • Source/WebCore/workers/WorkerInspectorProxy.cpp:
    (WebCore::WorkerInspectorProxy::automationOwnerData):
    (WebCore::WorkerInspectorProxy::automationOwnerIsCurrent):
    (WebCore::WorkerInspectorProxy::workerStarted):
    (WebCore::WorkerInspectorProxy::workerBecameExecutionReady):
    (WebCore::WorkerInspectorProxy::workerTerminated):
  • Source/WebCore/workers/WorkerInspectorProxy.h:
  • Source/WebKit/UIProcess/Automation/BidiScriptAgent.cpp:
    (WebKit::BidiScriptAgent::getRealms):
    (WebKit::BidiScriptAgent::createProtocolRealmInfo):
    (WebKit::BidiScriptAgent::DedicatedWorkerRealmInfo::matches):
    (WebKit::BidiScriptAgent::isCurrentWindowRealm):
    (WebKit::BidiScriptAgent::findRegisteredDedicatedWorkerRealm):
    (WebKit::BidiScriptAgent::registerDedicatedWorkerRealm):
    (WebKit::BidiScriptAgent::processRealmsForPagesAsync):
    (WebKit::BidiScriptAgent::collectExecutionReadyFrameRealms):
    (WebKit::BidiScriptAgent::emitEventsForActiveRealms):
  • Source/WebKit/UIProcess/Automation/BidiScriptAgent.h:
  • Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp:
    (WebKit::WebAutomationSession::scriptDedicatedWorkerRealmCreated):
  • Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp:
    (WebKit::WebAutomationSessionProxy::getDedicatedWorkerRealms):
  • Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.h:
  • Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.messages.in:
  • Tools/TestWebKitAPI/Tests/WebKit/WKWebView/glib/TestAutomationSession.cpp:
    (dedicatedWorkerRealmServerCallback):
    (AutomationTest::receivedMessage):
    (AutomationTest::browsingContextHandleFromLastResponse):
    (AutomationTest::loadPageAndWaitForTitle):
    (AutomationTest::getRealms):
    (verifyDedicatedWorkerRealmEnumeration):
    (testAutomationSessionRequestSession):
    (beforeAll):
    (afterAll):
  • WebDriverTests/TestExpectations.json:

768b1f6

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
✅ 🧪 style ✅ 🛠 ios ✅ 🛠 mac ✅ 🛠 wpe ✅ 🛠 win
✅ 🧪 bindings ✅ 🛠 ios-sim ✅ 🛠 mac-AS-debug ✅ 🧪 wpe-wk2 ❌ 🧪 win-tests
✅ 🧪 webkitperl ✅ 🧪 ios-wk2 ✅ 🧪 api-mac ✅ 🧪 api-wpe
✅ 🧪 webkitpy ✅ 🧪 ios-wk2-wpt ✅ 🧪 api-mac-debug
✅ 🧪 api-ios ✅ 🧪 mac-wk2 ✅ 🛠 gtk3-gcc
✅ 🛠 ios-safer-cpp ✅ 🧪 mac-AS-debug-wk2 ✅ 🛠 gtk
✅ 🛠 vision ✅ 🧪 gtk-wk2
✅ 🛠 vision-sim ✅ 🧪 mac-intel-wk2 ✅ 🧪 api-gtk
✅ 🧪 vision-wk2 ✅ 🛠 mac-safer-cpp   🛠 playstation
✅ 🛠 tv ✅ 🧪 mac-site-isolation
✅ 🛠 tv-sim
✅ 🛠 watch
✅ 🛠 watch-sim

@webkit-ews-buildbot webkit-ews-buildbot added the merging-blocked Applied to prevent a change from being merged label Sep 3, 2026
@sergedeh
sergedeh force-pushed the eng/WebDriver-BiDi-Implement-worker-realm-support-for-script-getRealms branch from 0776bbd to ddace51 Compare September 5, 2026 02:33
@sergedeh
sergedeh marked this pull request as ready for review September 6, 2026 20:44
@sergedeh

sergedeh commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@sergedeh
sergedeh force-pushed the eng/WebDriver-BiDi-Implement-worker-realm-support-for-script-getRealms branch from ddace51 to e981b78 Compare September 24, 2026 21:50
@sergedeh
sergedeh requested a review from a team as a code owner September 24, 2026 21:50

@burg burg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are almost there, just readability and a few more cleanups in this batch of feedback. Thanks for the patience.

std::nullopt,
{ },
{ },
emitCreatedEvent,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getRealms is a second registration path that validates less than the event path. The reply calls registerDedicatedWorkerRealm(..., false); unlike the event path it does not MESSAGE_CHECK the sender's connection. A BiDi client can get a worker realm that was never announced by script.realmCreated (and later get realmDestroyed for it), and a compromised WebContent process can report forged realm tuples indefinitely without being killed.

If you make getRealms read-only by looking up worker realms already registered and skip any that aren't, so there's one source of truth. emitCreatedEvent/creationNotified bookkeeping can then come out of registerDedicatedWorkerRealm.

Comment thread WebDriverTests/TestExpectations.json Outdated
},
"test_dedicated_worker": {
"expected": { "all": { "status": ["TIMEOUT"], "bug": "webkit.org/b/282981"}}
"expected": { "all": { "status": ["FAIL"], "bug": "webkit.org/b/304300", "note": "The imported WPT expects the worker script URL instead of the serialized worker origin"}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This FAIL cites b/304300, the bug this PR closes. Consider filing an upstream WPT bug so the origin/URL mismatch stays tracked after 304300 resolves.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i added an issue in the WPT repo: web-platform-tests/wpt#63009

if (currentOwnerRealmIterator == m_browsingContextToRealmId.end() || currentOwnerRealmIterator->value != ownerRealmIdentifier)
return std::nullopt;

auto ownerRealmIterator = m_activeRealms.find(ownerRealmIdentifier);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Between the chained inline comparisons and the many iterators, this is hard to follow. I'd prefer these checks pulled into named helper methods to keep it readable; below this it gets more familiar.

if (activeRealmIterator != m_activeRealms.end()) {
if (emitCreatedEvent && !activeRealmIterator->value.creationNotified) {
activeRealmIterator->value.creationNotified = true;
sendRealmCreatedEvent(realmIdentifier, activeRealmIterator->value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better to use a stack vector as a worklist so the code that actually sends the event and updates bookkeeping lives in one place.

AutomationInstrumentation::scriptDedicatedWorkerRealmDestroyed(m_identifier, m_automationOwner->frameIdentifier, m_automationOwner->documentIdentifier);
}

if (m_wasTerminatedBeforeExecutionReady) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd help to group the automation-related flags into an m_automationStateFlags bitset (or similar), to make clear they're instrumentation state and not determinative of how workers are implemented.

Comment thread Source/WebCore/workers/WorkerInspectorProxy.cpp
https://bugs.webkit.org/show_bug.cgi?id=304300

Reviewed by NOBODY (OOPS!).

Report script.realmCreated and script.realmDestroyed for dedicated workers
directly owned by automated top-level documents.

A dedicated worker becomes observable only after its global scope is ready.
Capture SecurityOriginData when the scope is created, then post readiness to
the worker object's ScriptExecutionContext. Retain WorkerMessagingProxy while
the startup callback is stored or queued, and clear the callback on startup
failure.

Navigation can replace the owner document while readiness or destruction is
in flight. Capture the owner frame and document at worker startup, require
that owner to remain current before reporting creation, and retain an accepted
association until destruction. When the captured owner remains valid,
termination before readiness produces one ordered realmCreated and
realmDestroyed pair when the readiness callback arrives.

Realm identifiers use process-local counters. Generating worker identifiers
in UIProcess could therefore collide with window identifiers from WebProcess.
Generate worker identifiers in WebProcess instead and qualify every realm
identifier with its ProcessIdentifier. Serialize both components in IPC and
in protocol realm strings.

Validate lifecycle messages against the sending connection, frame process,
automation-controlled page, current owner realm, and cached worker ownership.
Tie worker state to its exact owner realm so delayed destruction for an old
realm cannot remove its replacement or the replacement's workers. Treat
unknown late destruction as an idempotent no-op.

BidiScriptAgent stores worker metadata by realm identifier, applies session
and context event filtering, and replays active realms to new subscribers. It
removes worker metadata during worker, owner-realm, or browsing-context
teardown, including metadata whose active realm is already gone.

Iframe-owned and nested dedicated workers remain follow-up work because their
owner realms are not yet registered. script.getRealms does not yet enumerate
dedicated-worker realms.

The imported realmCreated WPT remains expected-failing because it expects the
full worker script URL instead of the serialized worker origin. The dedicated
worker realmDestroyed test and navigation lifecycle tests pass.

* Source/WebCore/automation/AutomationInstrumentation.cpp:
* Source/WebCore/automation/AutomationInstrumentation.h:
* Source/WebCore/workers/WorkerInspectorProxy.cpp:
* Source/WebCore/workers/WorkerInspectorProxy.h:
* Source/WebCore/workers/WorkerMessagingProxy.cpp:
* Source/WebCore/workers/WorkerMessagingProxy.h:
* Source/WebCore/workers/WorkerOrWorkletThread.cpp:
* Source/WebCore/workers/WorkerOrWorkletThread.h:
* Source/WebKit/Scripts/webkit/messages.py:
* Source/WebKit/Scripts/webkit/tests/MessageArgumentDescriptions.cpp:
* Source/WebKit/Shared/IdentifierTypes.h:
* Source/WebKit/Shared/ProcessQualified.serialization.in:
* Source/WebKit/UIProcess/Automation/BidiScriptAgent.cpp:
* Source/WebKit/UIProcess/Automation/BidiScriptAgent.h:
* Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp:
* Source/WebKit/UIProcess/Automation/WebAutomationSession.h:
* Source/WebKit/UIProcess/Automation/WebAutomationSession.messages.in:
* Source/WebKit/UIProcess/Automation/protocol/BidiScript.json:
* Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp:
* Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.h:
* WebDriverTests/TestExpectations.json:
@sergedeh
sergedeh force-pushed the eng/WebDriver-BiDi-Implement-worker-realm-support-for-script-getRealms branch from e981b78 to d4bd029 Compare September 28, 2026 00:20
https://bugs.webkit.org/show_bug.cgi?id=304300

Reviewed by NOBODY (OOPS!).

Teach script.getRealms to enumerate execution-ready dedicated workers that
are owned directly by automated top-level documents.

Keep lifecycle notifications as the only worker-realm registration path. Use
the WebProcess lifecycle registry to report candidate worker and owner
identities after verifying that the owner document and owner realm are still
current. The snapshot contains identity only; it neither supplies realm
metadata nor creates UIProcess state.

In UIProcess, treat lifecycle registration as the source of truth. Enumerate
each controlled main page once, retain the page and its main-frame process
across the asynchronous reply, and then revalidate the context-to-page
mapping, owner frame, process, and process-qualified worker and owner realm
identifiers. Return only candidates that exactly match an already registered
dedicated-worker realm, and deduplicate repeated candidates. Enumeration never
registers a realm or changes lifecycle bookkeeping.

Extract named helpers for current owner-window validation and exact dedicated
worker matching. Treat an identical duplicate lifecycle notification as an
idempotent no-op after validating its ownership, so it cannot emit a second
creation event or replace the registered origin.

Group WorkerInspectorProxy's automation state in an OptionSet. Keep the owner
frame, process-qualified document identifier, and eventual origin together in
AutomationOwnerData while preserving the ordered create/destroy pair for a
worker that terminates before becoming execution-ready.

Apply the context and realm-type filters before serializing protocol
RealmInfo values. Serialize origin and owner information from the registered
lifecycle RealmInfo. Dedicated-worker realms have no browsing context.

Extend the WebKitAutomationSession request-session test with a local dedicated
worker and a second controlled browsing context. The test verifies type and
context filtering, non-empty stable realm identifiers, serialized origin,
owner linkage, unfiltered enumeration without duplicates, and removal after
the owner navigates to a new document.

Imported WPT files are unchanged. The current upstream realmCreated worker
test expects the full worker script URL rather than the serialized worker
origin. Keep that test expected-failing with an explanatory note, but remove
b/304300 from the expectation because this patch resolves the WebKit bug.

Iframe-owned and nested dedicated workers, shared workers, service workers,
worklets, and worker-realm script execution remain follow-up work.

* Source/WebCore/workers/WorkerInspectorProxy.cpp:
(WebCore::WorkerInspectorProxy::automationOwnerData):
(WebCore::WorkerInspectorProxy::automationOwnerIsCurrent):
(WebCore::WorkerInspectorProxy::workerStarted):
(WebCore::WorkerInspectorProxy::workerBecameExecutionReady):
(WebCore::WorkerInspectorProxy::workerTerminated):
* Source/WebCore/workers/WorkerInspectorProxy.h:
* Source/WebKit/UIProcess/Automation/BidiScriptAgent.cpp:
(WebKit::BidiScriptAgent::getRealms):
(WebKit::BidiScriptAgent::createProtocolRealmInfo):
(WebKit::BidiScriptAgent::DedicatedWorkerRealmInfo::matches):
(WebKit::BidiScriptAgent::isCurrentWindowRealm):
(WebKit::BidiScriptAgent::findRegisteredDedicatedWorkerRealm):
(WebKit::BidiScriptAgent::registerDedicatedWorkerRealm):
(WebKit::BidiScriptAgent::processRealmsForPagesAsync):
(WebKit::BidiScriptAgent::collectExecutionReadyFrameRealms):
(WebKit::BidiScriptAgent::emitEventsForActiveRealms):
* Source/WebKit/UIProcess/Automation/BidiScriptAgent.h:
* Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp:
(WebKit::WebAutomationSession::scriptDedicatedWorkerRealmCreated):
* Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp:
(WebKit::WebAutomationSessionProxy::getDedicatedWorkerRealms):
* Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.h:
* Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.messages.in:
* Tools/TestWebKitAPI/Tests/WebKit/WKWebView/glib/TestAutomationSession.cpp:
(dedicatedWorkerRealmServerCallback):
(AutomationTest::receivedMessage):
(AutomationTest::browsingContextHandleFromLastResponse):
(AutomationTest::loadPageAndWaitForTitle):
(AutomationTest::getRealms):
(verifyDedicatedWorkerRealmEnumeration):
(testAutomationSessionRequestSession):
(beforeAll):
(afterAll):
* WebDriverTests/TestExpectations.json:
@sergedeh
sergedeh force-pushed the eng/WebDriver-BiDi-Implement-worker-realm-support-for-script-getRealms branch from 0b405dd to 768b1f6 Compare September 28, 2026 17:19
@sergedeh
sergedeh requested a review from burg September 28, 2026 22:17

@burg burg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=me, it's just smaller issues now. Please rebase and I'll set merge-queue. Thanks.

},
"test_dedicated_worker": {
"expected": { "all": { "status": ["TIMEOUT"], "bug": "webkit.org/b/282981"}}
"expected": { "all": { "status": ["FAIL"], "note": "Upstream WPT compares RealmInfo.origin with the full worker script URL; WebDriver BiDi requires the serialized worker origin."}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for filing web-platform-tests/wpt#63009. Please put it in the bug field here. Right now this entry has only a note and no bug at all, so nothing will prompt us to revisit it when upstream fixes the test.


RefPtr session = protectedThis->m_session.get();
if (!session)
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This drops callback without replying, so the client never gets a response to script.getRealms if the session goes away mid-command. Please reply with an error here instead.

return;
}

Ref workerProcess = currentPage->legacyMainFrameProcess();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the reply is only used to filter realms that are already registered, it can only hide realms, never add them. Is the round trip needed? Filtering m_dedicatedWorkerRealms by owner browsing context would avoid an IPC per page and the legacyMainFrameProcess() dependency, which the iframe follow-ups will have to undo anyway. If there's an ordering case it covers, a comment explaining it would help.

#if ENABLE(WEBDRIVER_BIDI)
auto WorkerInspectorProxy::automationOwnerData() const -> std::optional<AutomationOwnerData>
{
// FIXME: Support dedicated workers owned by iframes and other workers once

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs bug number?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merging-blocked Applied to prevent a change from being merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants