@@ -28,15 +28,20 @@ const DefaultWebSourceMapPathOverrides: ISourceMapPathOverrides = {
2828 'meteor://💻app/*' : '${webRoot}/*'
2929} ;
3030
31+ interface IExtendedInitializeRequestArguments extends DebugProtocol . InitializeRequestArguments {
32+ supportsLaunchUnelevatedProcessRequest ?: boolean
33+ }
34+
3135export class ChromeDebugAdapter extends CoreDebugAdapter {
3236 private _pagePauseMessage = 'Paused in Visual Studio Code' ;
3337
3438 private _chromeProc : ChildProcess ;
3539 private _overlayHelper : utils . DebounceHelper ;
3640 private _chromePID : number ;
3741 private _userRequestedUrl : string ;
42+ private _doesHostSupportLaunchUnelevatedProcessRequest : boolean ;
3843
39- public initialize ( args : DebugProtocol . InitializeRequestArguments ) : VSDebugProtocolCapabilities {
44+ public initialize ( args : IExtendedInitializeRequestArguments ) : VSDebugProtocolCapabilities {
4045 this . _overlayHelper = new utils . DebounceHelper ( /*timeoutMs=*/ 200 ) ;
4146 const capabilities : VSDebugProtocolCapabilities = super . initialize ( args ) ;
4247 capabilities . supportsRestartRequest = true ;
@@ -47,6 +52,8 @@ export class ChromeDebugAdapter extends CoreDebugAdapter {
4752 localize = nls . config ( { locale : args . locale } ) ( ) ;
4853 }
4954
55+ this . _doesHostSupportLaunchUnelevatedProcessRequest = args . supportsLaunchUnelevatedProcessRequest || false ;
56+
5057 return capabilities ;
5158 }
5259
@@ -353,26 +360,15 @@ export class ChromeDebugAdapter extends CoreDebugAdapter {
353360 this . events . emitStepStarted ( 'LaunchTarget.LaunchExe' ) ;
354361 const platform = coreUtils . getPlatform ( ) ;
355362 if ( platform === coreUtils . Platform . Windows && shouldLaunchUnelevated ) {
356- const semaphoreFile = path . join ( os . tmpdir ( ) , 'launchedUnelevatedChromeProcess.id' ) ;
357- if ( fs . existsSync ( semaphoreFile ) ) { // remove the previous semaphoreFile if it exists.
358- fs . unlinkSync ( semaphoreFile ) ;
359- }
360- const chromeProc = fork ( getChromeSpawnHelperPath ( ) ,
361- [ `${ process . env . windir } \\System32\\cscript.exe` , path . join ( __dirname , 'launchUnelevated.js' ) ,
362- semaphoreFile , chromePath , ...chromeArgs ] , { } ) ;
363-
364- chromeProc . unref ( ) ;
365- await new Promise < void > ( ( resolve , reject ) => {
366- chromeProc . on ( 'message' , resolve ) ;
367- } ) ;
368-
369- const pidStr = await findNewlyLaunchedChromeProcess ( semaphoreFile ) ;
363+ let chromePid : number ;
370364
371- if ( pidStr ) {
372- logger . log ( `Parsed output file and got Chrome PID ${ pidStr } ` ) ;
373- this . _chromePID = parseInt ( pidStr , 10 ) ;
365+ if ( this . _doesHostSupportLaunchUnelevatedProcessRequest ) {
366+ chromePid = await this . spawnChromeUnelevatedWithClient ( chromePath , chromeArgs ) ;
367+ } else {
368+ chromePid = await this . spawnChromeUnelevatedWithWindowsScriptHost ( chromePath , chromeArgs ) ;
374369 }
375370
371+ this . _chromePID = chromePid ;
376372 // Cannot get the real Chrome process, so return null.
377373 return null ;
378374 } else if ( platform === coreUtils . Platform . Windows && ! usingRuntimeExecutable ) {
@@ -433,6 +429,45 @@ export class ChromeDebugAdapter extends CoreDebugAdapter {
433429 }
434430 }
435431
432+ private async spawnChromeUnelevatedWithWindowsScriptHost ( chromePath : string , chromeArgs : string [ ] ) : Promise < number > {
433+ const semaphoreFile = path . join ( os . tmpdir ( ) , 'launchedUnelevatedChromeProcess.id' ) ;
434+ if ( fs . existsSync ( semaphoreFile ) ) { // remove the previous semaphoreFile if it exists.
435+ fs . unlinkSync ( semaphoreFile ) ;
436+ }
437+ const chromeProc = fork ( getChromeSpawnHelperPath ( ) ,
438+ [ `${ process . env . windir } \\System32\\cscript.exe` , path . join ( __dirname , 'launchUnelevated.js' ) ,
439+ semaphoreFile , chromePath , ...chromeArgs ] , { } ) ;
440+
441+ chromeProc . unref ( ) ;
442+ await new Promise < void > ( ( resolve , reject ) => {
443+ chromeProc . on ( 'message' , resolve ) ;
444+ } ) ;
445+
446+ const pidStr = await findNewlyLaunchedChromeProcess ( semaphoreFile ) ;
447+
448+ if ( pidStr ) {
449+ logger . log ( `Parsed output file and got Chrome PID ${ pidStr } ` ) ;
450+ return parseInt ( pidStr , 10 ) ;
451+ }
452+
453+ return null
454+ }
455+
456+ private async spawnChromeUnelevatedWithClient ( chromePath : string , chromeArgs : string [ ] ) : Promise < number > {
457+ return new Promise < number > ( ( resolve , reject ) => {
458+ this . _session . sendRequest ( "launchUnelevated" , {
459+ "process" : chromePath ,
460+ "args" : chromeArgs
461+ } , 10000 , ( response ) => {
462+ if ( ! response . success ) {
463+ reject ( new Error ( response . message ) ) ;
464+ } else {
465+ resolve ( response . body . processId ) ;
466+ }
467+ } ) ;
468+ } ) ;
469+ }
470+
436471 public async setExpression ( args : ISetExpressionArgs ) : Promise < ISetExpressionResponseBody > {
437472 const reconstructedExpression = `${ args . expression } = ${ args . value } ` ;
438473 const evaluateEventArgs : DebugProtocol . EvaluateArguments = {
0 commit comments