DevToolsProtocol, Runtime.evaluate against worker execution context
Asked Answered
F

1

9

In the console of chrome devtools there is a dropdown at the top to select the execution context.

Here is an example when on www.google.com

enter image description here

Changing the execution context changes the available global variables and what any console invoked .js can access

I'm trying to run some javascript via ChromeDevtools Protocol using the Runtime.evaluate function and I need to run it in the worker context.

Checking the CDP docs, I see that Runtime.evaluate takes a parameter ExecutionContextId. I initially made the assumption that the execution contexts via the DevTools window dropdown would be the same as this parameter. The only way I've worked out how to get a list of the the current ExecutionContextId's is to subscribe to the Runtime.executionContextCreated event then do a Runtime.disable followed by a Runtime.enable which causes an ExecutionContextDiscription to be received by the eventhandler for each loaded context.

However after looking though the ExecutionContextDescription's returned, some match those in the dropdown, but an execution context describing the worker is never returned.

How does one execute js in a worker execution context via CDP, as is trivially done in ChromeDevtools window ?

Fob answered 17/8, 2022 at 13:19 Comment(4)
Ugh, I am just having exactly the same issue. I also need to run a runtime command on a service worker, but I don't know the context ID. Did you figure something out? Giving this one a bounty to attract more attention.Simone
did you try Target.getTargets? every target has browserContextId in TargetInfo.Seasoning
@Seasoning maybe, One of the TargetInfo's returned (in my test here) is a SharedWorker, but the browserContextId is string (eg. 3EE21C36701BE09DB05708AAA333FB86 and ExecutionContextId is supposed to be integer. How to go from one to the other ?Fob
there is an alternative parameter for executionContextId as string, but evaluate doesn't accept browserContextId there. I didn't find a way. the only way I see to get executionContextId is what you describe in the question or Page.createIsolatedWorldSeasoning
F
1

Whilst I did not find a way to do it with an execution context, I was able to achieve the end game via the below process.

  1. Get a list of the possible TargetID's
  2. Connect to the Target of interest with Target.attachToTarget & note the sessionId returned
  3. Call the CDP method of interest in "flat mode"

Step 1 has a couple of approaches, and each additional step here may need to be applied in different situations.

  1. Call Target.getTargets which may return the target of interest
  2. Hook into the targetCreated event and call Target.setDiscoverTargets
  3. Call Target.setAutoAttach(true, false) before step 2
  4. Call Target.setAutoAttach(false, false) before step 3

In my testing here, the worker of interest did not appear via method 1, but does appears in method 2, and in other situations I needed all 4 steps for the event handler to properly fire. I don't know why there is a difference.

"Flat mode" as mentioned in the docs is basically any CDP command with a sessionId included. e.g.

{"method": "Domain.method", "params": {"method params"}, "sessionId": "12345"}

Credit goes to Puppeteer and its logs which helped me to decipher the process.

Fob answered 29/8, 2022 at 2:36 Comment(4)
Could you perhaps make your answer a little bit more explicit? Did you use the auto-attach feature at all, and if so, did you use waitForDebuggerOnStart? If not, does this mean you don't care when Runtime.evaluate will be executed in the worker?Simone
I could, but I think the answer covers the specifics that are directly related to getting to the point of Runtime.evaluate against the worker on the assumption the worker is already running (no need for auto-attach or waitForDebuggerOnStart in my testing). If there is some other complexity related to how a worker starts, then maybe some additional steps might be necessary ? But if the worker is not running then it would not even appear in the DevTools window context dropdown for adhoc js eval. Is the above not working in your case ?Fob
In my specific case I not only need to attach to all workers that may be running, but also clear their caches (or, prevent them from using any caching) before they actually start working. I have tried running the respective command from the Network domain as well as Runtime.evaluate with the chrome.benchmarking commands that clear caches — but it doesn't seem to work (requests have the fromDiskCache flag set). Might be another issue though …Simone
I've just updated my answer in light of some additional testing here. Turns out setAutoAttach is needed sometimes. If you can do a Runtime.evaluate('this.location') and inspect the details of the object it will give an indication if you are indeed running in the correct context. If you are, then the other issues you are experiencing are likely outside the scope of this question.Fob

© 2022 - 2024 — McMap. All rights reserved.