Skip to content

feat: browser list UI#668

Closed
Skn0tt wants to merge 22 commits intomicrosoft:mainfrom
Skn0tt:browserlist
Closed

feat: browser list UI#668
Skn0tt wants to merge 22 commits intomicrosoft:mainfrom
Skn0tt:browserlist

Conversation

@Skn0tt
Copy link
Member

@Skn0tt Skn0tt commented Aug 14, 2025

Adds UI for showing a list of browsers, each with a "Pick Locator" and "Close" button. This uses the data from microsoft/playwright#37027. On old versions, we try to infer the browser information from the currently selected project.

While the buttons are per-browser in the UI, they currently always affect all browsers. I'll fix this in a follow-up, but it should be fine given most people only ever use a single browser at a time anways.

Screen.Recording.2025-08-14.at.15.51.47.mov

@Skn0tt Skn0tt requested a review from dgozman August 14, 2025 13:53
@Skn0tt Skn0tt self-assigned this Aug 14, 2025
Copy link
Contributor

@dgozman dgozman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall!

package.nls.json Outdated
"contributes.command.pw.extension.command.inspect": "Pick locator",
"contributes.command.pw.extension.command.clearCache": "Clear cache",
"contributes.command.pw.extension.command.closeBrowsers": "Close all Playwright browsers",
"contributes.command.pw.extension.command.closeBrowsers": "Close all Playwright testing browsers",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you going to follow up with translations? I wonder what is the process for that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I don't think we have a set process - let me follow up with translations at the end, when everything's said and done.

<title>Playwright</title>
</head>
<body class="settings-view">
<section role="region" aria-label="Browsers">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps the "Show browser" checkbox should be here as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps! I'll try it out, but that's for a different PR.

this._onChanged = new this._vscode.EventEmitter();
this.onChanged = this._onChanged.event;

this._reusedBrowser.onBackend(b => this._add(b));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of listening to the ReusedBrowser, I'd make this a part of it. Or do you plan for this list to aggregate multiple backends?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, the MCP server will also be contributing a DebugController, but with different behaviour than ReusedBrowser. BrowserList will aggregate both.

}

export function createAction(action: ActionDescriptor, options?: { omitText?: boolean }): HTMLElement | null {
export interface BrowserEntry {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be in BrowserList?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, because it's part of the communication between settingsView.ts and settingsView.script.ts

<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline' ${webview.cspSource}; script-src 'nonce-${nonce}';">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need unsafe-inline?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, becaue the SVGs have <def> elements that don't work otherwise. I was unable to rewrite it so that it works without unsafe-inline. If you know a magic trick, I'd be happy to learn it!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we can use a png icon, or find a different svg. Here's an example.

<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src ${webview.cspSource}; script-src 'nonce-${nonce}';">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline' ${webview.cspSource}; script-src 'nonce-${nonce}';">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, we can use a png icon, or find a different svg. Here's an example.

import * as vscodeTypes from './vscodeTypes';

export class BrowserList {
private _state = new Map<DebugController, { id: string; name: string; channel?: string; title: string }[]>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite like that BrowserList touches DebugController, which is an internal part of it. I'd prefer for BrowserList to listen to ReusedBrowser.onBrowsersChanged event instead, and encapsulate the DebugController inside. WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's good how it is. Let me give an outlook for what i'm planning in the upcoming PRs:

ReusedBrowser won't be the only thing that contributes Debug Controllers, but the MCP integration will also contribute them. So I want all browser-related actions to live on BrowserList instead of ReusedBrowser. For that, I need DebugController to become an internal part of BrowserList. ReusedBrowser will lose a lot of responsibility to BrowserList, all the inspection and closing and recording stuff will move over to BrowserList, and ReusedBrowser ends up being just about starting/stopping the browser server.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed offline, I updated this PR so that it moves over the DebugController-related parts right away.

@Skn0tt
Copy link
Member Author

Skn0tt commented Aug 29, 2025

Mirroring our offline discussion here. Splitting up the responsibilities between BrowserList and ReusedBrowser is sound, but as evidenced by #681 the migration is risky. I'll close this PR and turn it into smaller chunks, in a sequence roughly like this:

  • extract the subprocess part of reusedBrowser into a class called playwrightServer
  • rename reusedBrowser into browserList
  • change the UI

@Skn0tt Skn0tt closed this Aug 29, 2025
@Skn0tt
Copy link
Member Author

Skn0tt commented Aug 29, 2025

here's a version of this PR that just changes the UI, and doesn't do any refactoring: #682

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants