Merging chrome-provided port feature from v1

This commit is contained in:
Eric Cornelson 2019-08-29 16:15:13 -07:00
Родитель cae9fae261
Коммит 7d7ad1df2d
4 изменённых файлов: 122 добавлений и 2 удалений

Просмотреть файл

@ -15,6 +15,7 @@ import { CDTPResourceContentGetter } from './cdtpComponents/cdtpResourceContentG
import { ShowOverlayWhenPaused, CDTPDeprecatedPage } from './features/showOverlayWhenPaused';
import { CustomizedUninitializedCDA } from './components/customizedUninitializedCDA';
import { ReportVersionInformation } from './features/reportVersionInformation';
import { ChromeProvidedPortConnection } from './chromeProvidedPortConnection';
const EXTENSION_NAME = 'debugger-for-chrome';
@ -46,6 +47,7 @@ extensibilityPoints.bindAdditionalComponents = (diContainer: DependencyInjection
diContainer.configureClass(TYPES.IServiceComponent, ReportVersionInformation);
diContainer.configureClass(CDTPDeprecatedPage, CDTPDeprecatedPage);
};
extensibilityPoints.chromeConnection = ChromeProvidedPortConnection;
ChromeDebugSession.run(ChromeDebugSession.getSession(
{

Просмотреть файл

@ -0,0 +1,55 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { chromeConnection } from 'vscode-chrome-debug-core';
import { utils, chromeUtils } from 'vscode-chrome-debug-core';
import { logger } from 'vscode-chrome-debug-core';
import * as errors from './errors';
/**
* Chrome connection class that supports launching with --remote-debugging-port=0 to get a random port for the debug session
*/
export class ChromeProvidedPortConnection extends chromeConnection.ChromeConnection {
private userDataDir: string | undefined = undefined;
setUserDataDir(userDataDir: string) {
this.userDataDir = userDataDir;
}
/**
* Attach the websocket to the first available tab in the chrome instance with the given remote debugging port number.
* If we launched with port = 0, then this method will read the launched port from the user data directory, and wait until the port is open
* before calling super.attach
*/
public attach(address = '127.0.0.1', port = 9222, targetUrl?: string, timeout = chromeConnection.ChromeConnection.ATTACH_TIMEOUT, extraCRDPChannelPort?: number): Promise<void> {
if (port === 0 && (this.userDataDir === undefined || this.userDataDir === '')) return errors.chromeProvidedPortWithoutUserDataDir();
return utils.retryAsync(async () => {
const launchedPort = (port === 0 && this.userDataDir) ? await this.getLaunchedPort(address, this.userDataDir) : port;
return launchedPort;
}, timeout, /*intervalDelay=*/200)
.catch(err => Promise.reject(err))
.then(launchedPort => {
return super.attach(address, launchedPort, targetUrl, timeout, extraCRDPChannelPort);
});
}
/**
* Gets the port on which chrome was launched, and throw error if the port is not open or accepting connections
* @param host The host address on which to check if the port is listening
* @param userDataDir Chrome user data directory in which to check for a port file
*/
private async getLaunchedPort(host: string, userDataDir: string): Promise<number> {
logger.verbose('Looking for DevToolsActivePort file...');
const launchedPort = await chromeUtils.getLaunchedPort(userDataDir);
logger.verbose('Got the port, checking if its ready...');
const portInUse = await chromeUtils.isPortInUse(launchedPort, host, 100);
if (!portInUse) {
// bail, the port isn't open
logger.verbose('Port not open yet...');
return errors.couldNotConnectToPort(host, launchedPort);
}
return launchedPort;
}
}

Просмотреть файл

@ -18,3 +18,20 @@ export function getNotExistErrorResponse(attribute: string, path: string): Promi
variables: { path }
}));
}
export function chromeProvidedPortWithoutUserDataDir() {
return Promise.reject(new ErrorWithMessage(<DebugProtocol.Message>{
id: 2008,
format: localize('random.port.no.userdatadir', 'When the remote debugging port is set to 0, you must also provide the "userDataDir" launch argument'),
sendTelemetry: true
}));
}
export function couldNotConnectToPort(address: string, port: number) {
return Promise.reject(new ErrorWithMessage(<DebugProtocol.Message>{
id: 2008,
format: localize('launch.port.not.open', 'Could not open a connection to Chrome at: {address}:{port}', '{address}', '{port}'),
variables: { address, port: port.toString() },
sendTelemetry: true
}));
}

Просмотреть файл

@ -15,8 +15,9 @@ import { isWindows } from './testSetup';
import * as puppeteer from 'puppeteer';
import { expect } from 'chai';
import { killAllChrome } from '../testUtils';
import { IAttachRequestArgs } from 'vscode-chrome-debug-core';
import { IAttachRequestArgs, utils } from 'vscode-chrome-debug-core';
import { getDebugAdapterLogFilePath } from './utils/logging';
import { DebugClient } from 'vscode-debugadapter-testsupport';
const DATA_ROOT = testSetup.DATA_ROOT;
@ -185,5 +186,50 @@ suite('Chrome Debug Adapter etc', () => {
// force kill chrome here, as it will be left open by the debug adapter (same behavior as v1)
killAllChrome();
});
test('Should launch successfully on port 0', async () => {
// browser already launched to the default port, and navigated away from about:blank
const remoteDebuggingPort = 0;
await Promise.all([
dc.configurationSequence(),
dc.launch({ url: 'http://localhost:7890', timeout: 5000, webRoot: testProjectRoot, port: remoteDebuggingPort }),
]);
// wait for url to === http://localhost:7890 (launch response can come back before the navigation completes)
return waitForUrl(dc, 'http://localhost:7890/');
});
test('Should launch successfully on port 0, even when a browser instance is already running', async () => {
// browser already launched to the default port, and navigated away from about:blank
const remoteDebuggingPort = 0;
const dataDir = path.join(__dirname, 'testDataDir');
const browser = await puppeteer.launch({ headless: false, args: ['https://bing.com', `--user-data-dir=${dataDir}`, `--remote-debugging-port=${remoteDebuggingPort}`] });
try {
await Promise.all([
dc.configurationSequence(),
dc.launch({ url: 'http://localhost:7890', timeout: 5000, webRoot: testProjectRoot, port: remoteDebuggingPort, userDataDir: dataDir }),
]);
await waitForUrl(dc, 'http://localhost:7890/');
} finally {
await browser.close();
}
});
});
});
});
async function waitForUrl(dc: DebugClient, url: string): Promise<string> {
const timeoutMs = 5000;
const intervalDelayMs = 50;
return await utils.retryAsync(async () => {
const response = await dc.evaluateRequest({
context: 'repl',
expression: 'window.location.href'
});
expect(response.body.result).to.equal(`"${url}"`);
return url;
}, timeoutMs, intervalDelayMs).catch(err => { throw err; });
}