mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore(agnostification): split up launcher class (#6484)
The `Launcher` class was serving two purposes: 1. Launch browsers 2. Connect to browsers Number 1) only needs to be done in Node land, but 2) is agnostic; in a browser version of Puppeteer we'll need the ability to connect over a websocket to send commands back and forth. As part of the agnostification work we needed to split the `Launcher` up so that the connection part can be made agnostic. Additionally, I removed dependencies on `https`, `http` and `URL` from Node, instead leaning on fetch (via `node-fetch` if in Node land) and the browser `URL` API (which was added to Node in Node 10).
This commit is contained in:
parent
1ed38af79a
commit
4846b8723c
@ -1,22 +0,0 @@
|
|||||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
|
||||||
|
|
||||||
[Home](./index.md) > [puppeteer](./puppeteer.md) > [ProductLauncher](./puppeteer.productlauncher.md) > [connect](./puppeteer.productlauncher.connect.md)
|
|
||||||
|
|
||||||
## ProductLauncher.connect() method
|
|
||||||
|
|
||||||
<b>Signature:</b>
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
connect(object: any): any;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Parameters
|
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| object | any | |
|
|
||||||
|
|
||||||
<b>Returns:</b>
|
|
||||||
|
|
||||||
any
|
|
||||||
|
|
@ -17,13 +17,12 @@ export interface ProductLauncher
|
|||||||
| Property | Type | Description |
|
| Property | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| [executablePath](./puppeteer.productlauncher.executablepath.md) | () => string | |
|
| [executablePath](./puppeteer.productlauncher.executablepath.md) | () => string | |
|
||||||
| [product](./puppeteer.productlauncher.product.md) | string | |
|
| [product](./puppeteer.productlauncher.product.md) | [Product](./puppeteer.product.md) | |
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
| Method | Description |
|
| Method | Description |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| [connect(object)](./puppeteer.productlauncher.connect.md) | |
|
|
||||||
| [defaultArgs(object)](./puppeteer.productlauncher.defaultargs.md) | |
|
| [defaultArgs(object)](./puppeteer.productlauncher.defaultargs.md) | |
|
||||||
| [launch(object)](./puppeteer.productlauncher.launch.md) | |
|
| [launch(object)](./puppeteer.productlauncher.launch.md) | |
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
<b>Signature:</b>
|
<b>Signature:</b>
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
product: string;
|
product: Product;
|
||||||
```
|
```
|
||||||
|
@ -13,7 +13,7 @@ connect(options: BrowserOptions & {
|
|||||||
browserWSEndpoint?: string;
|
browserWSEndpoint?: string;
|
||||||
browserURL?: string;
|
browserURL?: string;
|
||||||
transport?: ConnectionTransport;
|
transport?: ConnectionTransport;
|
||||||
product?: string;
|
product?: Product;
|
||||||
}): Promise<Browser>;
|
}): Promise<Browser>;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ connect(options: BrowserOptions & {
|
|||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| options | [BrowserOptions](./puppeteer.browseroptions.md) & { browserWSEndpoint?: string; browserURL?: string; transport?: ConnectionTransport; product?: string; } | Set of configurable options to set on the browser. |
|
| options | [BrowserOptions](./puppeteer.browseroptions.md) & { browserWSEndpoint?: string; browserURL?: string; transport?: ConnectionTransport; product?: [Product](./puppeteer.product.md)<!-- -->; } | Set of configurable options to set on the browser. |
|
||||||
|
|
||||||
<b>Returns:</b>
|
<b>Returns:</b>
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
"devtools-protocol": "0.0.809251",
|
"devtools-protocol": "0.0.809251",
|
||||||
"extract-zip": "^2.0.0",
|
"extract-zip": "^2.0.0",
|
||||||
"https-proxy-agent": "^4.0.0",
|
"https-proxy-agent": "^4.0.0",
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
"pkg-dir": "^4.2.0",
|
"pkg-dir": "^4.2.0",
|
||||||
"progress": "^2.0.1",
|
"progress": "^2.0.1",
|
||||||
"proxy-from-env": "^1.0.0",
|
"proxy-from-env": "^1.0.0",
|
||||||
|
@ -41,9 +41,11 @@ export * from './common/FileChooser.js';
|
|||||||
export * from './common/FrameManager.js';
|
export * from './common/FrameManager.js';
|
||||||
export * from './common/Input.js';
|
export * from './common/Input.js';
|
||||||
export * from './common/Page.js';
|
export * from './common/Page.js';
|
||||||
|
export * from './common/Product.js';
|
||||||
export * from './common/Puppeteer.js';
|
export * from './common/Puppeteer.js';
|
||||||
export * from './node/LaunchOptions.js';
|
export * from './common/BrowserConnector.js';
|
||||||
export * from './node/Launcher.js';
|
export * from './node/Launcher.js';
|
||||||
|
export * from './node/LaunchOptions.js';
|
||||||
export * from './common/HTTPRequest.js';
|
export * from './common/HTTPRequest.js';
|
||||||
export * from './common/HTTPResponse.js';
|
export * from './common/HTTPResponse.js';
|
||||||
export * from './common/SecurityDetails.js';
|
export * from './common/SecurityDetails.js';
|
||||||
|
109
src/common/BrowserConnector.ts
Normal file
109
src/common/BrowserConnector.ts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ConnectionTransport } from './ConnectionTransport.js';
|
||||||
|
import { Browser } from './Browser.js';
|
||||||
|
import { assert } from './assert.js';
|
||||||
|
import { debugError } from '../common/helper.js';
|
||||||
|
import { Connection } from './Connection.js';
|
||||||
|
import { WebSocketTransport } from './WebSocketTransport.js';
|
||||||
|
import { getFetch } from './fetch.js';
|
||||||
|
import { Viewport } from './PuppeteerViewport.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic browser options that can be passed when launching any browser.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface BrowserOptions {
|
||||||
|
ignoreHTTPSErrors?: boolean;
|
||||||
|
defaultViewport?: Viewport;
|
||||||
|
slowMo?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Users should never call this directly; it's called when calling
|
||||||
|
* `puppeteer.connect`.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export const connectToBrowser = async (
|
||||||
|
options: BrowserOptions & {
|
||||||
|
browserWSEndpoint?: string;
|
||||||
|
browserURL?: string;
|
||||||
|
transport?: ConnectionTransport;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const {
|
||||||
|
browserWSEndpoint,
|
||||||
|
browserURL,
|
||||||
|
ignoreHTTPSErrors = false,
|
||||||
|
defaultViewport = { width: 800, height: 600 },
|
||||||
|
transport,
|
||||||
|
slowMo = 0,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
assert(
|
||||||
|
Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) ===
|
||||||
|
1,
|
||||||
|
'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'
|
||||||
|
);
|
||||||
|
|
||||||
|
let connection = null;
|
||||||
|
if (transport) {
|
||||||
|
connection = new Connection('', transport, slowMo);
|
||||||
|
} else if (browserWSEndpoint) {
|
||||||
|
const connectionTransport = await WebSocketTransport.create(
|
||||||
|
browserWSEndpoint
|
||||||
|
);
|
||||||
|
connection = new Connection(browserWSEndpoint, connectionTransport, slowMo);
|
||||||
|
} else if (browserURL) {
|
||||||
|
const connectionURL = await getWSEndpoint(browserURL);
|
||||||
|
const connectionTransport = await WebSocketTransport.create(connectionURL);
|
||||||
|
connection = new Connection(connectionURL, connectionTransport, slowMo);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { browserContextIds } = await connection.send(
|
||||||
|
'Target.getBrowserContexts'
|
||||||
|
);
|
||||||
|
return Browser.create(
|
||||||
|
connection,
|
||||||
|
browserContextIds,
|
||||||
|
ignoreHTTPSErrors,
|
||||||
|
defaultViewport,
|
||||||
|
null,
|
||||||
|
() => connection.send('Browser.close').catch(debugError)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
async function getWSEndpoint(browserURL: string): Promise<string> {
|
||||||
|
const endpointURL = new URL('/json/version', browserURL);
|
||||||
|
|
||||||
|
const fetch = await getFetch();
|
||||||
|
try {
|
||||||
|
const result = await fetch(endpointURL.toString(), {
|
||||||
|
method: 'GET',
|
||||||
|
});
|
||||||
|
if (!result.ok) {
|
||||||
|
throw new Error(`HTTP ${result.statusText}`);
|
||||||
|
}
|
||||||
|
const data = await result.json();
|
||||||
|
return data.webSocketDebuggerUrl;
|
||||||
|
} catch (error) {
|
||||||
|
error.message =
|
||||||
|
`Failed to fetch browser webSocket URL from ${endpointURL}: ` +
|
||||||
|
error.message;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
21
src/common/Product.ts
Normal file
21
src/common/Product.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported products.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export type Product = 'chrome' | 'firefox';
|
@ -14,11 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import Launcher from '../node/Launcher.js';
|
import Launcher from '../node/Launcher.js';
|
||||||
import {
|
import { LaunchOptions, ChromeArgOptions } from '../node/LaunchOptions.js';
|
||||||
LaunchOptions,
|
|
||||||
ChromeArgOptions,
|
|
||||||
BrowserOptions,
|
|
||||||
} from '../node/LaunchOptions.js';
|
|
||||||
import { ProductLauncher } from '../node/Launcher.js';
|
import { ProductLauncher } from '../node/Launcher.js';
|
||||||
import {
|
import {
|
||||||
BrowserFetcher,
|
BrowserFetcher,
|
||||||
@ -36,6 +32,8 @@ import {
|
|||||||
CustomQueryHandler,
|
CustomQueryHandler,
|
||||||
} from './QueryHandler.js';
|
} from './QueryHandler.js';
|
||||||
import { PUPPETEER_REVISIONS } from '../revisions.js';
|
import { PUPPETEER_REVISIONS } from '../revisions.js';
|
||||||
|
import { Product } from './Product.js';
|
||||||
|
import { connectToBrowser, BrowserOptions } from './BrowserConnector.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main Puppeteer class. Provides the {@link Puppeteer.launch | launch}
|
* The main Puppeteer class. Provides the {@link Puppeteer.launch | launch}
|
||||||
@ -141,11 +139,11 @@ export class Puppeteer {
|
|||||||
browserWSEndpoint?: string;
|
browserWSEndpoint?: string;
|
||||||
browserURL?: string;
|
browserURL?: string;
|
||||||
transport?: ConnectionTransport;
|
transport?: ConnectionTransport;
|
||||||
product?: string;
|
product?: Product;
|
||||||
}
|
}
|
||||||
): Promise<Browser> {
|
): Promise<Browser> {
|
||||||
if (options.product) this._productName = options.product;
|
if (options.product) this._productName = options.product;
|
||||||
return this._launcher.connect(options);
|
return connectToBrowser(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
22
src/common/fetch.ts
Normal file
22
src/common/fetch.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2020 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { isNode } from '../environment.js';
|
||||||
|
|
||||||
|
/* Use the global version if we're in the browser, else load the node-fetch module. */
|
||||||
|
export const getFetch = async (): Promise<typeof fetch> => {
|
||||||
|
return isNode ? await import('node-fetch') : globalThis.fetch;
|
||||||
|
};
|
@ -22,6 +22,7 @@ import * as childProcess from 'child_process';
|
|||||||
import * as https from 'https';
|
import * as https from 'https';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
|
|
||||||
|
import { Product } from '../common/Product.js';
|
||||||
import extractZip from 'extract-zip';
|
import extractZip from 'extract-zip';
|
||||||
import { debug } from '../common/Debug.js';
|
import { debug } from '../common/Debug.js';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
@ -65,11 +66,6 @@ const browserConfig = {
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export type Platform = 'linux' | 'mac' | 'win32' | 'win64';
|
export type Platform = 'linux' | 'mac' | 'win32' | 'win64';
|
||||||
/**
|
|
||||||
* Supported products.
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export type Product = 'chrome' | 'firefox';
|
|
||||||
|
|
||||||
function archiveName(
|
function archiveName(
|
||||||
product: Product,
|
product: Product,
|
||||||
|
@ -13,9 +13,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Viewport } from '../common/PuppeteerViewport.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launcher options that only apply to Chrome.
|
* Launcher options that only apply to Chrome.
|
||||||
*
|
*
|
||||||
@ -43,13 +40,3 @@ export interface LaunchOptions {
|
|||||||
env?: Record<string, string | undefined>;
|
env?: Record<string, string | undefined>;
|
||||||
pipe?: boolean;
|
pipe?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic browser options that can be passed when launching any browser.
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export interface BrowserOptions {
|
|
||||||
ignoreHTTPSErrors?: boolean;
|
|
||||||
defaultViewport?: Viewport;
|
|
||||||
slowMo?: number;
|
|
||||||
}
|
|
||||||
|
@ -15,29 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as http from 'http';
|
|
||||||
import * as https from 'https';
|
|
||||||
import * as URL from 'url';
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
import { BrowserFetcher } from './BrowserFetcher.js';
|
import { BrowserFetcher } from './BrowserFetcher.js';
|
||||||
import { Connection } from '../common/Connection.js';
|
|
||||||
import { Browser } from '../common/Browser.js';
|
import { Browser } from '../common/Browser.js';
|
||||||
import { assert } from '../common/assert.js';
|
|
||||||
import { debugError } from '../common/helper.js';
|
|
||||||
import { ConnectionTransport } from '../common/ConnectionTransport.js';
|
|
||||||
import { WebSocketTransport } from '../common/WebSocketTransport.js';
|
|
||||||
import { BrowserRunner } from './BrowserRunner.js';
|
import { BrowserRunner } from './BrowserRunner.js';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
|
|
||||||
const mkdtempAsync = promisify(fs.mkdtemp);
|
const mkdtempAsync = promisify(fs.mkdtemp);
|
||||||
const writeFileAsync = promisify(fs.writeFile);
|
const writeFileAsync = promisify(fs.writeFile);
|
||||||
|
|
||||||
import {
|
import { ChromeArgOptions, LaunchOptions } from './LaunchOptions.js';
|
||||||
ChromeArgOptions,
|
import { BrowserOptions } from '../common/BrowserConnector.js';
|
||||||
LaunchOptions,
|
import { Product } from '../common/Product.js';
|
||||||
BrowserOptions,
|
|
||||||
} from './LaunchOptions.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes a launcher - a class that is able to create and launch a browser instance.
|
* Describes a launcher - a class that is able to create and launch a browser instance.
|
||||||
@ -45,10 +35,9 @@ import {
|
|||||||
*/
|
*/
|
||||||
export interface ProductLauncher {
|
export interface ProductLauncher {
|
||||||
launch(object);
|
launch(object);
|
||||||
connect(object);
|
|
||||||
executablePath: () => string;
|
executablePath: () => string;
|
||||||
defaultArgs(object);
|
defaultArgs(object);
|
||||||
product: string;
|
product: Product;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -215,66 +204,9 @@ class ChromeLauncher implements ProductLauncher {
|
|||||||
return resolveExecutablePath(this).executablePath;
|
return resolveExecutablePath(this).executablePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
get product(): string {
|
get product(): Product {
|
||||||
return 'chrome';
|
return 'chrome';
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(
|
|
||||||
options: BrowserOptions & {
|
|
||||||
browserWSEndpoint?: string;
|
|
||||||
browserURL?: string;
|
|
||||||
transport?: ConnectionTransport;
|
|
||||||
}
|
|
||||||
): Promise<Browser> {
|
|
||||||
const {
|
|
||||||
browserWSEndpoint,
|
|
||||||
browserURL,
|
|
||||||
ignoreHTTPSErrors = false,
|
|
||||||
defaultViewport = { width: 800, height: 600 },
|
|
||||||
transport,
|
|
||||||
slowMo = 0,
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
assert(
|
|
||||||
Number(!!browserWSEndpoint) +
|
|
||||||
Number(!!browserURL) +
|
|
||||||
Number(!!transport) ===
|
|
||||||
1,
|
|
||||||
'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'
|
|
||||||
);
|
|
||||||
|
|
||||||
let connection = null;
|
|
||||||
if (transport) {
|
|
||||||
connection = new Connection('', transport, slowMo);
|
|
||||||
} else if (browserWSEndpoint) {
|
|
||||||
const connectionTransport = await WebSocketTransport.create(
|
|
||||||
browserWSEndpoint
|
|
||||||
);
|
|
||||||
connection = new Connection(
|
|
||||||
browserWSEndpoint,
|
|
||||||
connectionTransport,
|
|
||||||
slowMo
|
|
||||||
);
|
|
||||||
} else if (browserURL) {
|
|
||||||
const connectionURL = await getWSEndpoint(browserURL);
|
|
||||||
const connectionTransport = await WebSocketTransport.create(
|
|
||||||
connectionURL
|
|
||||||
);
|
|
||||||
connection = new Connection(connectionURL, connectionTransport, slowMo);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { browserContextIds } = await connection.send(
|
|
||||||
'Target.getBrowserContexts'
|
|
||||||
);
|
|
||||||
return Browser.create(
|
|
||||||
connection,
|
|
||||||
browserContextIds,
|
|
||||||
ignoreHTTPSErrors,
|
|
||||||
defaultViewport,
|
|
||||||
null,
|
|
||||||
() => connection.send('Browser.close').catch(debugError)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -392,63 +324,6 @@ class FirefoxLauncher implements ProductLauncher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(
|
|
||||||
options: BrowserOptions & {
|
|
||||||
browserWSEndpoint?: string;
|
|
||||||
browserURL?: string;
|
|
||||||
transport?: ConnectionTransport;
|
|
||||||
}
|
|
||||||
): Promise<Browser> {
|
|
||||||
const {
|
|
||||||
browserWSEndpoint,
|
|
||||||
browserURL,
|
|
||||||
ignoreHTTPSErrors = false,
|
|
||||||
defaultViewport = { width: 800, height: 600 },
|
|
||||||
transport,
|
|
||||||
slowMo = 0,
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
assert(
|
|
||||||
Number(!!browserWSEndpoint) +
|
|
||||||
Number(!!browserURL) +
|
|
||||||
Number(!!transport) ===
|
|
||||||
1,
|
|
||||||
'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'
|
|
||||||
);
|
|
||||||
|
|
||||||
let connection = null;
|
|
||||||
if (transport) {
|
|
||||||
connection = new Connection('', transport, slowMo);
|
|
||||||
} else if (browserWSEndpoint) {
|
|
||||||
const connectionTransport = await WebSocketTransport.create(
|
|
||||||
browserWSEndpoint
|
|
||||||
);
|
|
||||||
connection = new Connection(
|
|
||||||
browserWSEndpoint,
|
|
||||||
connectionTransport,
|
|
||||||
slowMo
|
|
||||||
);
|
|
||||||
} else if (browserURL) {
|
|
||||||
const connectionURL = await getWSEndpoint(browserURL);
|
|
||||||
const connectionTransport = await WebSocketTransport.create(
|
|
||||||
connectionURL
|
|
||||||
);
|
|
||||||
connection = new Connection(connectionURL, connectionTransport, slowMo);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { browserContextIds } = await connection.send(
|
|
||||||
'Target.getBrowserContexts'
|
|
||||||
);
|
|
||||||
return Browser.create(
|
|
||||||
connection,
|
|
||||||
browserContextIds,
|
|
||||||
ignoreHTTPSErrors,
|
|
||||||
defaultViewport,
|
|
||||||
null,
|
|
||||||
() => connection.send('Browser.close').catch(debugError)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
executablePath(): string {
|
executablePath(): string {
|
||||||
return resolveExecutablePath(this).executablePath;
|
return resolveExecutablePath(this).executablePath;
|
||||||
}
|
}
|
||||||
@ -464,7 +339,7 @@ class FirefoxLauncher implements ProductLauncher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get product(): string {
|
get product(): Product {
|
||||||
return 'firefox';
|
return 'firefox';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,42 +580,6 @@ class FirefoxLauncher implements ProductLauncher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWSEndpoint(browserURL: string): Promise<string> {
|
|
||||||
let resolve, reject;
|
|
||||||
const promise = new Promise<string>((res, rej) => {
|
|
||||||
resolve = res;
|
|
||||||
reject = rej;
|
|
||||||
});
|
|
||||||
|
|
||||||
const endpointURL = URL.resolve(browserURL, '/json/version');
|
|
||||||
const protocol = endpointURL.startsWith('https') ? https : http;
|
|
||||||
const requestOptions = Object.assign(URL.parse(endpointURL), {
|
|
||||||
method: 'GET',
|
|
||||||
});
|
|
||||||
const request = protocol.request(requestOptions, (res) => {
|
|
||||||
let data = '';
|
|
||||||
if (res.statusCode !== 200) {
|
|
||||||
// Consume response data to free up memory.
|
|
||||||
res.resume();
|
|
||||||
reject(new Error('HTTP ' + res.statusCode));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res.setEncoding('utf8');
|
|
||||||
res.on('data', (chunk) => (data += chunk));
|
|
||||||
res.on('end', () => resolve(JSON.parse(data).webSocketDebuggerUrl));
|
|
||||||
});
|
|
||||||
|
|
||||||
request.on('error', reject);
|
|
||||||
request.end();
|
|
||||||
|
|
||||||
return promise.catch((error) => {
|
|
||||||
error.message =
|
|
||||||
`Failed to fetch browser webSocket url from ${endpointURL}: ` +
|
|
||||||
error.message;
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveExecutablePath(
|
function resolveExecutablePath(
|
||||||
launcher: ChromeLauncher | FirefoxLauncher
|
launcher: ChromeLauncher | FirefoxLauncher
|
||||||
): { executablePath: string; missingText?: string } {
|
): { executablePath: string; missingText?: string } {
|
||||||
|
@ -84,7 +84,7 @@ describeChromeOnly('Chromium-Specific Launcher tests', function () {
|
|||||||
.connect({ browserURL })
|
.connect({ browserURL })
|
||||||
.catch((error_) => (error = error_));
|
.catch((error_) => (error = error_));
|
||||||
expect(error.message).toContain(
|
expect(error.message).toContain(
|
||||||
'Failed to fetch browser webSocket url from'
|
'Failed to fetch browser webSocket URL from'
|
||||||
);
|
);
|
||||||
originalBrowser.close();
|
originalBrowser.close();
|
||||||
});
|
});
|
||||||
|
@ -803,6 +803,13 @@ function compareDocumentations(actual, expected) {
|
|||||||
expectedName: 'Array<Object>',
|
expectedName: 'Array<Object>',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'Method Puppeteer.connect() options.product',
|
||||||
|
{
|
||||||
|
actualName: 'string',
|
||||||
|
expectedName: 'Product',
|
||||||
|
},
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const expectedForSource = expectedNamingMismatches.get(source);
|
const expectedForSource = expectedNamingMismatches.get(source);
|
||||||
|
Loading…
Reference in New Issue
Block a user