Path: blob/main/plugins/default-browser-emulator/index.ts
1028 views
import BrowserEmulator from '@secret-agent/plugin-utils/lib/BrowserEmulator';1import IHttpResourceLoadDetails from '@secret-agent/interfaces/IHttpResourceLoadDetails';2import IDnsSettings from '@secret-agent/interfaces/IDnsSettings';3import ITcpSettings from '@secret-agent/interfaces/ITcpSettings';4import ITlsSettings from '@secret-agent/interfaces/ITlsSettings';5import { IPuppetPage } from '@secret-agent/interfaces/IPuppetPage';6import {7BrowserEmulatorClassDecorator,8IBrowserEmulatorConfig,9} from '@secret-agent/interfaces/ICorePlugin';10import { IPuppetWorker } from '@secret-agent/interfaces/IPuppetWorker';11import IViewport from '@secret-agent/interfaces/IViewport';12import ICorePluginCreateOptions from '@secret-agent/interfaces/ICorePluginCreateOptions';13import IUserAgentOption from '@secret-agent/interfaces/IUserAgentOption';14import BrowserEngine from '@secret-agent/plugin-utils/lib/BrowserEngine';15import IGeolocation from '@secret-agent/interfaces/IGeolocation';16import IHttp2ConnectSettings from '@secret-agent/interfaces/IHttp2ConnectSettings';17import IHttpSocketAgent from '@secret-agent/interfaces/IHttpSocketAgent';18import Viewports from './lib/Viewports';19import setWorkerDomOverrides from './lib/setWorkerDomOverrides';20import setPageDomOverrides from './lib/setPageDomOverrides';21import setUserAgent from './lib/helpers/setUserAgent';22import setScreensize from './lib/helpers/setScreensize';23import setTimezone from './lib/helpers/setTimezone';24import setLocale from './lib/helpers/setLocale';25import setActiveAndFocused from './lib/helpers/setActiveAndFocused';26import selectUserAgentOption from './lib/helpers/selectUserAgentOption';27import modifyHeaders from './lib/helpers/modifyHeaders';28import configureSessionDns from './lib/helpers/configureSessionDns';29import configureSessionTcp from './lib/helpers/configureSessionTcp';30import configureSessionTls from './lib/helpers/configureSessionTls';31import FirstPartyCookiesPlugin from './lib/plugins/FirstPartyCookiesPlugin';32import DataLoader from './lib/DataLoader';33import IBrowserData from './interfaces/IBrowserData';34import selectBrowserEngineOption from './lib/helpers/selectBrowserEngineOption';35import setGeolocation from './lib/helpers/setGeolocation';36import { configureBrowserLaunchArgs } from './lib/helpers/configureBrowserLaunchArgs';37import loadDomOverrides from './lib/loadDomOverrides';38import DomOverridesBuilder from './lib/DomOverridesBuilder';39import configureDeviceProfile from './lib/helpers/configureDeviceProfile';40import configureHttp2Session from './lib/helpers/configureHttp2Session';41import lookupPublicIp, { IpLookupServices } from './lib/helpers/lookupPublicIp';4243const dataLoader = new DataLoader(__dirname);44export const latestBrowserEngineId = 'chrome-88-0';45export const latestChromeBrowserVersion = { major: '88', minor: '0' };4647@BrowserEmulatorClassDecorator48export default class DefaultBrowserEmulator extends BrowserEmulator {49public static id = dataLoader.pkg.name.replace('@secret-agent/', '');5051public timezoneId: string;52public locale: string;53public viewport: IViewport;54public geolocation: IGeolocation;55public upstreamProxyIpMask: IBrowserEmulatorConfig['upstreamProxyIpMask'];56public upstreamProxyUrl: string;5758protected readonly data: IBrowserData;59private readonly domOverridesBuilder: DomOverridesBuilder;6061constructor(createOptions: ICorePluginCreateOptions) {62super(createOptions);63this.data = dataLoader.as(createOptions.userAgentOption) as any;6465// set default device profile options66configureDeviceProfile(this.deviceProfile);6768if (this.data.browserConfig.features.includes('FirstPartyCookies')) {69createOptions.corePlugins.use(FirstPartyCookiesPlugin);70}71this.domOverridesBuilder = loadDomOverrides(this, this.data);72}7374configure(config: IBrowserEmulatorConfig): void {75if (!config) return;7677config.locale = config.locale || this.locale || this.data.browserConfig.defaultLocale;78config.viewport =79config.viewport ||80this.viewport ||81Viewports.getDefault(this.data.windowBaseFraming, this.data.windowFraming);82config.timezoneId =83config.timezoneId || this.timezoneId || Intl.DateTimeFormat().resolvedOptions().timeZone;84config.geolocation = config.geolocation || this.geolocation;8586if (config.upstreamProxyUrl) {87config.upstreamProxyIpMask ??= {};88config.upstreamProxyIpMask.ipLookupService ??= IpLookupServices.ipify;89}9091this.locale = config.locale;92this.viewport = config.viewport;93this.timezoneId = config.timezoneId;94this.geolocation = config.geolocation;95this.upstreamProxyIpMask = config.upstreamProxyIpMask;96this.upstreamProxyUrl = config.upstreamProxyUrl;97}9899public onDnsConfiguration(settings: IDnsSettings): void {100configureSessionDns(this, settings);101}102103public onTcpConfiguration(settings: ITcpSettings): void {104configureSessionTcp(this, settings);105}106107public onTlsConfiguration(settings: ITlsSettings): void {108configureSessionTls(this, settings);109}110111public beforeHttpRequest(resource: IHttpResourceLoadDetails): void {112modifyHeaders(this, this.data, resource);113}114115public async onHttpAgentInitialized(agent: IHttpSocketAgent): Promise<void> {116if (this.upstreamProxyIpMask) {117this.upstreamProxyIpMask.publicIp ??= await lookupPublicIp(118this.upstreamProxyIpMask.ipLookupService,119);120this.upstreamProxyIpMask.proxyIp ??= await lookupPublicIp(121this.upstreamProxyIpMask.ipLookupService,122agent,123this.upstreamProxyUrl,124);125this.logger.info('PublicIp Lookup', {126...this.upstreamProxyIpMask,127});128this.domOverridesBuilder.add('webrtc', {129localIp: this.upstreamProxyIpMask.publicIp,130proxyIp: this.upstreamProxyIpMask.proxyIp,131});132}133}134135public onHttp2SessionConnect(136request: IHttpResourceLoadDetails,137settings: IHttp2ConnectSettings,138): void {139configureHttp2Session(this, this.data, request, settings);140}141142public onNewPuppetPage(page: IPuppetPage): Promise<any> {143// Don't await here! we want to queue all these up to run before the debugger resumes144const devtools = page.devtoolsSession;145return Promise.all([146setUserAgent(this, devtools),147setTimezone(this, devtools),148setLocale(this, devtools),149setScreensize(this, page, devtools),150setActiveAndFocused(this, devtools),151setPageDomOverrides(this.domOverridesBuilder, this.data, page),152setGeolocation(this, page),153]);154}155156public onNewPuppetWorker(worker: IPuppetWorker): Promise<any> {157const devtools = worker.devtoolsSession;158return Promise.all([159setUserAgent(this, devtools),160setWorkerDomOverrides(this.domOverridesBuilder, this.data, worker),161]);162}163164public static selectBrowserMeta(165userAgentSelector?: string,166): { browserEngine: BrowserEngine; userAgentOption: IUserAgentOption } {167const userAgentOption = selectUserAgentOption(userAgentSelector, dataLoader.userAgentOptions);168169const { browserName, browserVersion } = userAgentOption;170const browserEngineId = `${browserName}-${browserVersion.major}-${browserVersion.minor}`;171const browserEngineOption = selectBrowserEngineOption(172browserEngineId,173dataLoader.browserEngineOptions,174);175const browserEngine = new BrowserEngine(this, browserEngineOption);176return { browserEngine, userAgentOption };177}178179public static onBrowserWillLaunch(180browserEngine: BrowserEngine,181options: {182showBrowser?: boolean;183disableGpu?: boolean;184disableDevtools?: boolean;185},186): void {187configureBrowserLaunchArgs(browserEngine, options);188}189}190191192