-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Description
Filing as the workaround listed in #3699 wasn't sufficient to target content inside the iframe created for a devtools extension panel. I was able to eventually get this working, but it required accessing private APIs (as did the workaround in #3699) so I'd like to see this scenario improved and officially supported.
Here's what it took:
✔ Good: Installing the extension and opening the devtools on a page of my choosing works well.
const browser = await launch({
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`
],
defaultViewport: null,
devtools: true,
headless: false
});
const page = (await browser.pages())[0];
await page.goto(url);⚠ Issue 1: Getting a puppeteer Page pointing to the devtools requires some URL-matching and a hack as the Target type is other (this could be loaded in a separate browser tab as described in #3699, but that also requires accessing private data).
const targets = await browser.targets();
const devtoolsTarget = targets.filter((t) => {
return t.type() === 'other' && t.url().startsWith('chrome-devtools://');
})[0];
// Hack to get a page pointing to the devtools
devtoolsTarget._targetInfo.type = 'page';
const devtoolsPage = await devtoolsTarget.page();🙏 Proposal 1: Expose the devtools as a known target type that can return a Page.
const targets = await browser.targets();
const devtoolsTarget = targets.filter((t) => t.type() === 'devtools')[0];
const devtoolsPage = await devtoolsTarget.page();✔ Good: Activating the extension devtools tab so it's iframe gets created is awkward, but at least this uses public APIs. It takes advantage of keyboard shortcuts as suggested in #3699 - though I'm iterating just once in reverse as the extension is always the last tab.
await devtoolsPage.keyboard.down('Control');
await devtoolsPage.keyboard.press('[');
await devtoolsPage.keyboard.up('Control');⚠ Issue 2: At this point the example in #3699 shows how to get a reference to the tab element in the devtools, but that is outside of the extension panel's iframe and I want to debug the content inside the frame. Unfortunately devtoolsPage.frames() doesn't contain the extension panel frame, but I was able to work around this because the panel did appear in browser.targets().
const targets = await browser.targets();
const extensionPanelTarget = targets.filter((t) => {
return t.type() === 'other' &&
t.url().startsWith('chrome-extension://') &&
t.url().endsWith('/panel.html');
})[0];
// Hack to get a page pointing to the devtools extension panel.
extensionPanelTarget._targetInfo.type = 'page';
// Most APIs on `Page` fail as `mainFrame()` is `undefined` (frame has a `parentId`).
const extensionPanelPage = await extensionPanelTarget.page();
// Getting the first frame and working with that instead provides something usable.
const extensionPanelFrame = extensionPanelPage.frames()[0];
// And now we can finally interact with our extension panel frame!
extensionPanelFrame.click(selector);🙏 Proposal 2: Fix returning the extension panel frame in devtoolsPage.frames():
const extensionPanelFrame = devtoolsPage.frames().filter((frame) => {
return frame.url().startsWith('chrome-extension://') &&
frame.url().endsWith('/panel.html');
})[0];
extensionPanelFrame.click(selector);Let me know if you'd prefer to have the proposals split into two separate issues. I wanted to present them together initially for context on what it took to interact with a devtools extension panel and to better help anyone else who may be trying to do the same.