mirror of
https://github.com/microsoft/playwright.git
synced 2024-11-10 12:57:42 +03:00
feat(firefox): support downloads (#1689)
This commit is contained in:
parent
949dc7b514
commit
a7ae205254
@ -9,7 +9,7 @@
|
||||
"main": "index.js",
|
||||
"playwright": {
|
||||
"chromium_revision": "754895",
|
||||
"firefox_revision": "1072",
|
||||
"firefox_revision": "1074",
|
||||
"webkit_revision": "1188"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -53,7 +53,7 @@ export abstract class BrowserBase extends EventEmitter implements Browser {
|
||||
this._downloads.set(uuid, download);
|
||||
}
|
||||
|
||||
_downloadFinished(uuid: string, error: string) {
|
||||
_downloadFinished(uuid: string, error?: string) {
|
||||
const download = this._downloads.get(uuid);
|
||||
if (!download)
|
||||
return;
|
||||
|
@ -81,7 +81,7 @@ export class Download {
|
||||
await util.promisify(fs.unlink)(fileName).catch(e => {});
|
||||
}
|
||||
|
||||
_reportFinished(error: string) {
|
||||
_reportFinished(error?: string) {
|
||||
this._failure = error || null;
|
||||
this._finishedCallback();
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ export class FFBrowser extends BrowserBase {
|
||||
this._eventListeners = [
|
||||
helper.addEventListener(this._connection, 'Browser.attachedToTarget', this._onAttachedToTarget.bind(this)),
|
||||
helper.addEventListener(this._connection, 'Browser.detachedFromTarget', this._onDetachedFromTarget.bind(this)),
|
||||
helper.addEventListener(this._connection, 'Browser.downloadCreated', this._onDownloadCreated.bind(this)),
|
||||
helper.addEventListener(this._connection, 'Browser.downloadFinished', this._onDownloadFinished.bind(this)),
|
||||
];
|
||||
this._firstPagePromise = new Promise(f => this._firstPageCallback = f);
|
||||
}
|
||||
@ -96,7 +98,11 @@ export class FFBrowser extends BrowserBase {
|
||||
viewport,
|
||||
locale: options.locale,
|
||||
timezoneId: options.timezoneId,
|
||||
removeOnDetach: true
|
||||
removeOnDetach: true,
|
||||
downloadOptions: {
|
||||
behavior: options.acceptDownloads ? 'saveToDisk' : 'cancel',
|
||||
downloadsDir: this._downloadsPath,
|
||||
},
|
||||
});
|
||||
const context = new FFBrowserContext(this, browserContextId, options);
|
||||
await context._initialize();
|
||||
@ -135,6 +141,19 @@ export class FFBrowser extends BrowserBase {
|
||||
});
|
||||
}
|
||||
|
||||
_onDownloadCreated(payload: Protocol.Browser.downloadCreatedPayload) {
|
||||
const ffPage = this._ffPages.get(payload.pageTargetId)!;
|
||||
assert(ffPage);
|
||||
if (!ffPage)
|
||||
return;
|
||||
this._downloadCreated(ffPage._page, payload.uuid, payload.url);
|
||||
}
|
||||
|
||||
_onDownloadFinished(payload: Protocol.Browser.downloadFinishedPayload) {
|
||||
const error = payload.canceled ? 'canceled' : payload.error;
|
||||
this._downloadFinished(payload.uuid, error);
|
||||
}
|
||||
|
||||
_disconnect() {
|
||||
helper.removeEventListeners(this._eventListeners);
|
||||
this._connection.close();
|
||||
|
@ -49,16 +49,17 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
|
||||
async launch(options: LaunchOptions = {}): Promise<FFBrowser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const browserServer = await this._launchServer(options, 'local');
|
||||
const {browserServer, downloadsPath} = await this._launchServer(options, 'local');
|
||||
const browser = await WebSocketTransport.connect(browserServer.wsEndpoint()!, transport => {
|
||||
return FFBrowser.connect(transport, false, options.slowMo);
|
||||
});
|
||||
browser._ownedServer = browserServer;
|
||||
browser._downloadsPath = downloadsPath;
|
||||
return browser;
|
||||
}
|
||||
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
return await this._launchServer(options, 'server');
|
||||
return (await this._launchServer(options, 'server')).browserServer;
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
@ -66,17 +67,18 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
timeout = 30000,
|
||||
slowMo = 0,
|
||||
} = options;
|
||||
const browserServer = await this._launchServer(options, 'persistent', userDataDir);
|
||||
const {browserServer, downloadsPath} = await this._launchServer(options, 'persistent', userDataDir);
|
||||
const browser = await WebSocketTransport.connect(browserServer.wsEndpoint()!, transport => {
|
||||
return FFBrowser.connect(transport, true, slowMo);
|
||||
});
|
||||
browser._ownedServer = browserServer;
|
||||
browser._downloadsPath = downloadsPath;
|
||||
await helper.waitWithTimeout(browser._firstPagePromise, 'first page', timeout);
|
||||
const browserContext = browser._defaultContext;
|
||||
return browserContext;
|
||||
}
|
||||
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<BrowserServer> {
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, userDataDir?: string): Promise<{ browserServer: BrowserServer, downloadsPath: string }> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
@ -110,7 +112,7 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
if (!firefoxExecutable)
|
||||
throw new Error(`No executable path is specified. Pass "executablePath" option directly.`);
|
||||
|
||||
const { launchedProcess, gracefullyClose } = await launchProcess({
|
||||
const { launchedProcess, gracefullyClose, downloadsPath } = await launchProcess({
|
||||
executablePath: firefoxExecutable,
|
||||
args: firefoxArguments,
|
||||
env: os.platform() === 'linux' ? {
|
||||
@ -146,7 +148,7 @@ export class Firefox implements BrowserType<FFBrowser> {
|
||||
const webSocketWrapper = launchType === 'server' ? (await WebSocketTransport.connect(innerEndpoint, t => wrapTransportWithWebSocket(t, port))) : new WebSocketWrapper(innerEndpoint, []);
|
||||
browserWSEndpoint = webSocketWrapper.wsEndpoint;
|
||||
browserServer = new BrowserServer(launchedProcess, gracefullyClose, webSocketWrapper);
|
||||
return browserServer;
|
||||
return {browserServer, downloadsPath};
|
||||
}
|
||||
|
||||
async connect(options: ConnectOptions): Promise<FFBrowser> {
|
||||
|
@ -17,9 +17,9 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports.describe = function({browserType, CHROMIUM, WEBKIT, FFOX, WIN, MAC}) {
|
||||
module.exports.describe = function({browserType, defaultBrowserOptions, CHROMIUM, WEBKIT, FFOX, WIN, MAC}) {
|
||||
|
||||
describe.fail(FFOX)('Download', function() {
|
||||
describe('Download', function() {
|
||||
beforeEach(async(state) => {
|
||||
state.server.setRoute('/download', (req, res) => {
|
||||
res.setHeader('Content-Type', 'application/octet-stream');
|
||||
@ -97,7 +97,7 @@ module.exports.describe = function({browserType, CHROMIUM, WEBKIT, FFOX, WIN, MA
|
||||
expect(fs.existsSync(path1)).toBeFalsy();
|
||||
expect(fs.existsSync(path2)).toBeFalsy();
|
||||
});
|
||||
it('should delete downloads on browser gone', async ({ server, defaultBrowserOptions }) => {
|
||||
it('should delete downloads on browser gone', async ({ server }) => {
|
||||
const browser = await browserType.launch(defaultBrowserOptions);
|
||||
const page = await browser.newPage({ acceptDownloads: true });
|
||||
await page.setContent(`<a download=true href="${server.PREFIX}/download">download</a>`);
|
||||
|
@ -30,8 +30,7 @@ const BROWSER_CONFIGS = [
|
||||
...require('../lib/events').Events,
|
||||
...require('../lib/chromium/events').Events,
|
||||
},
|
||||
missingCoverage: ['browserContext.setGeolocation', 'browserContext.setOffline', 'cDPSession.send', 'cDPSession.detach', 'page.emit("download")',
|
||||
'download.url', 'download.path', 'download.failure', 'download.createReadStream', 'download.delete'],
|
||||
missingCoverage: ['browserContext.setGeolocation', 'browserContext.setOffline', 'cDPSession.send', 'cDPSession.detach'],
|
||||
},
|
||||
{
|
||||
name: 'WebKit',
|
||||
|
Loading…
Reference in New Issue
Block a user