Closed rupakkarki27 closed 8 months ago
Hi @rupakkarki27,
how did you get that page
instance? chrome.debugger
API requires a tabId
, and playwright-crx
should ensure that a page
maps to a chrome tabId
(that mapping can be found in crxTransport.ts
.
The simplest way to instanciate a page with a backed tabId
is to call crxApp.newPage
:
import { crx } from 'playwright-crx';
// ...
const crxApp = await crx.start();
const page = await crxApp.newPage();
Yes, that is what i did. I am sending background messages from the react app using chrome.runtime.sendMessage
api, and receiving it in background.ts
as such:
browser.runtime.onMessage.addListener(async (message: Message) => {
const tab = await chrome.tabs.query({ currentWindow: true, active: true });
const crxApp = await crx.start({ slowMo: 500 });
const page = await crxApp.attach(tab[0].id!).catch(() => crxApp.newPage());
// send the page instance to the script
}
I suspect that tab[0].id
is undefined. Try to output it with console.log, it will write into your extension service worker devtools.
You can open your extension devtools by inspecting the service worker view:
The tab[0].id
is not undefined. The issue is that the scripts navigates and goes to the page, but it's stuck on this loading screen. When I cancel, the page will load fine. This does not happen on all sites, proton mail is the only one I'm seeing this issue in.
Output of the tabs query:
{
"tab": [
{
"active": true,
"audible": false,
"autoDiscardable": true,
"discarded": false,
"favIconUrl": "",
"groupId": -1,
"height": 823,
"highlighted": true,
"id": 512783461,
"incognito": false,
"index": 2,
"mutedInfo": {
"muted": false
},
"pinned": false,
"selected": true,
"status": "complete",
"title": "Extensions",
"url": "chrome://extensions/",
"width": 1102,
"windowId": 512783460
}
]
}
I was able to replicate the issue I also get that "stuck" screen, and with the exact errors you have. I'll have to investigate it a little bit, it seems to be a bug.
stacktrace with sourcemaps:
No tabId provided for Runtime.enable
_send @ crxTransport.ts:163
send @ crxTransport.ts:89
_rawSend @ crConnection.ts:66
send @ crConnection.ts:158
_sendMayFail @ crConnection.ts:165
_onAttachedToTarget @ crPage.ts:748
(anonymous) @ crPage.ts:445
emit @ events.js:153
(anonymous) @ crConnection.ts:183
Promise.then (async)
_onMessage @ crConnection.ts:180
_onMessage @ crConnection.ts:76
_emitMessage @ crxTransport.ts:209
(anonymous) @ crxTransport.ts:200
Checking crPage.ts, target must be a Worker at that point.
I'm trying to create a simple test to check workers.
The No tabId provided for (...)
errors are related with service workers, not normal workers.
Workers are assigned to a page, and therefore it's possible to get the corresponding tab ID, but service workers are not. That's why browserContext
object has serviceWorkers
and page object only has workers, and workers()
function documentation explicitly says that:
This does not contain ServiceWorkers
That being said, I'm not sure if the behaviour on the page is because of that.
But there's a workaround: as soon as chrome.debugger
is detached from the page, it proceeds as expected, so you can detach and attach until the form is available:
const { id: tabId } = await chrome.tabs.create({ url: "https://account.proton.me/login" });
let page: Page;
while (true) {
page = await crxApp.attach(tabId!);
if (await page.locator("//input[@id='username']").isVisible())
break;
await crxApp.detach(tabId!);
await new Promise(r => setTimeout(r, 1000));
}
await page.getByLabel("Email or username").click();
await page.getByLabel("Email or username").fill('foo');
await page.getByLabel("Password").click();
await page.getByLabel("Password").fill('bar');
@ruifigueira, thank you for the workaround. It works pretty well but takes a bit longer. I'm working on any ways to optimize it further if I have time, but overall works great. Thanks.
Finally I found out the reason for this problem: playwright forces that all targets (pages, workers, service workers) to wait for debugger when they auto attach:
this._client.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true })
Playwright then sends a Runtime.runIfWaitingForDebugger
to let it continue. As explained above, chrome.debugger
can only send CDP instructions to tabs, so it doesn't seem to be possible to send the instruction for the service worker, and that's why it was stucked.
I fixed this by ensuring that service workers are never auto-attached.
Hey @ruifigueira, thanks for this implementation of playwright and it works very well in almost all scenarios, and I was able to bundle it in an extension version with vite and react. However, I am having some issues with certain sites for example proton mail. I'm trying to write a script that checks for the login email and password inputs, and fills it. However, the script just freezes after navigation to the page and then gives the errors as in the title. If I cancel the debugger then the sites loads normally, but at that point the automation won't work
However, it works when I try it with core playwright. I tried going through the playwright-crx to debug and possibly fix and contribute but I was not able to find anything, and could not determine where to start to contribute.
This is the small script that I used:
and I have received the following stack trace when the script stops:
It would be great if you would be able to point me at the right direction, and I'm hoping I could contribute to playwright-crx.
Thanks.