1717import { LaunchServerOptions } from './client/types' ;
1818import { BrowserType } from './server/browserType' ;
1919import * as ws from 'ws' ;
20+ import * as fs from 'fs' ;
2021import { Browser } from './server/browser' ;
2122import { ChildProcess } from 'child_process' ;
2223import { EventEmitter } from 'ws' ;
@@ -29,6 +30,8 @@ import { envObjectToArray } from './client/clientHelper';
2930import { createGuid } from './utils/utils' ;
3031import { SelectorsDispatcher } from './dispatchers/selectorsDispatcher' ;
3132import { Selectors } from './server/selectors' ;
33+ import { BrowserContext , Video } from './server/browserContext' ;
34+ import { StreamDispatcher } from './dispatchers/streamDispatcher' ;
3235
3336export class BrowserServerLauncherImpl implements BrowserServerLauncher {
3437 private _browserType : BrowserType ;
@@ -109,39 +112,49 @@ export class BrowserServerImpl extends EventEmitter implements BrowserServer {
109112 socket . on ( 'error' , ( ) => { } ) ;
110113 const selectors = new Selectors ( ) ;
111114 const scope = connection . rootDispatcher ( ) ;
112- const browser = new ConnectedBrowser ( scope , this . _browser , selectors ) ;
113- new RemoteBrowserDispatcher ( scope , browser , selectors ) ;
115+ const remoteBrowser = new RemoteBrowserDispatcher ( scope , this . _browser , selectors ) ;
114116 socket . on ( 'close' , ( ) => {
115117 // Avoid sending any more messages over closed socket.
116118 connection . onmessage = ( ) => { } ;
117119 // Cleanup contexts upon disconnect.
118- browser . close ( ) . catch ( e => { } ) ;
120+ remoteBrowser . connectedBrowser . close ( ) . catch ( e => { } ) ;
119121 } ) ;
120122 }
121123}
122124
123125class RemoteBrowserDispatcher extends Dispatcher < { } , channels . RemoteBrowserInitializer > implements channels . PlaywrightChannel {
124- constructor ( scope : DispatcherScope , browser : ConnectedBrowser , selectors : Selectors ) {
126+ readonly connectedBrowser : ConnectedBrowser ;
127+
128+ constructor ( scope : DispatcherScope , browser : Browser , selectors : Selectors ) {
129+ const connectedBrowser = new ConnectedBrowser ( scope , browser , selectors ) ;
125130 super ( scope , { } , 'RemoteBrowser' , {
126131 selectors : new SelectorsDispatcher ( scope , selectors ) ,
127- browser,
132+ browser : connectedBrowser ,
128133 } , false , 'remoteBrowser' ) ;
134+ this . connectedBrowser = connectedBrowser ;
135+ connectedBrowser . _remoteBrowser = this ;
129136 }
130137}
131138
132139class ConnectedBrowser extends BrowserDispatcher {
133140 private _contexts : BrowserContextDispatcher [ ] = [ ] ;
134141 private _selectors : Selectors ;
135142 _closed = false ;
143+ _remoteBrowser ?: RemoteBrowserDispatcher ;
136144
137145 constructor ( scope : DispatcherScope , browser : Browser , selectors : Selectors ) {
138146 super ( scope , browser ) ;
139147 this . _selectors = selectors ;
140148 }
141149
142150 async newContext ( params : channels . BrowserNewContextParams ) : Promise < { context : channels . BrowserContextChannel } > {
151+ if ( params . videosPath ) {
152+ // TODO: we should create a separate temp directory or accept a launchServer parameter.
153+ params . videosPath = this . _object . _options . downloadsPath ;
154+ }
143155 const result = await super . newContext ( params ) ;
144156 const dispatcher = result . context as BrowserContextDispatcher ;
157+ dispatcher . _object . on ( BrowserContext . Events . VideoStarted , ( video : Video ) => this . _sendVideo ( dispatcher , video ) ) ;
145158 dispatcher . _object . _setSelectors ( this . _selectors ) ;
146159 this . _contexts . push ( dispatcher ) ;
147160 return result ;
@@ -162,4 +175,18 @@ class ConnectedBrowser extends BrowserDispatcher {
162175 super . _didClose ( ) ;
163176 }
164177 }
178+
179+ private _sendVideo ( contextDispatcher : BrowserContextDispatcher , video : Video ) {
180+ video . _waitForCallbackOnFinish ( async ( ) => {
181+ const readable = fs . createReadStream ( video . _path ) ;
182+ await new Promise ( f => readable . on ( 'readable' , f ) ) ;
183+ const stream = new StreamDispatcher ( this . _remoteBrowser ! . _scope , readable ) ;
184+ this . _remoteBrowser ! . _dispatchEvent ( 'video' , { stream, context : contextDispatcher } ) ;
185+ await new Promise < void > ( resolve => {
186+ readable . on ( 'close' , resolve ) ;
187+ readable . on ( 'end' , resolve ) ;
188+ readable . on ( 'error' , resolve ) ;
189+ } ) ;
190+ } ) ;
191+ }
165192}
0 commit comments