Skip to content

Commit 7f73578

Browse files
committed
feat(cli): add command to list installed browsers (#34183)
1 parent 878bdcd commit 7f73578

File tree

3 files changed

+123
-9
lines changed

3 files changed

+123
-9
lines changed

docs/src/browsers.md

+38
Original file line numberDiff line numberDiff line change
@@ -1121,3 +1121,41 @@ playwright uninstall --all
11211121
```bash csharp
11221122
pwsh bin/Debug/netX/playwright.ps1 uninstall --all
11231123
```
1124+
1125+
### List browsers
1126+
1127+
This will list the browsers of the current Playwright installation:
1128+
1129+
```bash js
1130+
npx playwright list
1131+
```
1132+
1133+
```bash java
1134+
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="list"
1135+
```
1136+
1137+
```bash python
1138+
playwright list
1139+
```
1140+
1141+
```bash csharp
1142+
pwsh bin/Debug/netX/playwright.ps1 list
1143+
```
1144+
1145+
To list browsers of other Playwright installations as well, pass `--all` flag:
1146+
1147+
```bash js
1148+
npx playwright list --all
1149+
```
1150+
1151+
```bash java
1152+
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="list --all"
1153+
```
1154+
1155+
```bash python
1156+
playwright list --all
1157+
```
1158+
1159+
```bash csharp
1160+
pwsh bin/Debug/netX/playwright.ps1 list --all
1161+
```

packages/playwright-core/src/cli/program.ts

+23
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,29 @@ Examples:
199199
- $ install chrome firefox
200200
Install custom browsers, supports ${suggestedBrowsersToInstall()}.`);
201201

202+
program
203+
.command('list')
204+
.description('List browsers used by this installation of Playwright')
205+
.option('--all', 'List all browsers used by any Playwright installation.')
206+
.action(async (options: { all?: boolean }) => {
207+
await registry.list(!!options.all).then(browsersInfo => {
208+
for (const info of browsersInfo) {
209+
const whichInstanceLog = ` (${info.currentInstance ? 'CURRENT' : 'OTHER'})`;
210+
console.log(`Playwright${options.all ? whichInstanceLog : ''}: ${info.target}`);
211+
212+
for (const browser of info.browsers) {
213+
console.log(` Browser: ${browser.name}`);
214+
console.log(` Version: ${browser.version}`);
215+
console.log(` Location: ${browser.dir}`);
216+
console.log(` Installation completed: ${browser.installationCompleted}`);
217+
console.log(``);
218+
}
219+
console.log(``);
220+
console.log(``);
221+
}
222+
}).catch(logErrorAndExit);
223+
});
224+
202225
program
203226
.command('uninstall')
204227
.description('Removes browsers used by this installation of Playwright from the system (chromium, firefox, webkit, ffmpeg). This does not include branded channels.')

packages/playwright-core/src/server/registry/index.ts

+62-9
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,21 @@ export class Registry {
995995
return await validateDependenciesWindows(sdkLanguage, windowsExeAndDllDirectories.map(d => path.join(browserDirectory, d)));
996996
}
997997

998+
private async _validateMarkerFile(descriptor: BrowsersJSONDescriptor) {
999+
const { revision, dir, name } = descriptor;
1000+
1001+
const browserRevision = parseInt(revision, 10);
1002+
// Old browser installations don't have marker file.
1003+
// We switched chromium from 999999 to 1000, 300000 is the new Y2K.
1004+
const shouldHaveMarkerFile = (name === 'chromium' && (browserRevision >= 786218 || browserRevision < 300000)) ||
1005+
(name === 'firefox' && browserRevision >= 1128) ||
1006+
(name === 'webkit' && browserRevision >= 1307) ||
1007+
// All new applications have a marker file right away.
1008+
(name !== 'firefox' && name !== 'chromium' && name !== 'webkit');
1009+
1010+
return !shouldHaveMarkerFile || (await existsAsync(browserDirectoryToMarkerFilePath(dir)));
1011+
}
1012+
9981013
async installDeps(executablesToInstallDeps: Executable[], dryRun: boolean) {
9991014
const executables = this._dedupe(executablesToInstallDeps);
10001015
const targets = new Set<DependencyGroup>();
@@ -1009,6 +1024,51 @@ export class Registry {
10091024
return await installDependenciesLinux(targets, dryRun);
10101025
}
10111026

1027+
async list(all?: boolean) {
1028+
const linksDir = path.join(registryDirectory, '.links');
1029+
const links = new Set<string>();
1030+
links.add(calculateSha1(PACKAGE_PATH));
1031+
1032+
if (all)
1033+
(await fs.promises.readdir(linksDir)).forEach(link => links.add(link));
1034+
1035+
const browsersInfo: { target: string;currentInstance: boolean; browsers: { name: string; version: string; dir: string; installationCompleted: boolean}[] }[] = [];
1036+
1037+
for (const link of links) {
1038+
try {
1039+
const linkTarget = (await fs.promises.readFile(path.join(linksDir, link))).toString();
1040+
const browsersJSON = require(path.join(linkTarget, 'browsers.json'));
1041+
const descriptors = readDescriptors(browsersJSON);
1042+
const currentTargetBrowsers = [];
1043+
1044+
for (const descriptor of descriptors) {
1045+
const { name, browserVersion, dir } = descriptor;
1046+
if (!isBrowserDirectory(dir))
1047+
continue;
1048+
1049+
const doesExist = await existsAsync(dir);
1050+
if (!doesExist)
1051+
continue;
1052+
1053+
currentTargetBrowsers.push({
1054+
name,
1055+
version: browserVersion || '',
1056+
dir,
1057+
installationCompleted: await this._validateMarkerFile(descriptor)
1058+
});
1059+
}
1060+
browsersInfo.push({
1061+
target: linkTarget,
1062+
browsers: currentTargetBrowsers,
1063+
currentInstance: linkTarget === PACKAGE_PATH,
1064+
});
1065+
1066+
} catch (e) {}
1067+
}
1068+
1069+
return browsersInfo;
1070+
}
1071+
10121072
async install(executablesToInstall: Executable[], forceReinstall: boolean) {
10131073
const executables = this._dedupe(executablesToInstall);
10141074
await fs.promises.mkdir(registryDirectory, { recursive: true });
@@ -1257,15 +1317,8 @@ export class Registry {
12571317
if (!descriptor)
12581318
continue;
12591319
const usedBrowserPath = descriptor.dir;
1260-
const browserRevision = parseInt(descriptor.revision, 10);
1261-
// Old browser installations don't have marker file.
1262-
// We switched chromium from 999999 to 1000, 300000 is the new Y2K.
1263-
const shouldHaveMarkerFile = (browserName === 'chromium' && (browserRevision >= 786218 || browserRevision < 300000)) ||
1264-
(browserName === 'firefox' && browserRevision >= 1128) ||
1265-
(browserName === 'webkit' && browserRevision >= 1307) ||
1266-
// All new applications have a marker file right away.
1267-
(browserName !== 'firefox' && browserName !== 'chromium' && browserName !== 'webkit');
1268-
if (!shouldHaveMarkerFile || (await existsAsync(browserDirectoryToMarkerFilePath(usedBrowserPath))))
1320+
1321+
if (await this._validateMarkerFile(descriptor))
12691322
usedBrowserPaths.add(usedBrowserPath);
12701323
}
12711324
} catch (e) {

0 commit comments

Comments
 (0)