feat(browser): add browser.disconnected event (#960)

This patch adds a 'disconnected' event for the browser. The event is issued
when the "browser" loses connection to the chrome process.

References #952
This commit is contained in:
Adi Prasetyo 2017-11-04 08:46:17 +07:00 committed by Andrey Lushnikov
parent 88ba52a363
commit 03fefb53f8
4 changed files with 47 additions and 1 deletions

View File

@ -13,6 +13,7 @@
* [puppeteer.executablePath()](#puppeteerexecutablepath)
* [puppeteer.launch([options])](#puppeteerlaunchoptions)
- [class: Browser](#class-browser)
* [event: 'disconnected'](#event-disconnected)
* [event: 'targetchanged'](#event-targetchanged)
* [event: 'targetcreated'](#event-targetcreated)
* [event: 'targetdestroyed'](#event-targetdestroyed)
@ -291,6 +292,10 @@ puppeteer.launch().then(async browser => {
await browser2.close();
});
```
#### event: 'disconnected'
Emitted when puppeteer gets disconnected from the browser instance. This might happen because one of the following:
- browser closed or crashed
- `browser.disconnect` method was called
#### event: 'targetchanged'
- <[Target]>

View File

@ -33,6 +33,9 @@ class Browser extends EventEmitter {
this._closeCallback = closeCallback || new Function();
/** @type {Map<string, Target>} */
this._targets = new Map();
this._connection.setClosedCallback(() => {
this.emit(Browser.Events.Disconnected);
});
this._connection.on('Target.targetCreated', this._targetCreated.bind(this));
this._connection.on('Target.targetDestroyed', this._targetDestroyed.bind(this));
this._connection.on('Target.targetInfoChanged', this._targetInfoChanged.bind(this));
@ -136,7 +139,8 @@ class Browser extends EventEmitter {
Browser.Events = {
TargetCreated: 'targetcreated',
TargetDestroyed: 'targetdestroyed',
TargetChanged: 'targetchanged'
TargetChanged: 'targetchanged',
Disconnected: 'disconnected'
};
helper.tracePublicAPI(Browser);

View File

@ -75,6 +75,13 @@ class Connection extends EventEmitter {
});
}
/**
* @param {function()} callback
*/
setClosedCallback(callback) {
this._closeCallback = callback;
}
/**
* @param {string} message
*/
@ -108,6 +115,10 @@ class Connection extends EventEmitter {
}
_onClose() {
if (this._closeCallback) {
this._closeCallback();
this._closeCallback = null;
}
this._ws.removeAllListeners();
for (const callback of this._callbacks.values())
callback.reject(new Error(`Protocol error (${callback.method}): Target closed.`));

View File

@ -255,6 +255,32 @@ describe('Page', function() {
}));
});
describe('Browser.Events.disconnected', function() {
it('should emitted when: browser gets closed, disconnected or underlying websocket gets closed', SX(async function() {
const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
const browserWSEndpoint = originalBrowser.wsEndpoint();
const remoteBrowser1 = await puppeteer.connect({browserWSEndpoint});
const remoteBrowser2 = await puppeteer.connect({browserWSEndpoint});
let disconnectedOriginal = 0;
let disconnectedRemote1 = 0;
let disconnectedRemote2 = 0;
originalBrowser.on('disconnected', () => ++disconnectedOriginal);
remoteBrowser1.on('disconnected', () => ++disconnectedRemote1);
remoteBrowser2.on('disconnected', () => ++disconnectedRemote2);
await remoteBrowser2.disconnect();
expect(disconnectedOriginal).toBe(0);
expect(disconnectedRemote1).toBe(0);
expect(disconnectedRemote2).toBe(1);
await originalBrowser.close();
expect(disconnectedOriginal).toBe(1);
expect(disconnectedRemote1).toBe(1);
expect(disconnectedRemote2).toBe(1);
}));
});
describe('Page.close', function() {
it('should reject all promises when page is closed', SX(async function() {
const newPage = await browser.newPage();