feat(rpc): support firefox user prefs (#3093)

Also ignore firefoxUserPrefs in launchPersistentContext according to our api.
This commit is contained in:
Dmitry Gozman 2020-07-22 17:20:00 -07:00 committed by GitHub
parent 80c0711d98
commit 65002a0ac2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 32 additions and 15 deletions

View file

@ -170,6 +170,7 @@ export type BrowserTypeLaunchParams = {
password?: string,
},
downloadsPath?: string,
firefoxUserPrefs?: SerializedValue,
slowMo?: number,
};
export type BrowserTypeLaunchResult = {
@ -197,6 +198,7 @@ export type BrowserTypeLaunchServerParams = {
password?: string,
},
downloadsPath?: string,
firefoxUserPrefs?: SerializedValue,
port?: number,
};
export type BrowserTypeLaunchServerResult = {

View file

@ -22,6 +22,9 @@ import { ChannelOwner } from './channelOwner';
import { BrowserServer } from './browserServer';
import { LoggerSink } from '../../loggerSink';
import { headersObjectToArray, envObjectToArray } from '../serializers';
import { serializeArgument } from './jsHandle';
type FirefoxPrefsOptions = { firefoxUserPrefs?: { [key: string]: string | number | boolean } };
export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeInitializer> {
@ -41,7 +44,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
return this._initializer.name;
}
async launch(options: types.LaunchOptions & { logger?: LoggerSink } = {}): Promise<Browser> {
async launch(options: types.LaunchOptions & FirefoxPrefsOptions & { logger?: LoggerSink } = {}): Promise<Browser> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('browserType.launch', async () => {
@ -50,6 +53,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
env: options.env ? envObjectToArray(options.env) : undefined,
firefoxUserPrefs: options.firefoxUserPrefs ? serializeArgument(options.firefoxUserPrefs).value : undefined,
};
const browser = Browser.from((await this._channel.launch(launchOptions)).browser);
browser._logger = logger;
@ -57,7 +61,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
}, logger);
}
async launchServer(options: types.LaunchServerOptions & { logger?: LoggerSink } = {}): Promise<BrowserServer> {
async launchServer(options: types.LaunchServerOptions & FirefoxPrefsOptions & { logger?: LoggerSink } = {}): Promise<BrowserServer> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('browserType.launchServer', async () => {
@ -66,6 +70,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
env: options.env ? envObjectToArray(options.env) : undefined,
firefoxUserPrefs: options.firefoxUserPrefs ? serializeArgument(options.firefoxUserPrefs).value : undefined,
};
return BrowserServer.from((await this._channel.launchServer(launchServerOptions)).server);
}, logger);

View file

@ -151,6 +151,7 @@ interface BrowserType
username?: string
password?: string
downloadsPath?: string
firefoxUserPrefs?: SerializedValue
slowMo?: number
returns
browser: Browser
@ -176,6 +177,7 @@ interface BrowserType
username?: string
password?: string
downloadsPath?: string
firefoxUserPrefs?: SerializedValue
port?: number
returns
server: BrowserServer

View file

@ -24,6 +24,7 @@ import { BrowserContextBase } from '../../browserContext';
import { BrowserContextDispatcher } from './browserContextDispatcher';
import { BrowserServerDispatcher } from './browserServerDispatcher';
import { headersArrayToObject, envArrayToObject } from '../serializers';
import { parseValue } from './jsHandleDispatcher';
export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeInitializer> implements BrowserTypeChannel {
constructor(scope: DispatcherScope, browserType: BrowserTypeBase) {
@ -38,6 +39,7 @@ export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeIn
...params,
ignoreDefaultArgs: params.ignoreAllDefaultArgs ? true : params.ignoreDefaultArgs,
env: params.env ? envArrayToObject(params.env) : undefined,
firefoxUserPrefs: params.firefoxUserPrefs ? parseValue(params.firefoxUserPrefs) : undefined,
};
const browser = await this._object.launch(options);
return { browser: new BrowserDispatcher(this._scope, browser as BrowserBase) };
@ -59,6 +61,7 @@ export class BrowserTypeDispatcher extends Dispatcher<BrowserType, BrowserTypeIn
const options = {
...params,
ignoreDefaultArgs: params.ignoreAllDefaultArgs ? true : params.ignoreDefaultArgs,
firefoxUserPrefs: params.firefoxUserPrefs ? parseValue(params.firefoxUserPrefs) : undefined,
env: params.env ? envArrayToObject(params.env) : undefined,
};
return { server: new BrowserServerDispatcher(this._scope, await this._object.launchServer(options)) };

View file

@ -17,7 +17,7 @@
import { CRSession, CRSessionEvents } from '../../chromium/crConnection';
import { CDPSessionChannel, CDPSessionInitializer, SerializedValue } from '../channels';
import { Dispatcher, DispatcherScope } from './dispatcher';
import { serializeResult, parseArgument } from './jsHandleDispatcher';
import { serializeResult, parseValue } from './jsHandleDispatcher';
export class CDPSessionDispatcher extends Dispatcher<CRSession, CDPSessionInitializer> implements CDPSessionChannel {
constructor(scope: DispatcherScope, crSession: CRSession) {
@ -33,7 +33,7 @@ export class CDPSessionDispatcher extends Dispatcher<CRSession, CDPSessionInitia
}
async send(params: { method: string, params?: SerializedValue }): Promise<{ result: SerializedValue }> {
const cdpParams = params.params ? parseArgument({ value: params.params, handles: [] }) : undefined;
const cdpParams = params.params ? parseValue(params.params) : undefined;
return { result: serializeResult(await this._object.send(params.method as any, cdpParams)) };
}

View file

@ -65,6 +65,9 @@ export class JSHandleDispatcher extends Dispatcher<js.JSHandle, JSHandleInitiali
export function parseArgument(arg: SerializedArgument): any {
return parseSerializedValue(arg.value, arg.handles.map(a => (a as JSHandleDispatcher)._object));
}
export function parseValue(v: SerializedValue): any {
return parseSerializedValue(v, []);
}
export function serializeResult(arg: any): SerializedValue {
return serializeValue(arg, value => ({ fallThrough: value }), new Set());

View file

@ -73,26 +73,28 @@ export class Firefox extends BrowserTypeBase {
throw new Error('Pass userDataDir parameter instead of specifying -profile argument');
if (args.find(arg => arg.startsWith('-juggler')))
throw new Error('Use the port parameter instead of -juggler argument');
let firefoxUserPrefs = isPersistent ? undefined : options.firefoxUserPrefs;
if (proxy) {
options.firefoxUserPrefs = options.firefoxUserPrefs || {};
options.firefoxUserPrefs['network.proxy.type'] = 1;
// TODO: we should support proxy in persistent context without overriding user prefs.
firefoxUserPrefs = firefoxUserPrefs || {};
firefoxUserPrefs['network.proxy.type'] = 1;
const proxyServer = new URL(proxy.server);
const isSocks = proxyServer.protocol === 'socks5:';
if (isSocks) {
options.firefoxUserPrefs['network.proxy.socks'] = proxyServer.hostname;
options.firefoxUserPrefs['network.proxy.socks_port'] = parseInt(proxyServer.port, 10);
firefoxUserPrefs['network.proxy.socks'] = proxyServer.hostname;
firefoxUserPrefs['network.proxy.socks_port'] = parseInt(proxyServer.port, 10);
} else {
options.firefoxUserPrefs['network.proxy.http'] = proxyServer.hostname;
options.firefoxUserPrefs['network.proxy.http_port'] = parseInt(proxyServer.port, 10);
options.firefoxUserPrefs['network.proxy.ssl'] = proxyServer.hostname;
options.firefoxUserPrefs['network.proxy.ssl_port'] = parseInt(proxyServer.port, 10);
firefoxUserPrefs['network.proxy.http'] = proxyServer.hostname;
firefoxUserPrefs['network.proxy.http_port'] = parseInt(proxyServer.port, 10);
firefoxUserPrefs['network.proxy.ssl'] = proxyServer.hostname;
firefoxUserPrefs['network.proxy.ssl_port'] = parseInt(proxyServer.port, 10);
}
if (proxy.bypass)
options.firefoxUserPrefs['network.proxy.no_proxies_on'] = proxy.bypass;
firefoxUserPrefs['network.proxy.no_proxies_on'] = proxy.bypass;
}
if (options.firefoxUserPrefs) {
if (firefoxUserPrefs) {
const lines: string[] = [];
for (const [name, value] of Object.entries(options.firefoxUserPrefs))
for (const [name, value] of Object.entries(firefoxUserPrefs))
lines.push(`user_pref(${JSON.stringify(name)}, ${JSON.stringify(value)});`);
fs.writeFileSync(path.join(userDataDir, 'user.js'), lines.join('\n'));
}