mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
feat: expose raw devtools protocol connection (#1770)
feat: expose raw devtools protocol connection This patch introduces `target.createCDPSession` method that allows directly communicating with the target over the Chrome DevTools Protocol. Fixes #31.
This commit is contained in:
parent
ec8e40f1cb
commit
5368051610
48
docs/api.md
48
docs/api.md
@ -87,6 +87,7 @@
|
|||||||
* [page.setUserAgent(userAgent)](#pagesetuseragentuseragent)
|
* [page.setUserAgent(userAgent)](#pagesetuseragentuseragent)
|
||||||
* [page.setViewport(viewport)](#pagesetviewportviewport)
|
* [page.setViewport(viewport)](#pagesetviewportviewport)
|
||||||
* [page.tap(selector)](#pagetapselector)
|
* [page.tap(selector)](#pagetapselector)
|
||||||
|
* [page.target()](#pagetarget)
|
||||||
* [page.title()](#pagetitle)
|
* [page.title()](#pagetitle)
|
||||||
* [page.touchscreen](#pagetouchscreen)
|
* [page.touchscreen](#pagetouchscreen)
|
||||||
* [page.tracing](#pagetracing)
|
* [page.tracing](#pagetracing)
|
||||||
@ -198,9 +199,13 @@
|
|||||||
* [response.text()](#responsetext)
|
* [response.text()](#responsetext)
|
||||||
* [response.url()](#responseurl)
|
* [response.url()](#responseurl)
|
||||||
- [class: Target](#class-target)
|
- [class: Target](#class-target)
|
||||||
|
* [target.createCDPSession()](#targetcreatecdpsession)
|
||||||
* [target.page()](#targetpage)
|
* [target.page()](#targetpage)
|
||||||
* [target.type()](#targettype)
|
* [target.type()](#targettype)
|
||||||
* [target.url()](#targeturl)
|
* [target.url()](#targeturl)
|
||||||
|
- [class: CDPSession](#class-cdpsession)
|
||||||
|
* [cdpSession.detach()](#cdpsessiondetach)
|
||||||
|
* [cdpSession.send(method[, params])](#cdpsessionsendmethod-params)
|
||||||
- [class: Coverage](#class-coverage)
|
- [class: Coverage](#class-coverage)
|
||||||
* [coverage.startCSSCoverage(options)](#coveragestartcsscoverageoptions)
|
* [coverage.startCSSCoverage(options)](#coveragestartcsscoverageoptions)
|
||||||
* [coverage.startJSCoverage(options)](#coveragestartjscoverageoptions)
|
* [coverage.startJSCoverage(options)](#coveragestartjscoverageoptions)
|
||||||
@ -1139,6 +1144,9 @@ In the case of multiple pages in a single browser, each page can have its own vi
|
|||||||
This method fetches an element with `selector`, scrolls it into view if needed, and then uses [page.touchscreen](#pagetouchscreen) to tap in the center of the element.
|
This method fetches an element with `selector`, scrolls it into view if needed, and then uses [page.touchscreen](#pagetouchscreen) to tap in the center of the element.
|
||||||
If there's no element matching `selector`, the method throws an error.
|
If there's no element matching `selector`, the method throws an error.
|
||||||
|
|
||||||
|
#### page.target()
|
||||||
|
- returns: <[Target]> a target this page was created from.
|
||||||
|
|
||||||
#### page.title()
|
#### page.title()
|
||||||
- returns: <[Promise]<[string]>> Returns page's title.
|
- returns: <[Promise]<[string]>> Returns page's title.
|
||||||
|
|
||||||
@ -2166,6 +2174,11 @@ Contains the URL of the response.
|
|||||||
|
|
||||||
### class: Target
|
### class: Target
|
||||||
|
|
||||||
|
#### target.createCDPSession()
|
||||||
|
- returns: <[Promise]<[CDPSession]>>
|
||||||
|
|
||||||
|
Creates a Chrome Devtools Protocol session attached to the target.
|
||||||
|
|
||||||
#### target.page()
|
#### target.page()
|
||||||
- returns: <[Promise]<?[Page]>>
|
- returns: <[Promise]<?[Page]>>
|
||||||
|
|
||||||
@ -2179,6 +2192,40 @@ Identifies what kind of target this is. Can be `"page"`, `"service_worker"`, or
|
|||||||
#### target.url()
|
#### target.url()
|
||||||
- returns: <[string]>
|
- returns: <[string]>
|
||||||
|
|
||||||
|
|
||||||
|
### class: CDPSession
|
||||||
|
|
||||||
|
* extends: [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter)
|
||||||
|
|
||||||
|
The `CDPSession` instances are used to talk raw Chrome Devtools Protocol:
|
||||||
|
- protocol methods can be called with `session.send` method.
|
||||||
|
- protocol events can be subscribed to with `session.on` method.
|
||||||
|
|
||||||
|
Documentation on DevTools Protocol can be found here: [DevTools Protocol Viewer](https://chromedevtools.github.io/devtools-protocol/).
|
||||||
|
|
||||||
|
```js
|
||||||
|
const client = await page.target().createCDPSession();
|
||||||
|
await client.send('Animation.enable');
|
||||||
|
await client.on('Animation.animationCreated', () => console.log('Animation created!'));
|
||||||
|
const response = await client.send('Animation.getPlaybackRate');
|
||||||
|
console.log('playback rate is ' + response.playbackRate);
|
||||||
|
await client.send('Animation.setPlaybackRate', {
|
||||||
|
playbackRate: response.playbackRate / 2
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### cdpSession.detach()
|
||||||
|
- returns: <[Promise]>
|
||||||
|
|
||||||
|
Detaches session from target. Once detached, session won't emit any events and can't be used
|
||||||
|
to send messages.
|
||||||
|
|
||||||
|
#### cdpSession.send(method[, params])
|
||||||
|
- `method` <[string]> protocol method name
|
||||||
|
- `params` <[Object]> Optional method parameters
|
||||||
|
- returns: <[Promise]<[Object]>>
|
||||||
|
|
||||||
|
|
||||||
### class: Coverage
|
### class: Coverage
|
||||||
|
|
||||||
Coverage gathers information about parts of JavaScript and CSS that were used by the page.
|
Coverage gathers information about parts of JavaScript and CSS that were used by the page.
|
||||||
@ -2253,6 +2300,7 @@ reported.
|
|||||||
[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise"
|
[Promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise "Promise"
|
||||||
[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type "String"
|
[string]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type "String"
|
||||||
[stream.Readable]: https://nodejs.org/api/stream.html#stream_class_stream_readable "stream.Readable"
|
[stream.Readable]: https://nodejs.org/api/stream.html#stream_class_stream_readable "stream.Readable"
|
||||||
|
[CDPSession]: #class-cdpsession "CDPSession"
|
||||||
[Error]: https://nodejs.org/api/errors.html#errors_class_error "Error"
|
[Error]: https://nodejs.org/api/errors.html#errors_class_error "Error"
|
||||||
[Frame]: #class-frame "Frame"
|
[Frame]: #class-frame "Frame"
|
||||||
[ConsoleMessage]: #class-consolemessage "ConsoleMessage"
|
[ConsoleMessage]: #class-consolemessage "ConsoleMessage"
|
||||||
|
@ -193,6 +193,7 @@ class Target {
|
|||||||
*/
|
*/
|
||||||
constructor(browser, targetInfo) {
|
constructor(browser, targetInfo) {
|
||||||
this._browser = browser;
|
this._browser = browser;
|
||||||
|
this._targetId = targetInfo.targetId;
|
||||||
this._targetInfo = targetInfo;
|
this._targetInfo = targetInfo;
|
||||||
/** @type {?Promise<!Page>} */
|
/** @type {?Promise<!Page>} */
|
||||||
this._pagePromise = null;
|
this._pagePromise = null;
|
||||||
@ -202,13 +203,20 @@ class Target {
|
|||||||
this._initializedCallback(true);
|
this._initializedCallback(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {!Promise<!Puppeteer.CDPSession>}
|
||||||
|
*/
|
||||||
|
createCDPSession() {
|
||||||
|
return this._browser._connection.createSession(this._targetId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {!Promise<?Page>}
|
* @return {!Promise<?Page>}
|
||||||
*/
|
*/
|
||||||
async page() {
|
async page() {
|
||||||
if (this._targetInfo.type === 'page' && !this._pagePromise) {
|
if (this._targetInfo.type === 'page' && !this._pagePromise) {
|
||||||
this._pagePromise = this._browser._connection.createSession(this._targetInfo.targetId)
|
this._pagePromise = this._browser._connection.createSession(this._targetId)
|
||||||
.then(client => Page.create(client, this._browser._ignoreHTTPSErrors, this._browser._appMode, this._browser._screenshotTaskQueue));
|
.then(client => Page.create(client, this, this._browser._ignoreHTTPSErrors, this._browser._appMode, this._browser._screenshotTaskQueue));
|
||||||
}
|
}
|
||||||
return this._pagePromise;
|
return this._pagePromise;
|
||||||
}
|
}
|
||||||
@ -258,4 +266,4 @@ helper.tracePublicAPI(Target);
|
|||||||
* @property {boolean} attached
|
* @property {boolean} attached
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = { Browser, TaskQueue };
|
module.exports = { Browser, TaskQueue, Target };
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
const {helper} = require('./helper');
|
||||||
const debugProtocol = require('debug')('puppeteer:protocol');
|
const debugProtocol = require('debug')('puppeteer:protocol');
|
||||||
const debugSession = require('debug')('puppeteer:session');
|
const debugSession = require('debug')('puppeteer:session');
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ class Connection extends EventEmitter {
|
|||||||
this._ws = ws;
|
this._ws = ws;
|
||||||
this._ws.on('message', this._onMessage.bind(this));
|
this._ws.on('message', this._onMessage.bind(this));
|
||||||
this._ws.on('close', this._onClose.bind(this));
|
this._ws.on('close', this._onClose.bind(this));
|
||||||
/** @type {!Map<string, !Session>}*/
|
/** @type {!Map<string, !CDPSession>}*/
|
||||||
this._sessions = new Map();
|
this._sessions = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,17 +136,17 @@ class Connection extends EventEmitter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} targetId
|
* @param {string} targetId
|
||||||
* @return {!Promise<!Session>}
|
* @return {!Promise<!CDPSession>}
|
||||||
*/
|
*/
|
||||||
async createSession(targetId) {
|
async createSession(targetId) {
|
||||||
const {sessionId} = await this.send('Target.attachToTarget', {targetId});
|
const {sessionId} = await this.send('Target.attachToTarget', {targetId});
|
||||||
const session = new Session(this, targetId, sessionId);
|
const session = new CDPSession(this, targetId, sessionId);
|
||||||
this._sessions.set(sessionId, session);
|
this._sessions.set(sessionId, session);
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Session extends EventEmitter {
|
class CDPSession extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @param {!Connection} connection
|
* @param {!Connection} connection
|
||||||
* @param {string} targetId
|
* @param {string} targetId
|
||||||
@ -161,13 +162,6 @@ class Session extends EventEmitter {
|
|||||||
this._sessionId = sessionId;
|
this._sessionId = sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
targetId() {
|
|
||||||
return this._targetId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} method
|
* @param {string} method
|
||||||
* @param {!Object=} params
|
* @param {!Object=} params
|
||||||
@ -211,9 +205,8 @@ class Session extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async dispose() {
|
async detach() {
|
||||||
console.assert(!!this._connection, 'Protocol error: Connection closed. Most likely the page has been closed.');
|
await this._connection.send('Target.detachFromTarget', {sessionId: this._sessionId});
|
||||||
await this._connection.send('Target.closeTarget', {targetId: this._targetId});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onClosed() {
|
_onClosed() {
|
||||||
@ -223,6 +216,7 @@ class Session extends EventEmitter {
|
|||||||
this._connection = null;
|
this._connection = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
helper.tracePublicAPI(CDPSession);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Error} error
|
* @param {!Error} error
|
||||||
@ -234,4 +228,4 @@ function rewriteError(error, message) {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {Connection, Session};
|
module.exports = {Connection, CDPSession};
|
||||||
|
@ -25,7 +25,7 @@ const {helper, debugError} = require('./helper');
|
|||||||
|
|
||||||
class Coverage {
|
class Coverage {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
*/
|
*/
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this._jsCoverage = new JSCoverage(client);
|
this._jsCoverage = new JSCoverage(client);
|
||||||
@ -66,7 +66,7 @@ helper.tracePublicAPI(Coverage);
|
|||||||
|
|
||||||
class JSCoverage {
|
class JSCoverage {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
*/
|
*/
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
@ -154,7 +154,7 @@ class JSCoverage {
|
|||||||
|
|
||||||
class CSSCoverage {
|
class CSSCoverage {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
*/
|
*/
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
|
@ -18,7 +18,7 @@ const {helper} = require('./helper');
|
|||||||
|
|
||||||
class Dialog {
|
class Dialog {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
* @param {string} message
|
* @param {string} message
|
||||||
* @param {(string|undefined)} defaultValue
|
* @param {(string|undefined)} defaultValue
|
||||||
|
@ -20,7 +20,7 @@ const {helper, debugError} = require('./helper');
|
|||||||
class ElementHandle extends JSHandle {
|
class ElementHandle extends JSHandle {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.ExecutionContext} context
|
* @param {!Puppeteer.ExecutionContext} context
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {!Object} remoteObject
|
* @param {!Object} remoteObject
|
||||||
* @param {!Puppeteer.Page} page
|
* @param {!Puppeteer.Page} page
|
||||||
*/
|
*/
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
class EmulationManager {
|
class EmulationManager {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
*/
|
*/
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
|
@ -18,7 +18,7 @@ const {helper} = require('./helper');
|
|||||||
|
|
||||||
class ExecutionContext {
|
class ExecutionContext {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {!Object} contextPayload
|
* @param {!Object} contextPayload
|
||||||
* @param {function(*):!JSHandle} objectHandleFactory
|
* @param {function(*):!JSHandle} objectHandleFactory
|
||||||
*/
|
*/
|
||||||
@ -117,7 +117,7 @@ class ExecutionContext {
|
|||||||
class JSHandle {
|
class JSHandle {
|
||||||
/**
|
/**
|
||||||
* @param {!ExecutionContext} context
|
* @param {!ExecutionContext} context
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {!Object} remoteObject
|
* @param {!Object} remoteObject
|
||||||
*/
|
*/
|
||||||
constructor(context, client, remoteObject) {
|
constructor(context, client, remoteObject) {
|
||||||
|
@ -24,7 +24,7 @@ const readFileAsync = helper.promisify(fs.readFile);
|
|||||||
|
|
||||||
class FrameManager extends EventEmitter {
|
class FrameManager extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {{frame: Object, childFrames: ?Array}} frameTree
|
* @param {{frame: Object, childFrames: ?Array}} frameTree
|
||||||
* @param {!Puppeteer.Page} page
|
* @param {!Puppeteer.Page} page
|
||||||
*/
|
*/
|
||||||
@ -226,7 +226,7 @@ FrameManager.Events = {
|
|||||||
*/
|
*/
|
||||||
class Frame {
|
class Frame {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {?Frame} parentFrame
|
* @param {?Frame} parentFrame
|
||||||
* @param {string} frameId
|
* @param {string} frameId
|
||||||
*/
|
*/
|
||||||
|
@ -28,7 +28,7 @@ const keyDefinitions = require('./USKeyboardLayout');
|
|||||||
|
|
||||||
class Keyboard {
|
class Keyboard {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
*/
|
*/
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
@ -189,7 +189,7 @@ class Keyboard {
|
|||||||
|
|
||||||
class Mouse {
|
class Mouse {
|
||||||
/**
|
/**
|
||||||
* @param {Puppeteer.Session} client
|
* @param {Puppeteer.CDPSession} client
|
||||||
* @param {!Keyboard} keyboard
|
* @param {!Keyboard} keyboard
|
||||||
*/
|
*/
|
||||||
constructor(client, keyboard) {
|
constructor(client, keyboard) {
|
||||||
@ -268,7 +268,7 @@ class Mouse {
|
|||||||
|
|
||||||
class Touchscreen {
|
class Touchscreen {
|
||||||
/**
|
/**
|
||||||
* @param {Puppeteer.Session} client
|
* @param {Puppeteer.CDPSession} client
|
||||||
* @param {Keyboard} keyboard
|
* @param {Keyboard} keyboard
|
||||||
*/
|
*/
|
||||||
constructor(client, keyboard) {
|
constructor(client, keyboard) {
|
||||||
|
@ -19,7 +19,7 @@ const Multimap = require('./Multimap');
|
|||||||
|
|
||||||
class NetworkManager extends EventEmitter {
|
class NetworkManager extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {!Puppeteer.FrameManager} frameManager
|
* @param {!Puppeteer.FrameManager} frameManager
|
||||||
*/
|
*/
|
||||||
constructor(client, frameManager) {
|
constructor(client, frameManager) {
|
||||||
@ -281,7 +281,7 @@ class NetworkManager extends EventEmitter {
|
|||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {?string} requestId
|
* @param {?string} requestId
|
||||||
* @param {string} interceptionId
|
* @param {string} interceptionId
|
||||||
* @param {boolean} allowInterception
|
* @param {boolean} allowInterception
|
||||||
@ -479,7 +479,7 @@ helper.tracePublicAPI(Request);
|
|||||||
|
|
||||||
class Response {
|
class Response {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {!Request} request
|
* @param {!Request} request
|
||||||
* @param {number} status
|
* @param {number} status
|
||||||
* @param {!Object} headers
|
* @param {!Object} headers
|
||||||
|
27
lib/Page.js
27
lib/Page.js
@ -31,17 +31,18 @@ const writeFileAsync = helper.promisify(fs.writeFile);
|
|||||||
|
|
||||||
class Page extends EventEmitter {
|
class Page extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
|
* @param {!Puppeteer.Target} target
|
||||||
* @param {boolean} ignoreHTTPSErrors
|
* @param {boolean} ignoreHTTPSErrors
|
||||||
* @param {boolean} appMode
|
* @param {boolean} appMode
|
||||||
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue
|
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue
|
||||||
* @return {!Promise<!Page>}
|
* @return {!Promise<!Page>}
|
||||||
*/
|
*/
|
||||||
static async create(client, ignoreHTTPSErrors, appMode, screenshotTaskQueue) {
|
static async create(client, target, ignoreHTTPSErrors, appMode, screenshotTaskQueue) {
|
||||||
|
|
||||||
await client.send('Page.enable');
|
await client.send('Page.enable');
|
||||||
const {frameTree} = await client.send('Page.getFrameTree');
|
const {frameTree} = await client.send('Page.getFrameTree');
|
||||||
const page = new Page(client, frameTree, ignoreHTTPSErrors, screenshotTaskQueue);
|
const page = new Page(client, target, frameTree, ignoreHTTPSErrors, screenshotTaskQueue);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
client.send('Page.setLifecycleEventsEnabled', { enabled: true }),
|
client.send('Page.setLifecycleEventsEnabled', { enabled: true }),
|
||||||
@ -60,14 +61,16 @@ class Page extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
|
* @param {!Puppeteer.Target} target
|
||||||
* @param {{frame: Object, childFrames: ?Array}} frameTree
|
* @param {{frame: Object, childFrames: ?Array}} frameTree
|
||||||
* @param {boolean} ignoreHTTPSErrors
|
* @param {boolean} ignoreHTTPSErrors
|
||||||
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue
|
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue
|
||||||
*/
|
*/
|
||||||
constructor(client, frameTree, ignoreHTTPSErrors, screenshotTaskQueue) {
|
constructor(client, target, frameTree, ignoreHTTPSErrors, screenshotTaskQueue) {
|
||||||
super();
|
super();
|
||||||
this._client = client;
|
this._client = client;
|
||||||
|
this._target = target;
|
||||||
this._keyboard = new Keyboard(client);
|
this._keyboard = new Keyboard(client);
|
||||||
this._mouse = new Mouse(client, this._keyboard);
|
this._mouse = new Mouse(client, this._keyboard);
|
||||||
this._touchscreen = new Touchscreen(client, this._keyboard);
|
this._touchscreen = new Touchscreen(client, this._keyboard);
|
||||||
@ -101,6 +104,13 @@ class Page extends EventEmitter {
|
|||||||
client.on('Performance.metrics', event => this._emitMetrics(event));
|
client.on('Performance.metrics', event => this._emitMetrics(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {!Puppeteer.Target}
|
||||||
|
*/
|
||||||
|
target() {
|
||||||
|
return this._target;
|
||||||
|
}
|
||||||
|
|
||||||
_onTargetCrashed() {
|
_onTargetCrashed() {
|
||||||
this.emit('error', new Error('Page crashed!'));
|
this.emit('error', new Error('Page crashed!'));
|
||||||
}
|
}
|
||||||
@ -505,7 +515,7 @@ class Page extends EventEmitter {
|
|||||||
return request ? request.response() : null;
|
return request ? request.response() : null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {string} url
|
* @param {string} url
|
||||||
* @param {string} referrer
|
* @param {string} referrer
|
||||||
* @return {!Promise<?Error>}
|
* @return {!Promise<?Error>}
|
||||||
@ -691,7 +701,7 @@ class Page extends EventEmitter {
|
|||||||
* @return {!Promise<!Buffer>}
|
* @return {!Promise<!Buffer>}
|
||||||
*/
|
*/
|
||||||
async _screenshotTask(format, options) {
|
async _screenshotTask(format, options) {
|
||||||
await this._client.send('Target.activateTarget', {targetId: this._client.targetId()});
|
await this._client.send('Target.activateTarget', {targetId: this._target._targetId});
|
||||||
let clip = options.clip ? Object.assign({}, options['clip']) : undefined;
|
let clip = options.clip ? Object.assign({}, options['clip']) : undefined;
|
||||||
if (clip)
|
if (clip)
|
||||||
clip.scale = 1;
|
clip.scale = 1;
|
||||||
@ -785,7 +795,8 @@ class Page extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
await this._client.dispose();
|
console.assert(!!this._client._connection, 'Protocol error: Connection closed. Most likely the page has been closed.');
|
||||||
|
await this._client._connection.send('Target.closeTarget', {targetId: this._target._targetId});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,7 @@ const closeAsync = helper.promisify(fs.close);
|
|||||||
|
|
||||||
class Tracing {
|
class Tracing {
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
*/
|
*/
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
this._client = client;
|
this._client = client;
|
||||||
|
7
lib/externs.d.ts
vendored
7
lib/externs.d.ts
vendored
@ -1,5 +1,5 @@
|
|||||||
import { Connection as RealConnection, Session as RealSession } from './Connection.js';
|
import { Connection as RealConnection, CDPSession as RealCDPSession } from './Connection.js';
|
||||||
import {Browser as RealBrowser, TaskQueue as RealTaskQueue} from './Browser.js';
|
import {Browser as RealBrowser, TaskQueue as RealTaskQueue, Target as RealTarget} from './Browser.js';
|
||||||
import * as RealPage from './Page.js';
|
import * as RealPage from './Page.js';
|
||||||
import {Mouse as RealMouse, Keyboard as RealKeyboard, Touchscreen as RealTouchscreen} from './Input.js';
|
import {Mouse as RealMouse, Keyboard as RealKeyboard, Touchscreen as RealTouchscreen} from './Input.js';
|
||||||
import {Frame as RealFrame, FrameManager as RealFrameManager} from './FrameManager.js';
|
import {Frame as RealFrame, FrameManager as RealFrameManager} from './FrameManager.js';
|
||||||
@ -10,12 +10,13 @@ import * as child_process from 'child_process';
|
|||||||
export as namespace Puppeteer;
|
export as namespace Puppeteer;
|
||||||
|
|
||||||
export class Connection extends RealConnection {}
|
export class Connection extends RealConnection {}
|
||||||
export class Session extends RealSession {}
|
export class CDPSession extends RealCDPSession {}
|
||||||
export class Mouse extends RealMouse {}
|
export class Mouse extends RealMouse {}
|
||||||
export class Keyboard extends RealKeyboard {}
|
export class Keyboard extends RealKeyboard {}
|
||||||
export class Touchscreen extends RealTouchscreen {}
|
export class Touchscreen extends RealTouchscreen {}
|
||||||
export class TaskQueue extends RealTaskQueue {}
|
export class TaskQueue extends RealTaskQueue {}
|
||||||
export class Browser extends RealBrowser {}
|
export class Browser extends RealBrowser {}
|
||||||
|
export class Target extends RealTarget {}
|
||||||
export class Frame extends RealFrame {}
|
export class Frame extends RealFrame {}
|
||||||
export class FrameManager extends RealFrameManager {}
|
export class FrameManager extends RealFrameManager {}
|
||||||
export class NetworkManager extends RealNetworkManager {}
|
export class NetworkManager extends RealNetworkManager {}
|
||||||
|
@ -83,7 +83,7 @@ class Helper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {!Puppeteer.Session} client
|
* @param {!Puppeteer.CDPSession} client
|
||||||
* @param {!Object} remoteObject
|
* @param {!Object} remoteObject
|
||||||
*/
|
*/
|
||||||
static async releaseObject(client, remoteObject) {
|
static async releaseObject(client, remoteObject) {
|
||||||
|
56
test/test.js
56
test/test.js
@ -3474,6 +3474,56 @@ describe('Page', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Target.createCDPSession', function() {
|
||||||
|
it('should work', async function({page, server}) {
|
||||||
|
const client = await page.target().createCDPSession();
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
client.send('Runtime.enable'),
|
||||||
|
client.send('Runtime.evaluate', { expression: 'window.foo = "bar"' })
|
||||||
|
]);
|
||||||
|
const foo = await page.evaluate(() => window.foo);
|
||||||
|
expect(foo).toBe('bar');
|
||||||
|
});
|
||||||
|
it('should send events', async function({page, server}) {
|
||||||
|
const client = await page.target().createCDPSession();
|
||||||
|
await client.send('Network.enable');
|
||||||
|
const events = [];
|
||||||
|
client.on('Network.requestWillBeSent', event => events.push(event));
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
expect(events.length).toBe(1);
|
||||||
|
});
|
||||||
|
it('should enable and disable domains independently', async function({page, server}) {
|
||||||
|
const client = await page.target().createCDPSession();
|
||||||
|
await client.send('Runtime.enable');
|
||||||
|
await client.send('Debugger.enable');
|
||||||
|
// JS coverage enables and then disables Debugger domain.
|
||||||
|
await page.coverage.startJSCoverage();
|
||||||
|
await page.coverage.stopJSCoverage();
|
||||||
|
// generate a script in page and wait for the event.
|
||||||
|
const [event] = await Promise.all([
|
||||||
|
waitForEvents(client, 'Debugger.scriptParsed'),
|
||||||
|
page.evaluate('//# sourceURL=foo.js')
|
||||||
|
]);
|
||||||
|
// expect events to be dispatched.
|
||||||
|
expect(event.url).toBe('foo.js');
|
||||||
|
});
|
||||||
|
it('should be able to detach session', async function({page, server}) {
|
||||||
|
const client = await page.target().createCDPSession();
|
||||||
|
await client.send('Runtime.enable');
|
||||||
|
const evalResponse = await client.send('Runtime.evaluate', {expression: '1 + 2', returnByValue: true});
|
||||||
|
expect(evalResponse.result.value).toBe(3);
|
||||||
|
await client.detach();
|
||||||
|
let error = null;
|
||||||
|
try {
|
||||||
|
await client.send('Runtime.evaluate', {expression: '3 + 1', returnByValue: true});
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
expect(error.message).toContain('Session closed.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('JSCoverage', function() {
|
describe('JSCoverage', function() {
|
||||||
it('should work', async function({page, server}) {
|
it('should work', async function({page, server}) {
|
||||||
await page.coverage.startJSCoverage();
|
await page.coverage.startJSCoverage();
|
||||||
@ -3656,7 +3706,7 @@ runner.run();
|
|||||||
* @param {!EventEmitter} emitter
|
* @param {!EventEmitter} emitter
|
||||||
* @param {string} eventName
|
* @param {string} eventName
|
||||||
* @param {number=} eventCount
|
* @param {number=} eventCount
|
||||||
* @return {!Promise}
|
* @return {!Promise<!Object>}
|
||||||
*/
|
*/
|
||||||
function waitForEvents(emitter, eventName, eventCount = 1) {
|
function waitForEvents(emitter, eventName, eventCount = 1) {
|
||||||
let fulfill;
|
let fulfill;
|
||||||
@ -3664,12 +3714,12 @@ function waitForEvents(emitter, eventName, eventCount = 1) {
|
|||||||
emitter.on(eventName, onEvent);
|
emitter.on(eventName, onEvent);
|
||||||
return promise;
|
return promise;
|
||||||
|
|
||||||
function onEvent() {
|
function onEvent(event) {
|
||||||
--eventCount;
|
--eventCount;
|
||||||
if (eventCount)
|
if (eventCount)
|
||||||
return;
|
return;
|
||||||
emitter.removeListener(eventName, onEvent);
|
emitter.removeListener(eventName, onEvent);
|
||||||
fulfill();
|
fulfill(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@ const EXCLUDE_CLASSES = new Set([
|
|||||||
'Multimap',
|
'Multimap',
|
||||||
'NavigatorWatcher',
|
'NavigatorWatcher',
|
||||||
'NetworkManager',
|
'NetworkManager',
|
||||||
'Session',
|
|
||||||
'TaskQueue',
|
'TaskQueue',
|
||||||
'WaitTask',
|
'WaitTask',
|
||||||
]);
|
]);
|
||||||
|
Loading…
Reference in New Issue
Block a user