2019-12-19 16:53:24 -08: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-06-25 08:30:56 -07:00
import { BrowserBase , BrowserOptions , BrowserContextOptions } from '../browser' ;
import { assertBrowserContextIsNotOwned , BrowserContext , BrowserContextBase , validateBrowserContextOptions , verifyGeolocation } from '../browserContext' ;
2020-03-05 17:22:57 -08:00
import { Events as CommonEvents } from '../events' ;
2020-06-29 16:37:01 -07:00
import { assert , deprecate } from '../helper' ;
2019-12-19 16:53:24 -08:00
import * as network from '../network' ;
2020-03-19 16:25:12 -07:00
import { Page , PageBinding , Worker } from '../page' ;
2020-02-04 19:41:38 -08:00
import { ConnectionTransport , SlowMoTransport } from '../transport' ;
2020-03-05 17:22:57 -08:00
import * as types from '../types' ;
import { ConnectionEvents , CRConnection , CRSession } from './crConnection' ;
import { CRPage } from './crPage' ;
import { readProtocolStream } from './crProtocolHelper' ;
import { Events } from './events' ;
import { Protocol } from './protocol' ;
2020-03-23 21:48:32 -07:00
import { CRExecutionContext } from './crExecutionContext' ;
2020-06-11 18:18:33 -07:00
import { CRDevTools } from './crDevTools' ;
2019-12-19 16:53:24 -08:00
2020-04-02 17:56:14 -07:00
export class CRBrowser extends BrowserBase {
2020-03-06 15:11:03 -08:00
readonly _connection : CRConnection ;
_session : CRSession ;
private _clientRootSessionPromise : Promise < CRSession > | null = null ;
2020-02-24 08:53:30 -08:00
readonly _contexts = new Map < string , CRBrowserContext > ( ) ;
2020-03-23 21:48:32 -07:00
_crPages = new Map < string , CRPage > ( ) ;
_backgroundPages = new Map < string , CRPage > ( ) ;
_serviceWorkers = new Map < string , CRServiceWorker > ( ) ;
2020-05-19 14:55:11 -07:00
_devtools? : CRDevTools ;
2019-12-19 16:53:24 -08:00
private _tracingRecording = false ;
2020-01-13 13:33:25 -08:00
private _tracingPath : string | null = '' ;
2019-12-19 16:53:24 -08:00
private _tracingClient : CRSession | undefined ;
2020-05-19 14:55:11 -07:00
static async connect ( transport : ConnectionTransport , options : BrowserOptions , devtools? : CRDevTools ) : Promise < CRBrowser > {
2020-06-16 17:11:19 -07:00
const connection = new CRConnection ( SlowMoTransport . wrap ( transport , options . slowMo ) , options . loggers ) ;
2020-05-14 13:22:33 -07:00
const browser = new CRBrowser ( connection , options ) ;
2020-05-19 14:55:11 -07:00
browser . _devtools = devtools ;
2020-03-05 10:45:32 -08:00
const session = connection . rootSession ;
2020-05-14 13:22:33 -07:00
if ( ! options . persistent ) {
2020-04-08 11:18:06 -07:00
await session . send ( 'Target.setAutoAttach' , { autoAttach : true , waitForDebuggerOnStart : true , flatten : true } ) ;
return browser ;
2020-03-05 10:45:32 -08:00
}
2020-05-21 15:13:16 -07:00
browser . _defaultContext = new CRBrowserContext ( browser , null , options . persistent ) ;
2020-04-08 11:18:06 -07:00
const existingTargetAttachPromises : Promise < any > [ ] = [ ] ;
// First page, background pages and their service workers in the persistent context
// are created automatically and may be initialized before we enable auto-attach.
function attachToExistingPage ( { targetInfo } : Protocol . Target . targetCreatedPayload ) {
if ( targetInfo . type !== 'page' && targetInfo . type !== 'background_page' && targetInfo . type !== 'service_worker' )
return ;
// TODO: should we handle the error during 'Target.attachToTarget'? Can the target disappear?
existingTargetAttachPromises . push ( session . send ( 'Target.attachToTarget' , { targetId : targetInfo.targetId , flatten : true } ) ) ;
}
session . on ( 'Target.targetCreated' , attachToExistingPage ) ;
const startDiscover = session . send ( 'Target.setDiscoverTargets' , { discover : true } ) ;
const autoAttachAndStopDiscover = session . send ( 'Target.setAutoAttach' , { autoAttach : true , waitForDebuggerOnStart : true , flatten : true } ) . then ( ( ) = > {
// All targets collected before setAutoAttach response will not be auto-attached, the rest will be.
// TODO: We should fix this upstream and remove this tricky logic.
session . off ( 'Target.targetCreated' , attachToExistingPage ) ;
return session . send ( 'Target.setDiscoverTargets' , { discover : false } ) ;
} ) ;
await Promise . all ( [
startDiscover ,
autoAttachAndStopDiscover ,
2020-05-21 15:13:16 -07:00
( browser . _defaultContext as CRBrowserContext ) . _initialize ( ) ,
2020-04-08 11:18:06 -07:00
] ) ;
// Wait for initial targets to arrive.
await Promise . all ( existingTargetAttachPromises ) ;
2019-12-19 16:53:24 -08:00
return browser ;
}
2020-05-14 13:22:33 -07:00
constructor ( connection : CRConnection , options : BrowserOptions ) {
super ( options ) ;
2019-12-19 16:53:24 -08:00
this . _connection = connection ;
2020-03-06 15:11:03 -08:00
this . _session = this . _connection . rootSession ;
2020-06-29 16:26:32 -07:00
this . _connection . on ( ConnectionEvents . Disconnected , ( ) = > this . _didClose ( ) ) ;
2020-03-06 15:11:03 -08:00
this . _session . on ( 'Target.attachedToTarget' , this . _onAttachedToTarget . bind ( this ) ) ;
2020-03-19 16:10:24 -07:00
this . _session . on ( 'Target.detachedFromTarget' , this . _onDetachedFromTarget . bind ( this ) ) ;
2019-12-19 16:53:24 -08:00
}
2020-02-10 10:41:45 -08:00
2019-12-19 16:53:24 -08:00
async newContext ( options : BrowserContextOptions = { } ) : Promise < BrowserContext > {
2020-02-24 08:53:30 -08:00
options = validateBrowserContextOptions ( options ) ;
2020-03-06 15:11:03 -08:00
const { browserContextId } = await this . _session . send ( 'Target.createBrowserContext' , { disposeOnDetach : true } ) ;
2020-02-24 08:53:30 -08:00
const context = new CRBrowserContext ( this , browserContextId , options ) ;
2020-01-13 13:32:44 -08:00
await context . _initialize ( ) ;
2019-12-19 16:53:24 -08:00
this . _contexts . set ( browserContextId , context ) ;
return context ;
}
2020-02-10 10:41:45 -08:00
contexts ( ) : BrowserContext [ ] {
2020-02-05 12:41:55 -08:00
return Array . from ( this . _contexts . values ( ) ) ;
2019-12-19 16:53:24 -08:00
}
2020-03-13 11:33:33 -07:00
_onAttachedToTarget ( { targetInfo , sessionId , waitingForDebugger } : Protocol . Target . attachedToTargetPayload ) {
2020-04-18 19:58:11 -07:00
if ( targetInfo . type === 'browser' )
return ;
2020-03-09 15:53:45 -07:00
const session = this . _connection . session ( sessionId ) ! ;
2020-04-18 19:58:11 -07:00
assert ( targetInfo . browserContextId , 'targetInfo: ' + JSON . stringify ( targetInfo , null , 2 ) ) ;
let context = this . _contexts . get ( targetInfo . browserContextId ) || null ;
if ( ! context ) {
// TODO: auto attach only to pages from our contexts.
// assert(this._defaultContext);
2020-05-20 16:30:04 -07:00
context = this . _defaultContext as CRBrowserContext ;
2020-04-18 19:58:11 -07:00
}
2020-05-19 14:55:11 -07:00
if ( targetInfo . type === 'other' && targetInfo . url . startsWith ( 'devtools://devtools' ) && this . _devtools ) {
this . _devtools . install ( session ) ;
return ;
}
2020-04-18 19:58:11 -07:00
if ( targetInfo . type === 'other' || ! context ) {
if ( waitingForDebugger ) {
// Ideally, detaching should resume any target, but there is a bug in the backend.
2020-06-05 07:50:26 -07:00
session . _sendMayFail ( 'Runtime.runIfWaitingForDebugger' ) . then ( ( ) = > {
this . _session . _sendMayFail ( 'Target.detachFromTarget' , { sessionId } ) ;
2020-04-18 19:58:11 -07:00
} ) ;
}
return ;
}
2020-03-23 21:48:32 -07:00
assert ( ! this . _crPages . has ( targetInfo . targetId ) , 'Duplicate target ' + targetInfo . targetId ) ;
assert ( ! this . _backgroundPages . has ( targetInfo . targetId ) , 'Duplicate target ' + targetInfo . targetId ) ;
assert ( ! this . _serviceWorkers . has ( targetInfo . targetId ) , 'Duplicate target ' + targetInfo . targetId ) ;
if ( targetInfo . type === 'background_page' ) {
2020-04-23 10:38:58 -07:00
const backgroundPage = new CRPage ( session , targetInfo . targetId , context , null , false ) ;
2020-03-23 21:48:32 -07:00
this . _backgroundPages . set ( targetInfo . targetId , backgroundPage ) ;
backgroundPage . pageOrError ( ) . then ( ( ) = > {
2020-04-18 19:58:11 -07:00
context ! . emit ( Events . CRBrowserContext . BackgroundPage , backgroundPage . _page ) ;
2020-03-23 21:48:32 -07:00
} ) ;
2020-03-05 10:45:32 -08:00
return ;
2020-03-09 15:53:45 -07:00
}
2020-03-23 21:48:32 -07:00
if ( targetInfo . type === 'page' ) {
const opener = targetInfo . openerId ? this . _crPages . get ( targetInfo . openerId ) || null : null ;
2020-05-14 13:22:33 -07:00
const crPage = new CRPage ( session , targetInfo . targetId , context , opener , ! ! this . _options . headful ) ;
2020-03-23 21:48:32 -07:00
this . _crPages . set ( targetInfo . targetId , crPage ) ;
crPage . pageOrError ( ) . then ( ( ) = > {
2020-04-18 19:58:11 -07:00
context ! . emit ( CommonEvents . BrowserContext . Page , crPage . _page ) ;
2020-03-23 21:48:32 -07:00
if ( opener ) {
opener . pageOrError ( ) . then ( openerPage = > {
if ( openerPage instanceof Page && ! openerPage . isClosed ( ) )
openerPage . emit ( CommonEvents . Page . Popup , crPage . _page ) ;
} ) ;
2020-03-19 16:10:24 -07:00
}
} ) ;
2020-03-13 11:33:33 -07:00
return ;
2020-03-19 16:10:24 -07:00
}
2019-12-19 16:53:24 -08:00
2020-03-23 21:48:32 -07:00
if ( targetInfo . type === 'service_worker' ) {
const serviceWorker = new CRServiceWorker ( context , session , targetInfo . url ) ;
this . _serviceWorkers . set ( targetInfo . targetId , serviceWorker ) ;
context . emit ( Events . CRBrowserContext . ServiceWorker , serviceWorker ) ;
return ;
}
2020-04-18 19:58:11 -07:00
assert ( false , 'Unknown target type: ' + targetInfo . type ) ;
2020-03-09 15:53:45 -07:00
}
2020-03-23 21:48:32 -07:00
_onDetachedFromTarget ( payload : Protocol.Target.detachFromTargetParameters ) {
const targetId = payload . targetId ! ;
const crPage = this . _crPages . get ( targetId ) ;
if ( crPage ) {
this . _crPages . delete ( targetId ) ;
crPage . didClose ( ) ;
return ;
}
const backgroundPage = this . _backgroundPages . get ( targetId ) ;
if ( backgroundPage ) {
this . _backgroundPages . delete ( targetId ) ;
backgroundPage . didClose ( ) ;
2020-03-09 15:53:45 -07:00
return ;
2020-03-23 21:48:32 -07:00
}
const serviceWorker = this . _serviceWorkers . get ( targetId ) ;
if ( serviceWorker ) {
this . _serviceWorkers . delete ( targetId ) ;
serviceWorker . emit ( CommonEvents . Worker . Close ) ;
return ;
}
2019-12-19 16:53:24 -08:00
}
2020-03-23 21:48:32 -07:00
async _closePage ( crPage : CRPage ) {
await this . _session . send ( 'Target.closeTarget' , { targetId : crPage._targetId } ) ;
2019-12-19 16:53:24 -08:00
}
2020-04-03 16:34:07 -07:00
_disconnect() {
2020-02-06 12:41:43 -08:00
this . _connection . close ( ) ;
2020-04-02 16:57:12 -07:00
}
2019-12-19 16:53:24 -08:00
2020-03-13 09:00:03 -07:00
async newBrowserCDPSession ( ) : Promise < CRSession > {
2020-03-02 13:58:22 -08:00
return await this . _connection . createBrowserSession ( ) ;
2019-12-19 16:53:24 -08:00
}
2020-03-03 17:29:12 -08:00
async startTracing ( page? : Page , options : { path? : string ; screenshots? : boolean ; categories? : string [ ] ; } = { } ) {
2019-12-19 16:53:24 -08:00
assert ( ! this . _tracingRecording , 'Cannot start recording trace while already recording trace.' ) ;
2020-04-06 15:09:43 -07:00
this . _tracingClient = page ? ( page . _delegate as CRPage ) . _mainFrameSession._client : this._session ;
2019-12-19 16:53:24 -08:00
const defaultCategories = [
'-*' , 'devtools.timeline' , 'v8.execute' , 'disabled-by-default-devtools.timeline' ,
'disabled-by-default-devtools.timeline.frame' , 'toplevel' ,
'blink.console' , 'blink.user_timing' , 'latencyInfo' , 'disabled-by-default-devtools.timeline.stack' ,
'disabled-by-default-v8.cpu_profiler' , 'disabled-by-default-v8.cpu_profiler.hires'
] ;
const {
path = null ,
screenshots = false ,
categories = defaultCategories ,
} = options ;
if ( screenshots )
categories . push ( 'disabled-by-default-devtools.screenshot' ) ;
this . _tracingPath = path ;
this . _tracingRecording = true ;
await this . _tracingClient . send ( 'Tracing.start' , {
transferMode : 'ReturnAsStream' ,
categories : categories.join ( ',' )
} ) ;
}
2020-04-01 14:42:47 -07:00
async stopTracing ( ) : Promise < Buffer > {
2019-12-19 16:53:24 -08:00
assert ( this . _tracingClient , 'Tracing was not started.' ) ;
2020-03-27 15:16:17 -07:00
const [ event ] = await Promise . all ( [
new Promise ( f = > this . _tracingClient ! . once ( 'Tracing.tracingComplete' , f ) ) ,
this . _tracingClient . send ( 'Tracing.end' )
] ) ;
const result = await readProtocolStream ( this . _tracingClient , ( event as any ) . stream ! , this . _tracingPath ) ;
2019-12-19 16:53:24 -08:00
this . _tracingRecording = false ;
2020-03-27 15:16:17 -07:00
return result ;
2019-12-19 16:53:24 -08:00
}
isConnected ( ) : boolean {
return ! this . _connection . _closed ;
}
2020-02-12 22:35:06 -08:00
2020-03-06 15:11:03 -08:00
async _clientRootSession ( ) : Promise < CRSession > {
if ( ! this . _clientRootSessionPromise )
this . _clientRootSessionPromise = this . _connection . createBrowserSession ( ) ;
return this . _clientRootSessionPromise ;
}
2019-12-19 16:53:24 -08:00
}
2020-02-24 08:53:30 -08:00
2020-03-23 21:48:32 -07:00
class CRServiceWorker extends Worker {
readonly _browserContext : CRBrowserContext ;
constructor ( browserContext : CRBrowserContext , session : CRSession , url : string ) {
2020-06-09 16:11:17 -07:00
super ( url ) ;
2020-03-23 21:48:32 -07:00
this . _browserContext = browserContext ;
session . once ( 'Runtime.executionContextCreated' , event = > {
this . _createExecutionContext ( new CRExecutionContext ( session , event . context ) ) ;
} ) ;
// This might fail if the target is closed before we receive all execution contexts.
session . send ( 'Runtime.enable' , { } ) . catch ( e = > { } ) ;
session . send ( 'Runtime.runIfWaitingForDebugger' ) . catch ( e = > { } ) ;
}
}
2020-03-05 17:22:57 -08:00
export class CRBrowserContext extends BrowserContextBase {
2020-02-24 08:53:30 -08:00
readonly _browser : CRBrowser ;
readonly _browserContextId : string | null ;
2020-02-27 16:18:33 -08:00
readonly _evaluateOnNewDocumentSources : string [ ] ;
2020-02-24 08:53:30 -08:00
2020-06-25 08:30:56 -07:00
constructor ( browser : CRBrowser , browserContextId : string | null , options : types.BrowserContextOptions ) {
2020-06-29 16:26:32 -07:00
super ( browser , options , ! browserContextId ) ;
2020-02-24 08:53:30 -08:00
this . _browser = browser ;
this . _browserContextId = browserContextId ;
2020-02-27 16:18:33 -08:00
this . _evaluateOnNewDocumentSources = [ ] ;
2020-06-05 13:50:15 -07:00
this . _authenticateProxyViaCredentials ( ) ;
2020-02-24 08:53:30 -08:00
}
async _initialize() {
2020-05-21 15:13:16 -07:00
assert ( ! Array . from ( this . _browser . _crPages . values ( ) ) . some ( page = > page . _browserContext === this ) ) ;
2020-05-27 22:16:54 -07:00
const promises : Promise < any > [ ] = [ super . _initialize ( ) ] ;
2020-05-21 15:13:16 -07:00
if ( this . _browser . _options . downloadsPath ) {
promises . push ( this . _browser . _session . send ( 'Browser.setDownloadBehavior' , {
2020-04-02 17:56:14 -07:00
behavior : this._options.acceptDownloads ? 'allowAndName' : 'deny' ,
browserContextId : this._browserContextId || undefined ,
2020-05-14 13:22:33 -07:00
downloadPath : this._browser._options.downloadsPath
2020-05-21 15:13:16 -07:00
} ) ) ;
}
2020-03-17 15:32:50 -07:00
if ( this . _options . permissions )
2020-04-02 17:56:14 -07:00
promises . push ( this . grantPermissions ( this . _options . permissions ) ) ;
await Promise . all ( promises ) ;
2020-02-24 08:53:30 -08:00
}
2020-03-13 11:33:33 -07:00
pages ( ) : Page [ ] {
2020-03-23 21:48:32 -07:00
const result : Page [ ] = [ ] ;
for ( const crPage of this . _browser . _crPages . values ( ) ) {
if ( crPage . _browserContext === this && crPage . _initializedPage )
result . push ( crPage . _initializedPage ) ;
}
return result ;
2020-02-24 08:53:30 -08:00
}
async newPage ( ) : Promise < Page > {
assertBrowserContextIsNotOwned ( this ) ;
2020-03-06 15:11:03 -08:00
const { targetId } = await this . _browser . _session . send ( 'Target.createTarget' , { url : 'about:blank' , browserContextId : this._browserContextId || undefined } ) ;
2020-03-23 21:48:32 -07:00
const crPage = this . _browser . _crPages . get ( targetId ) ! ;
const result = await crPage . pageOrError ( ) ;
2020-03-05 15:18:27 -08:00
if ( result instanceof Page ) {
if ( result . isClosed ( ) )
throw new Error ( 'Page has been closed.' ) ;
return result ;
}
throw result ;
2020-02-24 08:53:30 -08:00
}
2020-06-25 08:30:56 -07:00
async _doCookies ( urls : string [ ] ) : Promise < types.NetworkCookie [ ] > {
2020-03-06 15:11:03 -08:00
const { cookies } = await this . _browser . _session . send ( 'Storage.getCookies' , { browserContextId : this._browserContextId || undefined } ) ;
2020-02-24 08:53:30 -08:00
return network . filterCookies ( cookies . map ( c = > {
const copy : any = { sameSite : 'None' , . . . c } ;
delete copy . size ;
delete copy . priority ;
2020-03-07 08:41:57 -08:00
delete copy . session ;
2020-06-25 08:30:56 -07:00
return copy as types . NetworkCookie ;
2020-02-24 08:53:30 -08:00
} ) , urls ) ;
}
2020-06-25 08:30:56 -07:00
async addCookies ( cookies : types.SetNetworkCookieParam [ ] ) {
2020-03-06 15:11:03 -08:00
await this . _browser . _session . send ( 'Storage.setCookies' , { cookies : network.rewriteCookies ( cookies ) , browserContextId : this._browserContextId || undefined } ) ;
2020-02-24 08:53:30 -08:00
}
async clearCookies() {
2020-03-06 15:11:03 -08:00
await this . _browser . _session . send ( 'Storage.clearCookies' , { browserContextId : this._browserContextId || undefined } ) ;
2020-02-24 08:53:30 -08:00
}
2020-03-17 15:32:50 -07:00
async _doGrantPermissions ( origin : string , permissions : string [ ] ) {
2020-02-24 08:53:30 -08:00
const webPermissionToProtocol = new Map < string , Protocol.Browser.PermissionType > ( [
[ 'geolocation' , 'geolocation' ] ,
[ 'midi' , 'midi' ] ,
[ 'notifications' , 'notifications' ] ,
[ 'camera' , 'videoCapture' ] ,
[ 'microphone' , 'audioCapture' ] ,
[ 'background-sync' , 'backgroundSync' ] ,
[ 'ambient-light-sensor' , 'sensors' ] ,
[ 'accelerometer' , 'sensors' ] ,
[ 'gyroscope' , 'sensors' ] ,
[ 'magnetometer' , 'sensors' ] ,
[ 'accessibility-events' , 'accessibilityEvents' ] ,
[ 'clipboard-read' , 'clipboardReadWrite' ] ,
[ 'clipboard-write' , 'clipboardSanitizedWrite' ] ,
[ 'payment-handler' , 'paymentHandler' ] ,
// chrome-specific permissions we have.
[ 'midi-sysex' , 'midiSysex' ] ,
] ) ;
const filtered = permissions . map ( permission = > {
const protocolPermission = webPermissionToProtocol . get ( permission ) ;
if ( ! protocolPermission )
throw new Error ( 'Unknown permission: ' + permission ) ;
return protocolPermission ;
} ) ;
2020-03-17 15:32:50 -07:00
await this . _browser . _session . send ( 'Browser.grantPermissions' , { origin : origin === '*' ? undefined : origin , browserContextId : this._browserContextId || undefined , permissions : filtered } ) ;
2020-02-24 08:53:30 -08:00
}
2020-03-17 15:32:50 -07:00
async _doClearPermissions() {
2020-03-06 15:11:03 -08:00
await this . _browser . _session . send ( 'Browser.resetPermissions' , { browserContextId : this._browserContextId || undefined } ) ;
2020-02-24 08:53:30 -08:00
}
async setGeolocation ( geolocation : types.Geolocation | null ) : Promise < void > {
if ( geolocation )
geolocation = verifyGeolocation ( geolocation ) ;
this . _options . geolocation = geolocation || undefined ;
2020-03-13 11:33:33 -07:00
for ( const page of this . pages ( ) )
2020-04-06 15:09:43 -07:00
await ( page . _delegate as CRPage ) . updateGeolocation ( ) ;
2020-02-24 08:53:30 -08:00
}
2020-06-25 08:30:56 -07:00
async setExtraHTTPHeaders ( headers : types.Headers ) : Promise < void > {
2020-02-26 12:42:20 -08:00
this . _options . extraHTTPHeaders = network . verifyHeaders ( headers ) ;
2020-03-13 11:33:33 -07:00
for ( const page of this . pages ( ) )
2020-02-26 12:42:20 -08:00
await ( page . _delegate as CRPage ) . updateExtraHTTPHeaders ( ) ;
}
2020-03-04 17:58:12 -08:00
async setOffline ( offline : boolean ) : Promise < void > {
this . _options . offline = offline ;
2020-03-13 11:33:33 -07:00
for ( const page of this . pages ( ) )
2020-04-06 15:09:43 -07:00
await ( page . _delegate as CRPage ) . updateOffline ( ) ;
2020-03-04 17:58:12 -08:00
}
2020-03-06 13:50:42 -08:00
async setHTTPCredentials ( httpCredentials : types.Credentials | null ) : Promise < void > {
2020-06-29 16:37:01 -07:00
deprecate ( ` context.setHTTPCredentials ` , ` warning: method |context.setHTTPCredentials()| is deprecated. Instead of changing credentials, create another browser context with new credentials. ` ) ;
2020-03-06 13:50:42 -08:00
this . _options . httpCredentials = httpCredentials || undefined ;
2020-03-13 11:33:33 -07:00
for ( const page of this . pages ( ) )
2020-04-06 15:09:43 -07:00
await ( page . _delegate as CRPage ) . updateHttpCredentials ( ) ;
2020-03-06 13:50:42 -08:00
}
2020-06-25 08:30:56 -07:00
async _doAddInitScript ( source : string ) {
2020-02-27 16:18:33 -08:00
this . _evaluateOnNewDocumentSources . push ( source ) ;
2020-03-13 11:33:33 -07:00
for ( const page of this . pages ( ) )
2020-02-27 16:18:33 -08:00
await ( page . _delegate as CRPage ) . evaluateOnNewDocument ( source ) ;
}
2020-05-18 14:28:06 -07:00
async _doExposeBinding ( binding : PageBinding ) {
2020-03-13 11:33:33 -07:00
for ( const page of this . pages ( ) )
2020-03-03 16:46:06 -08:00
await ( page . _delegate as CRPage ) . exposeBinding ( binding ) ;
}
2020-03-09 21:02:54 -07:00
async route ( url : types.URLMatch , handler : network.RouteHandler ) : Promise < void > {
this . _routes . push ( { url , handler } ) ;
2020-03-13 11:33:33 -07:00
for ( const page of this . pages ( ) )
2020-03-09 21:02:54 -07:00
await ( page . _delegate as CRPage ) . updateRequestInterception ( ) ;
}
2020-04-15 19:55:22 -07:00
async unroute ( url : types.URLMatch , handler? : network.RouteHandler ) : Promise < void > {
this . _routes = this . _routes . filter ( route = > route . url !== url || ( handler && route . handler !== handler ) ) ;
for ( const page of this . pages ( ) )
await ( page . _delegate as CRPage ) . updateRequestInterception ( ) ;
}
2020-06-29 16:26:32 -07:00
async _doClose() {
assert ( this . _browserContextId ) ;
2020-03-06 15:11:03 -08:00
await this . _browser . _session . send ( 'Target.disposeBrowserContext' , { browserContextId : this._browserContextId } ) ;
2020-02-24 08:53:30 -08:00
this . _browser . _contexts . delete ( this . _browserContextId ) ;
}
2020-03-13 11:33:33 -07:00
backgroundPages ( ) : Page [ ] {
2020-03-23 21:48:32 -07:00
const result : Page [ ] = [ ] ;
for ( const backgroundPage of this . _browser . _backgroundPages . values ( ) ) {
if ( backgroundPage . _browserContext === this && backgroundPage . _initializedPage )
result . push ( backgroundPage . _initializedPage ) ;
}
return result ;
2020-02-24 14:35:51 -08:00
}
2020-03-19 16:10:24 -07:00
serviceWorkers ( ) : Worker [ ] {
2020-03-23 21:48:32 -07:00
return Array . from ( this . _browser . _serviceWorkers . values ( ) ) . filter ( serviceWorker = > serviceWorker . _browserContext === this ) ;
2020-03-19 16:10:24 -07:00
}
2020-03-13 09:00:03 -07:00
async newCDPSession ( page : Page ) : Promise < CRSession > {
2020-03-23 21:48:32 -07:00
const targetId = ( page . _delegate as CRPage ) . _targetId ;
2020-03-06 15:11:03 -08:00
const rootSession = await this . _browser . _clientRootSession ( ) ;
const { sessionId } = await rootSession . send ( 'Target.attachToTarget' , { targetId , flatten : true } ) ;
return this . _browser . _connection . session ( sessionId ) ! ;
2020-02-24 14:35:51 -08:00
}
2020-02-24 08:53:30 -08:00
}