Skip to content

Commit

Permalink
Add support for sessionId to events too
Browse files Browse the repository at this point in the history
Allow to filter events by `sessionId`. There is one gotcha that when
using promises without filter, the `sessionId` is not returned due to
the limitation of promises to return only one value, and the fact that
changing the return type would be a breaking change.

Related to #441.
  • Loading branch information
cyrus-and committed Mar 15, 2021
1 parent 78f207c commit 88345ad
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 11 deletions.
27 changes: 21 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,8 @@ Emitted when the remote instance sends any notification through the WebSocket.

- `method`: a string describing the notification (e.g.,
`'Network.requestWillBeSent'`);
- `params`: an object containing the payload.
- `params`: an object containing the payload;
- `sessionId`: an optional string representing the session identifier.

Refer to the [Chrome Debugging Protocol] specification for more information.

Expand All @@ -706,14 +707,16 @@ client.on('event', (message) => {
#### Event: '`<domain>`.`<method>`'

```js
function (params) {}
function (params, sessionId) {}
```

Emitted when the remote instance sends a notification for `<domain>.<method>`
through the WebSocket.

`params` is an object containing the payload.

`sessionId` is an optional string representing the session identifier.

This is just a utility event which allows to easily listen for specific
notifications (see [`'event'`](#event-event)), for example:

Expand All @@ -727,6 +730,18 @@ Additionally, the equivalent `<domain>.on('<method>', ...)` syntax is available,
client.Network.on('requestWillBeSent', console.log);
```

#### Event: '`<domain>`.`<method>`.`<sessionId>`'

```js
function (params, sessionId) {}
```

Equivalent to the following but only for those events belonging to the given `session`:

```js
client.on('<domain>.<event>', callback);
```

#### Event: 'ready'

```js
Expand Down Expand Up @@ -819,16 +834,16 @@ For example:
client.Page.navigate({url: 'https://github.com'}, console.log);
```

#### client.`<domain>`.`<event>`([callback])
#### client.`<domain>`.`<event>`([sessionId], [callback])

Just a shorthand for:

```js
client.on('<domain>.<event>', callback);
client.on('<domain>.<event>[.<sessionId>]', callback);
```

When `callback` is omitted the event is registered only once and a `Promise`
object is returned.
object is returned. Notice though that in this case the optional `sessionId` usually passed to `callback` is not returned.

When `callback` is provided, it returns a function that can be used to
unsubscribe `callback` from the event, it can be useful when anonymous functions
Expand All @@ -837,7 +852,7 @@ are used as callbacks.
For example:

```js
const unsubscribe = client.Network.requestWillBeSent((params) => {
const unsubscribe = client.Network.requestWillBeSent((params, sessionId) => {
console.log(params.request.url);
});
unsubscribe();
Expand Down
13 changes: 9 additions & 4 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,18 @@ function addCommand(chrome, domainName, command) {

function addEvent(chrome, domainName, event) {
const eventName = `${domainName}.${event.name}`;
const handler = (handler) => {
const handler = (sessionId, handler) => {
if (typeof sessionId === 'function') {
handler = sessionId;
sessionId = undefined;
}
const rawEventName = sessionId ? `${eventName}.${sessionId}` : eventName;
if (typeof handler === 'function') {
chrome.on(eventName, handler);
return () => chrome.removeListener(eventName, handler);
chrome.on(rawEventName, handler);
return () => chrome.removeListener(rawEventName, handler);
} else {
return new Promise((fulfill, reject) => {
chrome.once(eventName, fulfill);
chrome.once(rawEventName, fulfill);
});
}
};
Expand Down
4 changes: 3 additions & 1 deletion lib/chrome.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,10 @@ class Chrome extends EventEmitter {
}
// event
else if (message.method) {
const {method, params, sessionId} = message;
this.emit('event', message);
this.emit(message.method, message.params);
this.emit(method, params, sessionId);
this.emit(`${method}.${sessionId}`, params, sessionId);
}
}

Expand Down
41 changes: 41 additions & 0 deletions test/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,45 @@ describe('registering event', () => {
});
});
});
describe('passing a sessionId', () => {
it('should only listen for those events', async () => {
// fetch and connect to the browser target
const version = await Chrome.Version();
const chrome = await Chrome({
target: version.webSocketDebuggerUrl
});
// create another target
await chrome.Target.createTarget({url: 'about:blank'});
// fetch the targets (two pages) and attach to each of them
const {targetInfos} = await chrome.Target.getTargets();
const {sessionId: sessionId0} = await chrome.Target.attachToTarget({
targetId: targetInfos[0].targetId,
flatten: true
});
const {sessionId: sessionId1} = await chrome.Target.attachToTarget({
targetId: targetInfos[1].targetId,
flatten: true
});
// enable the Page events in both of them
await chrome.Page.enable(sessionId0);
await chrome.Page.enable(sessionId1);
// trigger a reload in both of them
chrome.Page.reload(sessionId0);
chrome.Page.reload(sessionId1);
// awaits individual events
await Promise.all([
chrome.Page.loadEventFired(sessionId0),
chrome.Page.loadEventFired(sessionId1),
new Promise((fulfill, reject) => {
let counter = 0;
chrome.Page.loadEventFired((params) => {
if (++counter == 2) {
fulfill();
}
});
})
]);
return chrome.close();
});
});
});

0 comments on commit 88345ad

Please sign in to comment.