Skip to content

Commit bc04a51

Browse files
committed
feat: support webkit technology preview
This patch adds support for `technology preview` webkit channel, which we will keep close to the actual Safari Technology Preview releases. This channel does not install by default. It is supposed to be installed with the following CLI command: ```sh $ npx playwright install webkit-technology-preview ``` Once the channel is installed, it can be used the following way: ```js const browser = await playwright.webkit.launch({ channel: 'technology-preview', }); ``` **NOTE:** if clients attempt using the channel without installing it, it'll throw an error with a copyable instructions to install via CLI. References #5884
1 parent 1f1c8b7 commit bc04a51

File tree

8 files changed

+89
-31
lines changed

8 files changed

+89
-31
lines changed

browsers.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@
1919
"mac10.14": "1443"
2020
}
2121
},
22+
{
23+
"name": "webkit-technology-preview",
24+
"revision": "1443",
25+
"download": true,
26+
"installationSources": ["cli"]
27+
},
2228
{
2329
"name": "ffmpeg",
2430
"revision": "1005",

packages/build_package.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const PLAYWRIGHT_CORE_FILES = ['bin/PrintDeps.exe', 'lib', 'types', 'NOTICE', 'L
3333
const PACKAGES = {
3434
'playwright': {
3535
description: 'A high-level API to automate web browsers',
36-
browsers: ['chromium', 'firefox', 'webkit', 'ffmpeg'],
36+
browsers: ['chromium', 'firefox', 'webkit', 'ffmpeg', 'webkit-technology-preview'],
3737
// We copy README.md additionally for Playwright so that it looks nice on NPM.
3838
files: [...PLAYWRIGHT_CORE_FILES, 'README.md'],
3939
},
@@ -44,7 +44,7 @@ const PACKAGES = {
4444
},
4545
'playwright-webkit': {
4646
description: 'A high-level API to automate WebKit',
47-
browsers: ['webkit'],
47+
browsers: ['webkit', 'webkit-technology-preview'],
4848
files: PLAYWRIGHT_CORE_FILES,
4949
},
5050
'playwright-firefox': {

src/cli/cli.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { BrowserType } from '../client/browserType';
3232
import { BrowserContextOptions, LaunchOptions } from '../client/types';
3333
import { spawn } from 'child_process';
3434
import { installDeps } from '../install/installDeps';
35+
import { allBrowserNames } from '../utils/registry';
3536

3637
program
3738
.version('Version ' + require('../../package.json').version)
@@ -85,10 +86,10 @@ program
8586
.description('ensure browsers necessary for this version of Playwright are installed')
8687
.action(async function(browserType) {
8788
try {
88-
const allBrowsers = new Set(['chromium', 'firefox', 'webkit', 'ffmpeg']);
89+
const allBrowsers = new Set(allBrowserNames);
8990
for (const type of browserType) {
9091
if (!allBrowsers.has(type)) {
91-
console.log(`Invalid browser name: '${type}'. Expecting 'chromium', 'firefox' or 'webkit'.`);
92+
console.log(`Invalid browser name: '${type}'. Expecting one of: ${allBrowserNames.map(name => `'${name}'`).join(', ')}`);
9293
process.exit(1);
9394
}
9495
}

src/cli/driver.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,5 @@ export async function launchBrowserServer(browserName: string, configFile?: stri
6666
}
6767

6868
export async function installBrowsers(browserNames?: BrowserName[]) {
69-
await installBrowsersWithProgressBar(browserNames);
69+
await installBrowsersWithProgressBar(browserNames, 'cli');
7070
}

src/install/installer.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import fs from 'fs';
1818
import path from 'path';
1919
import util from 'util';
2020
import lockfile from 'proper-lockfile';
21-
import {Registry, allBrowserNames, isBrowserDirectory, BrowserName, registryDirectory} from '../utils/registry';
21+
import {Registry, allBrowserNames, isBrowserDirectory, BrowserName, registryDirectory, InstallationSource} from '../utils/registry';
2222
import * as browserFetcher from './browserFetcher';
2323
import { getAsBooleanFromENV, calculateSha1, removeFolders } from '../utils/utils';
2424

@@ -31,7 +31,7 @@ const fsWriteFileAsync = util.promisify(fs.writeFile.bind(fs));
3131

3232
const PACKAGE_PATH = path.join(__dirname, '..', '..');
3333

34-
export async function installBrowsersWithProgressBar(browserNames: BrowserName[] = allBrowserNames) {
34+
export async function installBrowsersWithProgressBar(browserNames: BrowserName[] = allBrowserNames, installationSource : InstallationSource = 'default') {
3535
// PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1
3636
if (getAsBooleanFromENV('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {
3737
browserFetcher.logPolitely('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');
@@ -58,13 +58,13 @@ export async function installBrowsersWithProgressBar(browserNames: BrowserName[]
5858
try {
5959
await fsMkdirAsync(linksDir, { recursive: true });
6060
await fsWriteFileAsync(path.join(linksDir, calculateSha1(PACKAGE_PATH)), PACKAGE_PATH);
61-
await validateCache(linksDir, browserNames);
61+
await validateCache(linksDir, browserNames, installationSource);
6262
} finally {
6363
await releaseLock();
6464
}
6565
}
6666

67-
async function validateCache(linksDir: string, browserNames: BrowserName[]) {
67+
async function validateCache(linksDir: string, browserNames: BrowserName[], installationSource: InstallationSource) {
6868
// 1. Collect used downloads and package descriptors.
6969
const usedBrowserPaths: Set<string> = new Set();
7070
for (const fileName of await fsReaddirAsync(linksDir)) {
@@ -74,7 +74,7 @@ async function validateCache(linksDir: string, browserNames: BrowserName[]) {
7474
linkTarget = (await fsReadFileAsync(linkPath)).toString();
7575
const linkRegistry = new Registry(linkTarget);
7676
for (const browserName of allBrowserNames) {
77-
if (!linkRegistry.shouldDownload(browserName))
77+
if (!linkRegistry.shouldRetain(browserName))
7878
continue;
7979
const usedBrowserPath = linkRegistry.browserDirectory(browserName);
8080
const browserRevision = linkRegistry.revision(browserName);
@@ -107,7 +107,7 @@ async function validateCache(linksDir: string, browserNames: BrowserName[]) {
107107
// 3. Install missing browsers for this package.
108108
const myRegistry = new Registry(PACKAGE_PATH);
109109
for (const browserName of browserNames) {
110-
if (!myRegistry.shouldDownload(browserName))
110+
if (!myRegistry.shouldDownload(browserName, installationSource))
111111
continue;
112112
await browserFetcher.downloadBrowserWithProgressBar(myRegistry, browserName).catch(e => {
113113
throw new Error(`Failed to download ${browserName}, caused by\n${e.stack}`);

src/server/validateDependencies.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ export async function validateHostRequirements(registry: registry.Registry, brow
4343
}
4444

4545
const DL_OPEN_LIBRARIES = {
46-
chromium: [],
47-
webkit: ['libGLESv2.so.2', 'libx264.so'],
48-
firefox: [],
49-
clank: [],
50-
ffmpeg: [],
46+
'chromium': [],
47+
'webkit': ['libGLESv2.so.2', 'libx264.so'],
48+
'webkit-technology-preview': ['libGLESv2.so.2', 'libx264.so'],
49+
'firefox': [],
50+
'clank': [],
51+
'ffmpeg': [],
5152
};
5253

5354
function isSupportedWindowsVersion(): boolean {

src/server/webkit/webkit.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,26 @@ import { BrowserType } from '../browserType';
2323
import { ConnectionTransport } from '../transport';
2424
import { BrowserOptions, PlaywrightOptions } from '../browser';
2525
import * as types from '../types';
26+
import * as fs from 'fs';
27+
import { assert } from '../../utils/utils';
2628

2729
export class WebKit extends BrowserType {
2830
constructor(playwrightOptions: PlaywrightOptions) {
2931
super('webkit', playwrightOptions);
3032
}
3133

34+
executablePath(options?: types.LaunchOptions): string {
35+
if (options?.channel) {
36+
let executablePath = undefined;
37+
if (options.channel === 'technology-preview')
38+
executablePath = this._registry.executablePath('webkit-technology-preview');
39+
assert(executablePath, `unsupported webkit channel "${options.channel}"`);
40+
assert(fs.existsSync(executablePath), `webkit channel "${options.channel}" is not installed. Try running 'npx playwright install webkit-technology-preview'`);
41+
return executablePath;
42+
}
43+
return super.executablePath(options);
44+
}
45+
3246
_connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<WKBrowser> {
3347
return WKBrowser.connect(transport, options);
3448
}

src/utils/registry.ts

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,21 @@ import * as util from 'util';
2323
import { getUbuntuVersionSync } from './ubuntuVersion';
2424
import { assert, getFromENV } from './utils';
2525

26-
export type BrowserName = 'chromium'|'webkit'|'firefox'|'ffmpeg';
27-
export const allBrowserNames: BrowserName[] = ['chromium', 'webkit', 'firefox', 'ffmpeg'];
26+
export type InstallationSource = 'default'|'cli';
27+
export type BrowserName = 'chromium'|'webkit'|'webkit-technology-preview'|'firefox'|'ffmpeg';
28+
export const allBrowserNames: BrowserName[] = ['chromium', 'webkit', 'webkit-technology-preview', 'firefox', 'ffmpeg'];
2829

2930
type BrowserPlatform = 'win32'|'win64'|'mac10.13'|'mac10.14'|'mac10.15'|'mac11'|'mac11-arm64'|'ubuntu18.04'|'ubuntu20.04';
3031
type BrowserDescriptor = {
3132
name: BrowserName,
3233
revision: string,
3334
download: boolean,
3435
browserDirectory: string,
36+
installationSources: Set<InstallationSource>,
3537
};
3638

3739
const EXECUTABLE_PATHS = {
38-
chromium: {
40+
'chromium': {
3941
'ubuntu18.04': ['chrome-linux', 'chrome'],
4042
'ubuntu20.04': ['chrome-linux', 'chrome'],
4143
'mac10.13': ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'],
@@ -46,7 +48,7 @@ const EXECUTABLE_PATHS = {
4648
'win32': ['chrome-win', 'chrome.exe'],
4749
'win64': ['chrome-win', 'chrome.exe'],
4850
},
49-
firefox: {
51+
'firefox': {
5052
'ubuntu18.04': ['firefox', 'firefox'],
5153
'ubuntu20.04': ['firefox', 'firefox'],
5254
'mac10.13': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'],
@@ -57,7 +59,7 @@ const EXECUTABLE_PATHS = {
5759
'win32': ['firefox', 'firefox.exe'],
5860
'win64': ['firefox', 'firefox.exe'],
5961
},
60-
webkit: {
62+
'webkit': {
6163
'ubuntu18.04': ['pw_run.sh'],
6264
'ubuntu20.04': ['pw_run.sh'],
6365
'mac10.13': undefined,
@@ -68,7 +70,18 @@ const EXECUTABLE_PATHS = {
6870
'win32': ['Playwright.exe'],
6971
'win64': ['Playwright.exe'],
7072
},
71-
ffmpeg: {
73+
'webkit-technology-preview': {
74+
'ubuntu18.04': ['pw_run.sh'],
75+
'ubuntu20.04': ['pw_run.sh'],
76+
'mac10.13': undefined,
77+
'mac10.14': ['pw_run.sh'],
78+
'mac10.15': ['pw_run.sh'],
79+
'mac11': ['pw_run.sh'],
80+
'mac11-arm64': ['pw_run.sh'],
81+
'win32': ['Playwright.exe'],
82+
'win64': ['Playwright.exe'],
83+
},
84+
'ffmpeg': {
7285
'ubuntu18.04': ['ffmpeg-linux'],
7386
'ubuntu20.04': ['ffmpeg-linux'],
7487
'mac10.13': ['ffmpeg-mac'],
@@ -82,7 +95,7 @@ const EXECUTABLE_PATHS = {
8295
};
8396

8497
const DOWNLOAD_URLS = {
85-
chromium: {
98+
'chromium': {
8699
'ubuntu18.04': '%s/builds/chromium/%s/chromium-linux.zip',
87100
'ubuntu20.04': '%s/builds/chromium/%s/chromium-linux.zip',
88101
'mac10.13': '%s/builds/chromium/%s/chromium-mac.zip',
@@ -93,7 +106,7 @@ const DOWNLOAD_URLS = {
93106
'win32': '%s/builds/chromium/%s/chromium-win32.zip',
94107
'win64': '%s/builds/chromium/%s/chromium-win64.zip',
95108
},
96-
firefox: {
109+
'firefox': {
97110
'ubuntu18.04': '%s/builds/firefox/%s/firefox-ubuntu-18.04.zip',
98111
'ubuntu20.04': '%s/builds/firefox/%s/firefox-ubuntu-18.04.zip',
99112
'mac10.13': '%s/builds/firefox/%s/firefox-mac-10.14.zip',
@@ -104,7 +117,7 @@ const DOWNLOAD_URLS = {
104117
'win32': '%s/builds/firefox/%s/firefox-win32.zip',
105118
'win64': '%s/builds/firefox/%s/firefox-win64.zip',
106119
},
107-
webkit: {
120+
'webkit': {
108121
'ubuntu18.04': '%s/builds/webkit/%s/webkit-ubuntu-18.04.zip',
109122
'ubuntu20.04': '%s/builds/webkit/%s/webkit-ubuntu-20.04.zip',
110123
'mac10.13': undefined,
@@ -115,7 +128,18 @@ const DOWNLOAD_URLS = {
115128
'win32': '%s/builds/webkit/%s/webkit-win64.zip',
116129
'win64': '%s/builds/webkit/%s/webkit-win64.zip',
117130
},
118-
ffmpeg: {
131+
'webkit-technology-preview': {
132+
'ubuntu18.04': '%s/builds/webkit/%s/webkit-ubuntu-18.04.zip',
133+
'ubuntu20.04': '%s/builds/webkit/%s/webkit-ubuntu-20.04.zip',
134+
'mac10.13': undefined,
135+
'mac10.14': undefined,
136+
'mac10.15': '%s/builds/webkit/%s/webkit-mac-10.15.zip',
137+
'mac11': '%s/builds/webkit/%s/webkit-mac-10.15.zip',
138+
'mac11-arm64': '%s/builds/webkit/%s/webkit-mac-11.0-arm64.zip',
139+
'win32': '%s/builds/webkit/%s/webkit-win64.zip',
140+
'win64': '%s/builds/webkit/%s/webkit-win64.zip',
141+
},
142+
'ffmpeg': {
119143
'ubuntu18.04': '%s/builds/ffmpeg/%s/ffmpeg-linux.zip',
120144
'ubuntu20.04': '%s/builds/ffmpeg/%s/ffmpeg-linux.zip',
121145
'mac10.13': '%s/builds/ffmpeg/%s/ffmpeg-mac.zip',
@@ -209,11 +233,13 @@ export class Registry {
209233
const revisionOverride = (obj.revisionOverrides || {})[hostPlatform];
210234
const revision = revisionOverride || obj.revision;
211235
const browserDirectory = revisionOverride ? `${name}-${hostPlatform}-special-${revision}` : `${name}-${revision}`;
236+
const installationSources = new Set(obj.installationSources || ['default']);
212237
return {
213238
name,
214239
revision,
215240
download: obj.download,
216241
browserDirectory,
242+
installationSources,
217243
};
218244
});
219245
}
@@ -270,10 +296,11 @@ export class Registry {
270296
const browser = this._descriptors.find(browser => browser.name === browserName);
271297
assert(browser, `ERROR: Playwright does not support ${browserName}`);
272298
const envDownloadHost: { [key: string]: string } = {
273-
chromium: 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST',
274-
firefox: 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST',
275-
webkit: 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST',
276-
ffmpeg: 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST',
299+
'chromium': 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST',
300+
'firefox': 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST',
301+
'webkit': 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST',
302+
'webkit-technology-preview': 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST',
303+
'ffmpeg': 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST',
277304
};
278305
const downloadHost = getFromENV(envDownloadHost[browserName]) ||
279306
getFromENV('PLAYWRIGHT_DOWNLOAD_HOST') ||
@@ -283,7 +310,16 @@ export class Registry {
283310
return util.format(urlTemplate, downloadHost, browser.revision);
284311
}
285312

286-
shouldDownload(browserName: BrowserName): boolean {
313+
shouldDownload(browserName: BrowserName, installationSource: InstallationSource): boolean {
314+
// Older versions do not have "download" field. We assume they need all browsers
315+
// from the list. So we want to skip all browsers that are explicitly marked as "download: false".
316+
const browser = this._descriptors.find(browser => browser.name === browserName);
317+
if (!browser || browser.download === false)
318+
return false;
319+
return browser.installationSources.has(installationSource);
320+
}
321+
322+
shouldRetain(browserName: BrowserName): boolean {
287323
// Older versions do not have "download" field. We assume they need all browsers
288324
// from the list. So we want to skip all browsers that are explicitly marked as "download: false".
289325
const browser = this._descriptors.find(browser => browser.name === browserName);

0 commit comments

Comments
 (0)