Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome DevTools Protocol: control new tabs

Need to be done: I need to simulate user interactions (journeys) across a chain of sites.

Question: Do you have any tips how to programatically controll a tab opened as a result of a simulated click?

My experience: I'm using the chrome-remote-interface npm package. I'm able to simulate a click with a custom ChromeController class which initializes the chrome-remote-interface and these methods:

async simulateClick(selector) {
    return await this.evaluate(function (selector) {
        document.querySelector(selector).click()
    }, selector);
}
/**
 * Shamelessly stolen from simple-headless-browser
 */
async evaluate (fn, ...args) {

    const exp = args && args.length > 0 ? `(${String(fn)}).apply(null, ${JSON.stringify(args)})` : `(${String(fn)}).apply(null)`
    const result = await this.client.Runtime.evaluate({
        expression: exp,
        returnByValue: true
    })        

    return result
}

Now I would like to interact with the recently opened tab. I can get the targetId of the new tab with the experimenetal Target Domain (prototyping in node cli):

var targets;
chromeController.client.Target.getTargets().then(t => targets = t);

Which results in:

{ targetInfos: 
 [ { targetId: '97556479-cdb6-415c-97a1-6efa4e00b281',
     type: 'page',
     title: 'xxx/preview/239402/',
     url: 'xxx/preview/239402/' },
   { targetId: 'bbfe11d5-8e4a-4879-9081-10bb7234209c',
     type: 'page',
     title: 'Document',
     url: 'xxx/preview/239402/teaser/0/' } ] }

I am able to switch between the tabs with:

chromeController.client.Target.activateTarget({targetId:'xxx'})

However I'm not able to get any interaction with this, I can't find the connection, how to load it into the Page and Runtime objects.

I've searched in the docs and also tried googling: 'site:chromedevtools.github.io targetId' which only lead me to

> chromeController.client.Browser.getWindowForTarget({targetId: '97556479-cdb6-415c-97a1-6efa4e00b281'}).catch(e => console.log(e.message));
Promise { <pending> }
> 'Browser.getWindowForTarget' wasn't found

I've also tried to Target.setDiscoverTargets({discover: true}) and to close the original tab.

Thanks for any help!

like image 262
Nightowl Avatar asked Dec 07 '25 17:12

Nightowl


1 Answers

Recently faced this same issue and in short I had to create a new dev tools protocol client for each new target I wanted control over.

My experience is with dev tools protocol using direct communication with websocket but the api is the same so it should be similar. So here is a summary of what I had to do.

Initially looking at the docs I would have assumed Target.attachToTarget should give us control of the new tab but I found that it didn't work.

My workaround was to create a listener that listened for the Target.targetCreated event which provides a targetInfos just like you found with Target.getTargets but for every new target created like a new tab, page, or iframe. Note: you need to enable Target.setDiscoverTargets in order to receive these events over the protocol.

 [ { targetId: '97556479-cdb6-415c-97a1-6efa4e00b281',
     type: 'page',
     title: 'xxx/preview/239402/',
     url: 'xxx/preview/239402/' },
   { targetId: 'bbfe11d5-8e4a-4879-9081-10bb7234209c',
     type: 'page',
     title: 'Document',
     url: 'xxx/preview/239402/teaser/0/' } ] }

With that listener I looked for targets that were of type page, you could filter on a specific url if you know what the page will be. With the targetId in hand I requested available websocket targets following the HTTPEndpoints section near the bottom of the devtools home page.

GET /json or /json/list
A list of all available websocket targets.

[ {
  "description": "",
  "devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/DAB7FB6187B554E10B0BD18821265734",
  "id": "DAB7FB6187B554E10B0BD18821265734",
  "title": "Yahoo",
  "type": "page",
  "url": "https://www.yahoo.com/",
  "webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/DAB7FB6187B554E10B0BD18821265734"
} ]

I could then launch a new dev tools protocol client using the webSocketDebuggerUrl and have full control over the tab.

I know this is a pretty round about way but, its the only way I was able to make if work.

Although these days it's probably easier to use something like puppeteer to interface with multiple tabs in chrome if you can. Here is the source code to a puppeteer module that follows new tabs that could be good reference for trying to replicate it pageVideoStreamCollector.ts

This is a very late answer but just putting this here if anyone else has the same issue as help on chrome dev tools is very hard to come by. Hope it helps someone out.

like image 83
nickrl21 Avatar answered Dec 09 '25 11:12

nickrl21