Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Playwright as a Chromium extension #23514

Open
ruifigueira opened this issue Jun 4, 2023 · 11 comments
Open

[Feature] Playwright as a Chromium extension #23514

ruifigueira opened this issue Jun 4, 2023 · 11 comments

Comments

@ruifigueira
Copy link
Contributor

ruifigueira commented Jun 4, 2023

I've been working on a PoC to compile playwright into a chromium extension. You can find my fork here: https://github.com/ruifigueira/playwright-crx.

I was able to make it work (with some limitations, of course).

Here is a small video of the recorder as a chrome devtools panel:

chrome_pA3XQPGFEU.mp4

The core of this integration is a ConnectionTransport implementation (see crxTransport.ts) that mostly uses chrome.debugger API.

This API is per tab (we need to provide chrome tab ID to attach it), so for now it can only handle one tab at a time.

Besides, some CDP methods are not supported under chrome.debugger, so I had to emulate them.

To build the chrome extension:

npm ci
npm run build

Then, In chrome, just add an unpacked extension pointing to packages/playwright-core/lib/webpack/crx.

image

After that, it should be available in devtools as a panel with name Playwright Recorder.
Try to record and inspect some elements to ensure everything works fine.

Let me know yout thoughts!

@pavelfeldman
Copy link
Member

@ruifigueira this looks very impressive! What kind of feedback are you looking for?

In terms of priorities, we like to generate code into the editor (VS Code), but given how ubiquitous Chrome DevTools are, it feels like a nice addition to the suite. So if we can figure out a good maintenance story and cover it with enough tests, we can accept the contribution!

I think the major obstacle is the collection of the polyfills (vite-plugin-node-polyfills). Your approach is great - it is minimally intrusive to Playwright code, but at the same time it is the most brittle. I wonder if there is a middle ground where we don't pollute our code with too many unnecessary abstractions, yet we can compile our code with the explicit platform externs. Think explicit platformBundle that is implemented via the node internals and mocked by the browser). It might easily get out of hand, but I would at least be interested in what it could look like.

@pavelfeldman
Copy link
Member

I wonder if there is a middle ground where we don't pollute our code with too many unnecessary abstractions

Looked at our third party dependencies and this breaks fairly quickly against their extensive use of builtins. Even if we abstract our code, it'll still be a problem in thier's.

@ruifigueira
Copy link
Contributor Author

@pavelfeldman thanks for the feedback.

Honestly, I think this approach for shimming / polyfilling those thirdparty dependencies is not that bad.
I've been battling a little bit with vite trying to make it replace problematic code and current implementation using define is far from great, but if we can properly replace all require('./utilsBundleImpl') and a few more node-ish stuff, I would be quite happy.

Besides that, right now I'm instantiating the full playwright stuff by calling the createInProcessPlaywright but probably creating a new BrowserContext or something similar and start from there, it would be a wiser solution

@pavelfeldman
Copy link
Member

I'm not too concerned about these, we can always fix it in the code we own. Unfortunately, we are using some third party node modules that will also require fs and alike without us calling any methods that require those. So while we can solve this problem for ourselves, we can't solve it for others.

I looked at the https://github.com/niksy/node-stdlib-browser#package-contents and I don't think we'd be comfortable shipping something that uses those stubs in production: often times there is no clear ownership and some modules aren't even semverd. Unfortunately, going that route would make us easily compromised.

We can probably accept patches upstream that help you get rid of defines: massage utilsBundle in a way that you can consume it (not sure why it did not work out of the box). I was hoping you could teach vite to bundle the package.json files too. Third party modules that you stub there seem to be isomorphic. So all in all, getting rid of defines sounds doable.

@ruifigueira
Copy link
Contributor Author

Before addressing the isomorphic "decoupling", I refactored playwright-core a little bit:

  • I replaced most of the requires (I noticed that some of them are due to circular references issues)
  • I'm using absolute paths for utilsBundle, zipBundle and deviceDescriptors imports, for them to be replaced easily with vite alias.
  • I moved some util functions declared in utilsBundle into utils folder, that way I don't need to redefine those functions on my crx module.

You can check those changes in 2b3b58a . I tried to be as minimalistic as possible in my changes on your code base.

With that I refactored vite on my side (0bc67c8):

  • use browserfs and browserify for shim / polyfill. As you say, the objective is not to rely on these, but for now they let me compile / run the code as a chrome extension
  • replace utilsBundle / zipBundle imports with their *Impl counterparts

@aslushnikov
Copy link
Collaborator

aslushnikov commented Jun 12, 2023

@pavelfeldman Pavel is not available right now, so I'll mark this as 1.36 so that we don't forget about it.

@ruifigueira
Copy link
Contributor Author

Hi @pavelfeldman

I was on vacations, but I'm still working on this :)

For testing, the goal is to use your current page tests as much as possible.
The idea is to run tests in a chrome extension worker service, and for that we send the test body to run there, similar to playwright evaluate calls to execute code on the browser.

Of course, tests that depend on functions defined outside the test will fail, which is a big limitation on this approach, but I was able to run it and more than 1k tests ran successfully.

You can check a PoC for that in 872a755

By setting PWPAGE_IMPL to crx, it will run tests using that mechanism. I changed WorkerMain a bit so that it would serialize the test function and send it to the service worker to run there.

@damartripamungkas
Copy link

Saya sedang mengerjakan PoC untuk mengkompilasi penulis naskah menjadi ekstensi chromium. Anda dapat menemukan garpu saya di sini: https://github.com/ruifigueira/playwright-crx .

Saya dapat membuatnya berfungsi (tentu saja dengan beberapa keterbatasan).

Berikut adalah video kecil perekam sebagai panel chrome devtools:

chrome_pA3XQPGFEU.mp4
Inti dari integrasi ini adalah ConnectionTransportimplementasi (lihat crxTransport.ts ) yang sebagian besar menggunakan chrome.debugger API .

API ini per tab (kita perlu memberikan ID tab chrome untuk melampirkannya), jadi untuk saat ini hanya dapat menangani satu tab dalam satu waktu.

Selain itu, beberapa metode CDP tidak didukung chrome.debugger, jadi saya harus menirunya.

Untuk membuat ekstensi chrome:

npm ci
npm run build

Kemudian, di chrome, cukup tambahkan ekstensi yang belum dibongkar yang menunjuk ke packages/playwright-core/lib/webpack/crx.

gambar

Setelah itu, seharusnya tersedia di devtools sebagai panel dengan nama Playwright Recorder . Cobalah untuk mencatat dan memeriksa beberapa elemen untuk memastikan semuanya berfungsi dengan baik.

Beri tahu saya pendapat Anda!

can you help me, i dont see playwright-cfx in inspect

image

@ruifigueira
Copy link
Contributor Author

I replaced the devtool panel with an action button / context menu to trigger Playwright CRX. For more details see the section Recorder in #24020 (comment).

@ruifigueira
Copy link
Contributor Author

Different approach, now compatible with Firefox too:

#30347

@ducan-ne
Copy link

This is awesome, I've made something similar with pptr, but now playwright is much better than in apis. Can't wait to use it

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

No branches or pull requests

5 participants