2020-06-26 01:05:36 +02:00
/ * *
* Copyright 2017 Google Inc . All rights reserved .
* Modifications copyright ( c ) Microsoft Corporation .
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
2020-12-27 02:05:57 +01:00
import { Page , BindingCall } from './page' ;
2021-08-16 21:49:10 +02:00
import { Frame } from './frame' ;
2020-06-26 01:05:36 +02:00
import * as network from './network' ;
2020-08-25 02:05:16 +02:00
import * as channels from '../protocol/channels' ;
2021-02-11 15:36:15 +01:00
import fs from 'fs' ;
2020-06-26 01:05:36 +02:00
import { ChannelOwner } from './channelOwner' ;
2021-08-24 20:45:50 +02:00
import { deprecate , evaluationScript } from './clientHelper' ;
2020-06-26 01:05:36 +02:00
import { Browser } from './browser' ;
2021-04-02 03:47:14 +02:00
import { Worker } from './worker' ;
2020-07-30 02:26:59 +02:00
import { Events } from './events' ;
2020-08-23 00:13:51 +02:00
import { TimeoutSettings } from '../utils/timeoutSettings' ;
2020-07-14 01:03:24 +02:00
import { Waiter } from './waiter' ;
2021-01-25 23:49:26 +01:00
import { URLMatch , Headers , WaitForEventOptions , BrowserContextOptions , StorageState , LaunchOptions } from './types' ;
2021-09-13 21:43:07 +02:00
import { isUnderTest , headersObjectToArray , mkdirIfNeeded } from '../utils/utils' ;
2020-10-01 06:17:30 +02:00
import { isSafeCloseError } from '../utils/errors' ;
2020-12-27 02:05:57 +01:00
import * as api from '../../types/types' ;
import * as structs from '../../types/structs' ;
2021-04-02 03:47:14 +02:00
import { CDPSession } from './cdpSession' ;
2021-04-25 05:39:48 +02:00
import { Tracing } from './tracing' ;
2021-08-10 03:09:11 +02:00
import type { BrowserType } from './browserType' ;
2021-08-26 20:26:08 +02:00
import { Artifact } from './artifact' ;
2021-09-13 21:43:07 +02:00
import { FetchRequest } from './fetch' ;
2020-06-26 01:05:36 +02:00
2020-12-27 02:05:57 +01:00
export class BrowserContext extends ChannelOwner < channels.BrowserContextChannel , channels.BrowserContextInitializer > implements api . BrowserContext {
2020-06-26 01:05:36 +02:00
_pages = new Set < Page > ( ) ;
2021-08-24 20:45:50 +02:00
private _routes : network.RouteHandler [ ] = [ ] ;
2020-09-14 16:50:47 +02:00
readonly _browser : Browser | null = null ;
2021-08-10 03:09:11 +02:00
private _browserType : BrowserType | undefined ;
2020-12-27 02:05:57 +01:00
readonly _bindings = new Map < string , ( source : structs.BindingSource , ...args : any [ ] ) = > any > ( ) ;
2020-06-27 06:22:03 +02:00
_timeoutSettings = new TimeoutSettings ( ) ;
2020-06-30 01:37:38 +02:00
_ownerPage : Page | undefined ;
2020-07-10 00:33:01 +02:00
private _closedPromise : Promise < void > ;
2021-08-20 21:32:21 +02:00
_options : channels.BrowserNewContextParams = { } ;
2020-06-26 01:05:36 +02:00
2021-09-14 21:56:09 +02:00
readonly _request : FetchRequest ;
2021-05-12 21:21:54 +02:00
readonly tracing : Tracing ;
2021-04-02 03:47:14 +02:00
readonly _backgroundPages = new Set < Page > ( ) ;
readonly _serviceWorkers = new Set < Worker > ( ) ;
readonly _isChromium : boolean ;
2020-08-25 02:05:16 +02:00
static from ( context : channels.BrowserContextChannel ) : BrowserContext {
2020-07-02 03:36:09 +02:00
return ( context as any ) . _object ;
2020-06-26 01:05:36 +02:00
}
2020-08-25 02:05:16 +02:00
static fromNullable ( context : channels.BrowserContextChannel | null ) : BrowserContext | null {
2020-06-26 01:05:36 +02:00
return context ? BrowserContext . from ( context ) : null ;
}
2021-01-13 21:08:14 +01:00
constructor ( parent : ChannelOwner , type : string , guid : string , initializer : channels.BrowserContextInitializer ) {
2020-07-27 19:21:39 +02:00
super ( parent , type , guid , initializer ) ;
2020-07-14 06:46:59 +02:00
if ( parent instanceof Browser )
2020-07-14 00:26:09 +02:00
this . _browser = parent ;
2021-04-02 03:47:14 +02:00
this . _isChromium = this . _browser ? . _name === 'chromium' ;
2021-05-12 21:21:54 +02:00
this . tracing = new Tracing ( this ) ;
2021-09-15 03:31:35 +02:00
this . _request = FetchRequest . from ( initializer . fetchRequest ) ;
2020-07-14 00:26:09 +02:00
2021-09-27 18:58:08 +02:00
this . _channel . on ( 'bindingCall' , ( { binding } ) = > this . _onBinding ( BindingCall . from ( binding ) ) ) ;
2020-06-30 19:55:11 +02:00
this . _channel . on ( 'close' , ( ) = > this . _onClose ( ) ) ;
2021-09-27 18:58:08 +02:00
this . _channel . on ( 'page' , ( { page } ) = > this . _onPage ( Page . from ( page ) ) ) ;
2020-06-30 19:55:11 +02:00
this . _channel . on ( 'route' , ( { route , request } ) = > this . _onRoute ( network . Route . from ( route ) , network . Request . from ( request ) ) ) ;
2021-04-02 03:47:14 +02:00
this . _channel . on ( 'backgroundPage' , ( { page } ) = > {
const backgroundPage = Page . from ( page ) ;
this . _backgroundPages . add ( backgroundPage ) ;
this . emit ( Events . BrowserContext . BackgroundPage , backgroundPage ) ;
} ) ;
2021-09-27 18:58:08 +02:00
this . _channel . on ( 'serviceWorker' , ( { worker } ) = > {
2021-04-02 03:47:14 +02:00
const serviceWorker = Worker . from ( worker ) ;
serviceWorker . _context = this ;
this . _serviceWorkers . add ( serviceWorker ) ;
this . emit ( Events . BrowserContext . ServiceWorker , serviceWorker ) ;
} ) ;
2021-05-13 19:29:14 +02:00
this . _channel . on ( 'request' , ( { request , page } ) = > this . _onRequest ( network . Request . from ( request ) , Page . fromNullable ( page ) ) ) ;
this . _channel . on ( 'requestFailed' , ( { request , failureText , responseEndTiming , page } ) = > this . _onRequestFailed ( network . Request . from ( request ) , responseEndTiming , failureText , Page . fromNullable ( page ) ) ) ;
2021-08-31 05:43:40 +02:00
this . _channel . on ( 'requestFinished' , params = > this . _onRequestFinished ( params ) ) ;
2021-05-13 19:29:14 +02:00
this . _channel . on ( 'response' , ( { response , page } ) = > this . _onResponse ( network . Response . from ( response ) , Page . fromNullable ( page ) ) ) ;
2020-07-10 00:33:01 +02:00
this . _closedPromise = new Promise ( f = > this . once ( Events . BrowserContext . Close , f ) ) ;
2020-06-26 01:05:36 +02:00
}
2021-08-10 03:09:11 +02:00
_setBrowserType ( browserType : BrowserType ) {
this . _browserType = browserType ;
browserType . _contexts . add ( this ) ;
}
2020-06-26 21:28:27 +02:00
private _onPage ( page : Page ) : void {
this . _pages . add ( page ) ;
this . emit ( Events . BrowserContext . Page , page ) ;
2021-04-02 20:15:07 +02:00
if ( page . _opener && ! page . _opener . isClosed ( ) )
page . _opener . emit ( Events . Page . Popup , page ) ;
2020-06-26 21:28:27 +02:00
}
2020-06-26 20:51:47 +02:00
2021-05-13 19:29:14 +02:00
private _onRequest ( request : network.Request , page : Page | null ) {
this . emit ( Events . BrowserContext . Request , request ) ;
if ( page )
page . emit ( Events . Page . Request , request ) ;
}
private _onResponse ( response : network.Response , page : Page | null ) {
this . emit ( Events . BrowserContext . Response , response ) ;
if ( page )
page . emit ( Events . Page . Response , response ) ;
}
private _onRequestFailed ( request : network.Request , responseEndTiming : number , failureText : string | undefined , page : Page | null ) {
request . _failureText = failureText || null ;
if ( request . _timing )
request . _timing . responseEnd = responseEndTiming ;
this . emit ( Events . BrowserContext . RequestFailed , request ) ;
if ( page )
page . emit ( Events . Page . RequestFailed , request ) ;
}
2021-08-31 05:43:40 +02:00
private _onRequestFinished ( params : channels.BrowserContextRequestFinishedEvent ) {
2021-09-02 19:39:57 +02:00
const { responseEndTiming } = params ;
2021-08-31 05:43:40 +02:00
const request = network . Request . from ( params . request ) ;
const response = network . Response . fromNullable ( params . response ) ;
const page = Page . fromNullable ( params . page ) ;
2021-05-13 19:29:14 +02:00
if ( request . _timing )
request . _timing . responseEnd = responseEndTiming ;
this . emit ( Events . BrowserContext . RequestFinished , request ) ;
if ( page )
page . emit ( Events . Page . RequestFinished , request ) ;
2021-08-31 05:43:40 +02:00
if ( response )
response . _finishedPromise . resolve ( ) ;
2021-05-13 19:29:14 +02:00
}
2020-06-26 20:51:47 +02:00
_onRoute ( route : network.Route , request : network.Request ) {
2021-08-24 20:45:50 +02:00
for ( const routeHandler of this . _routes ) {
if ( routeHandler . matches ( request . url ( ) ) ) {
routeHandler . handle ( route , request ) ;
2020-06-26 20:51:47 +02:00
return ;
}
}
2021-03-09 04:53:19 +01:00
// it can race with BrowserContext.close() which then throws since its closed
route . continue ( ) . catch ( ( ) = > { } ) ;
2020-06-26 20:51:47 +02:00
}
async _onBinding ( bindingCall : BindingCall ) {
2020-06-26 21:28:27 +02:00
const func = this . _bindings . get ( bindingCall . _initializer . name ) ;
2020-06-26 20:51:47 +02:00
if ( ! func )
return ;
2021-03-22 17:59:39 +01:00
await bindingCall . call ( func ) ;
2020-06-26 01:05:36 +02:00
}
setDefaultNavigationTimeout ( timeout : number ) {
2020-07-14 01:03:24 +02:00
this . _timeoutSettings . setDefaultNavigationTimeout ( timeout ) ;
2020-06-26 01:05:36 +02:00
this . _channel . setDefaultNavigationTimeoutNoReply ( { timeout } ) ;
}
setDefaultTimeout ( timeout : number ) {
2020-06-27 06:22:03 +02:00
this . _timeoutSettings . setDefaultTimeout ( timeout ) ;
2020-06-26 01:05:36 +02:00
this . _channel . setDefaultTimeoutNoReply ( { timeout } ) ;
}
2020-09-14 16:50:47 +02:00
browser ( ) : Browser | null {
return this . _browser ;
}
2020-06-26 01:05:36 +02:00
pages ( ) : Page [ ] {
return [ . . . this . _pages ] ;
}
async newPage ( ) : Promise < Page > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2020-07-16 23:32:21 +02:00
if ( this . _ownerPage )
throw new Error ( 'Please use browser.newContext()' ) ;
2021-02-20 01:21:39 +01:00
return Page . from ( ( await channel . newPage ( ) ) . page ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
async cookies ( urls? : string | string [ ] ) : Promise < network.NetworkCookie [ ] > {
if ( ! urls )
urls = [ ] ;
if ( urls && typeof urls === 'string' )
urls = [ urls ] ;
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
return ( await channel . cookies ( { urls : urls as string [ ] } ) ) . cookies ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
async addCookies ( cookies : network.SetNetworkCookieParam [ ] ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . addCookies ( { cookies } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
async clearCookies ( ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . clearCookies ( ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
async grantPermissions ( permissions : string [ ] , options ? : { origin? : string } ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . grantPermissions ( { permissions , . . . options } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
async clearPermissions ( ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . clearPermissions ( ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
2020-07-30 02:26:59 +02:00
async setGeolocation ( geolocation : { longitude : number , latitude : number , accuracy? : number } | null ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . setGeolocation ( { geolocation : geolocation || undefined } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
2020-07-30 02:26:59 +02:00
async setExtraHTTPHeaders ( headers : Headers ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2020-08-19 00:38:29 +02:00
network . validateHeaders ( headers ) ;
2021-02-20 01:21:39 +01:00
await channel . setExtraHTTPHeaders ( { headers : headersObjectToArray ( headers ) } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
async setOffline ( offline : boolean ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . setOffline ( { offline } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
2020-07-30 02:26:59 +02:00
async setHTTPCredentials ( httpCredentials : { username : string , password : string } | null ) : Promise < void > {
2020-09-07 06:36:22 +02:00
if ( ! isUnderTest ( ) )
2020-08-18 01:19:21 +02:00
deprecate ( ` context.setHTTPCredentials ` , ` warning: method |context.setHTTPCredentials()| is deprecated. Instead of changing credentials, create another browser context with new credentials. ` ) ;
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . setHTTPCredentials ( { httpCredentials : httpCredentials || undefined } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
async addInitScript ( script : Function | string | { path? : string , content? : string } , arg? : any ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2020-08-19 22:27:58 +02:00
const source = await evaluationScript ( script , arg ) ;
2021-02-20 01:21:39 +01:00
await channel . addInitScript ( { source } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
2021-01-04 22:50:29 +01:00
async exposeBinding ( name : string , callback : ( source : structs.BindingSource , . . . args : any [ ] ) = > any , options : { handle? : boolean } = { } ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . exposeBinding ( { name , needsHandle : options.handle } ) ;
2021-01-04 22:50:29 +01:00
this . _bindings . set ( name , callback ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
2021-01-04 22:50:29 +01:00
async exposeFunction ( name : string , callback : Function ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
await channel . exposeBinding ( { name } ) ;
2021-01-04 22:50:29 +01:00
const binding = ( source : structs.BindingSource , . . . args : any [ ] ) = > callback ( . . . args ) ;
2020-10-02 07:47:31 +02:00
this . _bindings . set ( name , binding ) ;
} ) ;
2020-06-26 01:05:36 +02:00
}
2021-08-24 20:45:50 +02:00
async route ( url : URLMatch , handler : network.RouteHandlerCallback , options : { times? : number } = { } ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-08-24 20:45:50 +02:00
this . _routes . unshift ( new network . RouteHandler ( this . _options . baseURL , url , handler , options . times ) ) ;
2020-07-16 23:32:21 +02:00
if ( this . _routes . length === 1 )
2021-02-20 01:21:39 +01:00
await channel . setNetworkInterceptionEnabled ( { enabled : true } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
2021-08-24 20:45:50 +02:00
async unroute ( url : URLMatch , handler? : network.RouteHandlerCallback ) : Promise < void > {
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2020-07-16 23:32:21 +02:00
this . _routes = this . _routes . filter ( route = > route . url !== url || ( handler && route . handler !== handler ) ) ;
if ( this . _routes . length === 0 )
2021-02-20 01:21:39 +01:00
await channel . setNetworkInterceptionEnabled ( { enabled : false } ) ;
2020-07-16 23:32:21 +02:00
} ) ;
2020-06-26 01:05:36 +02:00
}
2020-07-30 02:26:59 +02:00
async waitForEvent ( event : string , optionsOrPredicate : WaitForEventOptions = { } ) : Promise < any > {
2021-07-01 02:56:48 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-06-28 22:27:38 +02:00
const timeout = this . _timeoutSettings . timeout ( typeof optionsOrPredicate === 'function' ? { } : optionsOrPredicate ) ;
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate ;
2021-07-01 02:56:48 +02:00
const waiter = Waiter . createForEvent ( this , event ) ;
2021-06-28 22:27:38 +02:00
waiter . rejectOnTimeout ( timeout , ` Timeout while waiting for event " ${ event } " ` ) ;
if ( event !== Events . BrowserContext . Close )
waiter . rejectOnEvent ( this , Events . BrowserContext . Close , new Error ( 'Context closed' ) ) ;
const result = await waiter . waitForEvent ( this , event , predicate as any ) ;
waiter . dispose ( ) ;
return result ;
} ) ;
2020-06-26 01:05:36 +02:00
}
2020-12-15 01:03:52 +01:00
async storageState ( options : { path? : string } = { } ) : Promise < StorageState > {
2021-06-28 22:27:38 +02:00
return await this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-02-20 01:21:39 +01:00
const state = await channel . storageState ( ) ;
2020-12-15 01:03:52 +01:00
if ( options . path ) {
await mkdirIfNeeded ( options . path ) ;
2021-06-03 18:55:33 +02:00
await fs . promises . writeFile ( options . path , JSON . stringify ( state , undefined , 2 ) , 'utf8' ) ;
2020-12-15 01:03:52 +01:00
}
return state ;
2020-11-13 23:24:53 +01:00
} ) ;
}
2021-04-02 03:47:14 +02:00
backgroundPages ( ) : Page [ ] {
return [ . . . this . _backgroundPages ] ;
}
serviceWorkers ( ) : Worker [ ] {
return [ . . . this . _serviceWorkers ] ;
}
2021-08-16 21:49:10 +02:00
async newCDPSession ( page : Page | Frame ) : Promise < api.CDPSession > {
// channelOwner.ts's validation messages don't handle the pseudo-union type, so we're explicit here
if ( ! ( page instanceof Page ) && ! ( page instanceof Frame ) )
throw new Error ( 'page: expected Page or Frame' ) ;
2021-06-28 22:27:38 +02:00
return this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-08-16 21:49:10 +02:00
const result = await channel . newCDPSession ( page instanceof Page ? { page : page._channel } : { frame : page._channel } ) ;
2021-04-02 03:47:14 +02:00
return CDPSession . from ( result . session ) ;
} ) ;
}
2021-03-22 17:59:39 +01:00
_onClose() {
2020-06-27 02:24:21 +02:00
if ( this . _browser )
this . _browser . _contexts . delete ( this ) ;
2021-08-10 03:09:11 +02:00
this . _browserType ? . _contexts ? . delete ( this ) ;
2021-01-22 18:58:31 +01:00
this . emit ( Events . BrowserContext . Close , this ) ;
2020-06-26 01:05:36 +02:00
}
2020-06-30 19:55:11 +02:00
async close ( ) : Promise < void > {
2020-10-01 06:17:30 +02:00
try {
2021-06-28 22:27:38 +02:00
await this . _wrapApiCall ( async ( channel : channels.BrowserContextChannel ) = > {
2021-08-10 03:09:11 +02:00
await this . _browserType ? . _onWillCloseContext ? . ( this ) ;
2021-08-25 22:32:56 +02:00
if ( this . _options . recordHar ) {
const har = await this . _channel . harExport ( ) ;
2021-08-26 20:26:08 +02:00
const artifact = Artifact . from ( har . artifact ) ;
if ( this . browser ( ) ? . _remoteType )
artifact . _isRemote = true ;
await artifact . saveAs ( this . _options . recordHar . path ) ;
await artifact . delete ( ) ;
2021-08-25 22:32:56 +02:00
}
2021-02-20 01:21:39 +01:00
await channel . close ( ) ;
2020-10-01 06:17:30 +02:00
await this . _closedPromise ;
} ) ;
} catch ( e ) {
if ( isSafeCloseError ( e ) )
return ;
throw e ;
}
2020-06-30 19:55:11 +02:00
}
2021-01-25 23:49:26 +01:00
2021-01-26 04:01:04 +01:00
async _enableRecorder ( params : {
language : string ,
launchOptions? : LaunchOptions ,
contextOptions? : BrowserContextOptions ,
device? : string ,
saveStorage? : string ,
2021-02-04 01:01:51 +01:00
startRecording? : boolean ,
2021-01-26 04:01:04 +01:00
outputFile? : string
} ) {
await this . _channel . recorderSupplementEnable ( params ) ;
2021-01-25 23:49:26 +01:00
}
2020-06-26 01:05:36 +02:00
}
2020-11-03 04:42:05 +01:00
2021-02-12 02:46:54 +01:00
export async function prepareBrowserContextParams ( options : BrowserContextOptions ) : Promise < channels.BrowserNewContextParams > {
2020-11-03 04:42:05 +01:00
if ( options . videoSize && ! options . videosPath )
throw new Error ( ` "videoSize" option requires "videosPath" to be specified ` ) ;
if ( options . extraHTTPHeaders )
network . validateHeaders ( options . extraHTTPHeaders ) ;
2021-02-12 02:46:54 +01:00
const contextParams : channels.BrowserNewContextParams = {
2020-11-03 04:42:05 +01:00
. . . options ,
viewport : options.viewport === null ? undefined : options . viewport ,
noDefaultViewport : options.viewport === null ,
extraHTTPHeaders : options.extraHTTPHeaders ? headersObjectToArray ( options . extraHTTPHeaders ) : undefined ,
2021-06-03 18:55:33 +02:00
storageState : typeof options . storageState === 'string' ? JSON . parse ( await fs . promises . readFile ( options . storageState , 'utf8' ) ) : options . storageState ,
2020-11-03 04:42:05 +01:00
} ;
2021-02-12 02:46:54 +01:00
if ( ! contextParams . recordVideo && options . videosPath ) {
contextParams . recordVideo = {
2020-11-03 04:42:05 +01:00
dir : options.videosPath ,
size : options.videoSize
} ;
}
2021-02-12 02:46:54 +01:00
return contextParams ;
2020-11-03 04:42:05 +01:00
}