Skip to content
This repository was archived by the owner on Dec 6, 2022. It is now read-only.

Commit 0bf1e63

Browse files
authored
Merge pull request #680 from changsi-an/master
Add the supportsLaunchUnelevatedProcessRequest flag to the telemetry.
2 parents c35c805 + ec0a337 commit 0bf1e63

3 files changed

Lines changed: 107 additions & 18 deletions

File tree

src/chromeDebugAdapter.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ const DefaultWebSourceMapPathOverrides: ISourceMapPathOverrides = {
2828
'meteor://💻app/*': '${webRoot}/*'
2929
};
3030

31-
interface IExtendedInitializeRequestArguments extends DebugProtocol.InitializeRequestArguments{
32-
supportsLaunchUnelevatedProcessRequest?: boolean
31+
interface IExtendedInitializeRequestArguments extends DebugProtocol.InitializeRequestArguments {
32+
supportsLaunchUnelevatedProcessRequest?: boolean;
3333
}
3434

3535
export class ChromeDebugAdapter extends CoreDebugAdapter {
@@ -67,6 +67,9 @@ export class ChromeDebugAdapter extends CoreDebugAdapter {
6767
if (args.shouldLaunchChromeUnelevated !== undefined) {
6868
telemetryPropertyCollector.addTelemetryProperty('shouldLaunchChromeUnelevated', args.shouldLaunchChromeUnelevated.toString());
6969
}
70+
if (this._doesHostSupportLaunchUnelevatedProcessRequest) {
71+
telemetryPropertyCollector.addTelemetryProperty('doesHostSupportLaunchUnelevated', 'true');
72+
}
7073
if (args.runtimeExecutable) {
7174
const re = findExecutable(args.runtimeExecutable);
7275
if (!re) {
@@ -450,14 +453,14 @@ export class ChromeDebugAdapter extends CoreDebugAdapter {
450453
return parseInt(pidStr, 10);
451454
}
452455

453-
return null
456+
return null;
454457
}
455458

456459
private async spawnChromeUnelevatedWithClient(chromePath: string, chromeArgs: string[]): Promise<number> {
457460
return new Promise<number>((resolve, reject) => {
458-
this._session.sendRequest("launchUnelevated", {
459-
"process": chromePath,
460-
"args": chromeArgs
461+
this._session.sendRequest('launchUnelevated', {
462+
'process': chromePath,
463+
'args': chromeArgs
461464
}, 10000, (response) => {
462465
if (!response.success) {
463466
reject(new Error(response.message));

src/chromeDebugInterfaces.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export interface ISetExpressionArgs {
3434
expression: string;
3535
value: string;
3636
frameId: number;
37-
format?: DebugProtocol.ValueFormat
37+
format?: DebugProtocol.ValueFormat;
3838
timeout?: number;
3939
}
4040

test/chromeDebugAdapter.test.ts

Lines changed: 97 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*--------------------------------------------------------*/
44

55
import { DebugProtocol } from 'vscode-debugprotocol';
6-
import { chromeConnection, ISourceMapPathOverrides, telemetry } from 'vscode-chrome-debug-core';
6+
import { chromeConnection, ISourceMapPathOverrides, telemetry, utils as coreUtils, ChromeDebugSession } from 'vscode-chrome-debug-core';
77

88
import * as mockery from 'mockery';
99
import { EventEmitter } from 'events';
@@ -30,6 +30,7 @@ suite('ChromeDebugAdapter', () => {
3030
let mockEventEmitter: EventEmitter;
3131
let mockChrome: IMockChromeConnectionAPI;
3232

33+
let mockChromeDebugSession: IMock<MockChromeDebugSession>;
3334
let chromeDebugAdapter: _ChromeDebugAdapter;
3435

3536
setup(() => {
@@ -41,6 +42,14 @@ suite('ChromeDebugAdapter', () => {
4142
mockChromeConnection = Mock.ofType(chromeConnection.ChromeConnection, MockBehavior.Strict);
4243
mockChrome = getMockChromeConnectionApi();
4344
mockEventEmitter = mockChrome.mockEventEmitter;
45+
mockChromeDebugSession = Mock.ofType(MockChromeDebugSession, MockBehavior.Strict);
46+
mockChromeDebugSession
47+
.setup(x => x.sendEvent(It.isAny()))
48+
.verifiable(Times.atLeast(0));
49+
mockChromeDebugSession
50+
.setup(x => x.sendRequest(It.isAnyString(), It.isAny(), It.isAnyNumber(), It.isAny()))
51+
.verifiable(Times.atLeast(0));
52+
4453
mockChromeConnection
4554
.setup(x => x.api)
4655
.returns(() => mockChrome.apiObjects)
@@ -67,7 +76,7 @@ suite('ChromeDebugAdapter', () => {
6776

6877
// Instantiate the ChromeDebugAdapter, injecting the mock ChromeConnection
6978
const cDAClass: typeof _ChromeDebugAdapter = require(MODULE_UNDER_TEST).ChromeDebugAdapter;
70-
chromeDebugAdapter = new cDAClass({ chromeConnection: function() { return mockChromeConnection.object; } } as any, new MockChromeDebugSession() as any);
79+
chromeDebugAdapter = new cDAClass({ chromeConnection: function() { return mockChromeConnection.object; } } as any, mockChromeDebugSession.object as any);
7180
});
7281

7382
teardown(() => {
@@ -82,6 +91,17 @@ suite('ChromeDebugAdapter', () => {
8291
let originalSpawn: any;
8392
let originalStatSync: any;
8493

94+
setup(() => {
95+
mockChromeConnection
96+
.setup(x => x.attach(It.isValue(undefined), It.isAnyNumber(), It.isAnyString(), It.isValue(undefined), It.isValue(undefined)))
97+
.returns(() => Promise.resolve())
98+
.verifiable();
99+
100+
mockChrome.Runtime
101+
.setup(x => x.evaluate(It.isAny()))
102+
.returns(() => Promise.resolve<any>({ result: { type: 'string', value: '123' }}));
103+
});
104+
85105
teardown(() => {
86106
// Hacky mock cleanup
87107
require('child_process').fork = originalFork;
@@ -117,19 +137,85 @@ suite('ChromeDebugAdapter', () => {
117137
originalStatSync = require('fs').statSync;
118138
require('fs').statSync = () => true;
119139

120-
mockChromeConnection
121-
.setup(x => x.attach(It.isValue(undefined), It.isAnyNumber(), It.isAnyString(), It.isValue(undefined), It.isValue(undefined)))
122-
.returns(() => Promise.resolve())
123-
.verifiable();
124-
125-
mockChrome.Runtime
126-
.setup(x => x.evaluate(It.isAny()))
127-
.returns(() => Promise.resolve<any>({ result: { type: 'string', value: '123' }}));
128-
129140
return chromeDebugAdapter.launch({ file: 'c:\\path with space\\index.html', runtimeArgs: ['abc', 'def'] },
130141
new telemetry.TelemetryPropertyCollector())
131142
.then(() => assert(spawnCalled));
132143
});
144+
145+
test('launches unelevated with client', async () => {
146+
let telemetryPropertyCollector = new telemetry.TelemetryPropertyCollector();
147+
chromeDebugAdapter.initialize({
148+
adapterID: 'test debug adapter',
149+
pathFormat: 'path',
150+
supportsLaunchUnelevatedProcessRequest: true
151+
});
152+
153+
const originalGetPlatform = require('os').platform;
154+
require('os').platform = () => { return 'win32'; };
155+
156+
const originalGetBrowser = require('../src/utils').getBrowserPath;
157+
require('../src/utils').getBrowserPath = () => { return 'c:\\someplace\\chrome.exe'; };
158+
159+
const expectedProcessId = 325;
160+
let collectedLaunchParams: any;
161+
mockChromeDebugSession
162+
.setup(x => x.sendRequest('launchUnelevated',
163+
It.is((x: any) => {
164+
collectedLaunchParams = x;
165+
return true;
166+
}),
167+
10000,
168+
It.is(
169+
(callback: (response: DebugProtocol.Response) => void) => {
170+
callback({
171+
seq: null,
172+
type: 'command',
173+
request_seq: 100,
174+
command: 'launchUnelevated',
175+
success: true,
176+
body: {
177+
processId: expectedProcessId
178+
}
179+
});
180+
return true;
181+
})))
182+
.verifiable(Times.atLeast(1));
183+
184+
await chromeDebugAdapter.launch({
185+
file: 'c:\\path with space\\index.html',
186+
runtimeArgs: ['abc', 'def'],
187+
shouldLaunchChromeUnelevated: true
188+
}, telemetryPropertyCollector);
189+
190+
assert.equal(expectedProcessId, (<any>chromeDebugAdapter)._chromePID, 'Debug Adapter should receive the Chrome process id');
191+
assert(collectedLaunchParams.process != null);
192+
assert(collectedLaunchParams.process.match(/chrome/i));
193+
assert(collectedLaunchParams.args != null);
194+
195+
assert(collectedLaunchParams.args.filter((x) => x == '--no-default-browser-check').length != 0,
196+
'Should have seen the --no-default-browser-check parameter');
197+
assert(collectedLaunchParams.args.filter((x) => x == '--no-first-run').length != 0,
198+
'Should have seen the --no-first-run parameter');
199+
assert(collectedLaunchParams.args.filter((x) => x == 'abc').length != 0,
200+
'Should have seen the abc parameter');
201+
assert(collectedLaunchParams.args.filter((x) => x == 'def').length != 0,
202+
'Should have seen the def parameter');
203+
assert(collectedLaunchParams.args.filter((x) => x == 'about:blank').length != 0,
204+
'Should have seen the about:blank parameter');
205+
assert(collectedLaunchParams.args.filter((x) => x.match(/remote-debugging-port/)).length != 0,
206+
'Should have seen a parameter like remote-debugging-port');
207+
assert(collectedLaunchParams.args.filter((x) => x.match(/user-data-dir/)).length != 0,
208+
'Should have seen a parameter like user-data-dir');
209+
210+
const telemetryProperties = telemetryPropertyCollector.getProperties();
211+
assert.equal(telemetryProperties.shouldLaunchChromeUnelevated, 'true', "Should send telemetry that Chrome is requested to be launched unelevated.'");
212+
assert.equal(telemetryProperties.doesHostSupportLaunchUnelevated, 'true', "Should send telemetry that host supports launcheing Chrome unelevated.'");
213+
214+
require('os').platform = originalGetPlatform;
215+
require('../src/utils').getBrowserPath = originalGetBrowser;
216+
217+
return Promise.resolve();
218+
});
133219
});
134220

135221
suite('resolveWebRootPattern', () => {

0 commit comments

Comments
 (0)