feat: expose other sessions from connection (#6863)
This commit is contained in:
parent
2605309f74
commit
cb285a2379
@ -357,6 +357,7 @@
|
|||||||
* [target.url()](#targeturl)
|
* [target.url()](#targeturl)
|
||||||
* [target.worker()](#targetworker)
|
* [target.worker()](#targetworker)
|
||||||
- [class: CDPSession](#class-cdpsession)
|
- [class: CDPSession](#class-cdpsession)
|
||||||
|
* [cdpSession.connection()](#cdpsessionconnection)
|
||||||
* [cdpSession.detach()](#cdpsessiondetach)
|
* [cdpSession.detach()](#cdpsessiondetach)
|
||||||
* [cdpSession.send(method[, ...paramArgs])](#cdpsessionsendmethod-paramargs)
|
* [cdpSession.send(method[, ...paramArgs])](#cdpsessionsendmethod-paramargs)
|
||||||
- [class: Coverage](#class-coverage)
|
- [class: Coverage](#class-coverage)
|
||||||
@ -4558,6 +4559,12 @@ await client.send('Animation.setPlaybackRate', {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### cdpSession.connection()
|
||||||
|
|
||||||
|
- returns: <[Connection]>
|
||||||
|
|
||||||
|
Returns the underlying connection associated with the session. Can be used to obtain other related sessions.
|
||||||
|
|
||||||
#### cdpSession.detach()
|
#### cdpSession.detach()
|
||||||
|
|
||||||
- returns: <[Promise]>
|
- returns: <[Promise]>
|
||||||
|
@ -125,11 +125,13 @@ export class Connection extends EventEmitter {
|
|||||||
sessionId
|
sessionId
|
||||||
);
|
);
|
||||||
this._sessions.set(sessionId, session);
|
this._sessions.set(sessionId, session);
|
||||||
|
this.emit('sessionattached', session);
|
||||||
} else if (object.method === 'Target.detachedFromTarget') {
|
} else if (object.method === 'Target.detachedFromTarget') {
|
||||||
const session = this._sessions.get(object.params.sessionId);
|
const session = this._sessions.get(object.params.sessionId);
|
||||||
if (session) {
|
if (session) {
|
||||||
session._onClosed();
|
session._onClosed();
|
||||||
this._sessions.delete(object.params.sessionId);
|
this._sessions.delete(object.params.sessionId);
|
||||||
|
this.emit('sessiondetached', session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object.sessionId) {
|
if (object.sessionId) {
|
||||||
@ -253,6 +255,10 @@ export class CDPSession extends EventEmitter {
|
|||||||
this._sessionId = sessionId;
|
this._sessionId = sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connection(): Connection {
|
||||||
|
return this._connection;
|
||||||
|
}
|
||||||
|
|
||||||
send<T extends keyof ProtocolMapping.Commands>(
|
send<T extends keyof ProtocolMapping.Commands>(
|
||||||
method: T,
|
method: T,
|
||||||
...paramArgs: ProtocolMapping.Commands[T]['paramsType']
|
...paramArgs: ProtocolMapping.Commands[T]['paramsType']
|
||||||
|
@ -488,8 +488,16 @@ export class Page extends EventEmitter {
|
|||||||
this._viewport = null;
|
this._viewport = null;
|
||||||
|
|
||||||
client.on('Target.attachedToTarget', (event) => {
|
client.on('Target.attachedToTarget', (event) => {
|
||||||
if (event.targetInfo.type !== 'worker') {
|
if (
|
||||||
|
event.targetInfo.type !== 'worker' &&
|
||||||
|
event.targetInfo.type !== 'iframe'
|
||||||
|
) {
|
||||||
// If we don't detach from service workers, they will never die.
|
// If we don't detach from service workers, they will never die.
|
||||||
|
// We still want to attach to workers for emitting events.
|
||||||
|
// We still want to attach to iframes so sessions may interact with them.
|
||||||
|
// We detach from all other types out of an abundance of caution.
|
||||||
|
// See https://source.chromium.org/chromium/chromium/src/+/master:content/browser/devtools/devtools_agent_host_impl.cc?q=f:devtools%20-f:out%20%22::kTypePage%5B%5D%22&ss=chromium
|
||||||
|
// for the complete list of available types.
|
||||||
client
|
client
|
||||||
.send('Target.detachFromTarget', {
|
.send('Target.detachFromTarget', {
|
||||||
sessionId: event.sessionId,
|
sessionId: event.sessionId,
|
||||||
|
@ -42,9 +42,10 @@ describeChromeOnly('headful tests', function () {
|
|||||||
let headfulOptions;
|
let headfulOptions;
|
||||||
let headlessOptions;
|
let headlessOptions;
|
||||||
let extensionOptions;
|
let extensionOptions;
|
||||||
|
let forcedOopifOptions;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const { defaultBrowserOptions } = getTestState();
|
const { server, defaultBrowserOptions } = getTestState();
|
||||||
headfulOptions = Object.assign({}, defaultBrowserOptions, {
|
headfulOptions = Object.assign({}, defaultBrowserOptions, {
|
||||||
headless: false,
|
headless: false,
|
||||||
});
|
});
|
||||||
@ -59,6 +60,18 @@ describeChromeOnly('headful tests', function () {
|
|||||||
`--load-extension=${extensionPath}`,
|
`--load-extension=${extensionPath}`,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
forcedOopifOptions = Object.assign({}, defaultBrowserOptions, {
|
||||||
|
headless: false,
|
||||||
|
devtools: true,
|
||||||
|
args: [
|
||||||
|
`--host-rules=MAP oopifdomain 127.0.0.1`,
|
||||||
|
`--isolate-origins=${server.PREFIX.replace(
|
||||||
|
'localhost',
|
||||||
|
'oopifdomain'
|
||||||
|
)}`,
|
||||||
|
],
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('HEADFUL', function () {
|
describe('HEADFUL', function () {
|
||||||
@ -147,6 +160,58 @@ describeChromeOnly('headful tests', function () {
|
|||||||
expect(urls).toEqual([server.EMPTY_PAGE, 'https://google.com/']);
|
expect(urls).toEqual([server.EMPTY_PAGE, 'https://google.com/']);
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
|
it('OOPIF: should expose events within OOPIFs', async () => {
|
||||||
|
const { server, puppeteer } = getTestState();
|
||||||
|
|
||||||
|
const browser = await puppeteer.launch(forcedOopifOptions);
|
||||||
|
const page = await browser.newPage();
|
||||||
|
|
||||||
|
// Setup our session listeners to observe OOPIF activity.
|
||||||
|
const session = await page.target().createCDPSession();
|
||||||
|
const networkEvents = [];
|
||||||
|
const otherSessions = [];
|
||||||
|
await session.send('Target.setAutoAttach', {
|
||||||
|
autoAttach: true,
|
||||||
|
flatten: true,
|
||||||
|
waitForDebuggerOnStart: true,
|
||||||
|
});
|
||||||
|
session.connection().on('sessionattached', async (session) => {
|
||||||
|
otherSessions.push(session);
|
||||||
|
|
||||||
|
session.on('Network.requestWillBeSent', (params) =>
|
||||||
|
networkEvents.push(params)
|
||||||
|
);
|
||||||
|
await session.send('Network.enable');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Navigate to the empty page and add an OOPIF iframe with at least one request.
|
||||||
|
await page.goto(server.EMPTY_PAGE);
|
||||||
|
await page.evaluate((frameUrl) => {
|
||||||
|
const frame = document.createElement('iframe');
|
||||||
|
frame.setAttribute('src', frameUrl);
|
||||||
|
document.body.appendChild(frame);
|
||||||
|
return new Promise((x, y) => {
|
||||||
|
frame.onload = x;
|
||||||
|
frame.onerror = y;
|
||||||
|
});
|
||||||
|
}, server.PREFIX.replace('localhost', 'oopifdomain') + '/one-style.html');
|
||||||
|
await page.waitForSelector('iframe');
|
||||||
|
|
||||||
|
// Ensure we found the iframe session.
|
||||||
|
expect(otherSessions).toHaveLength(1);
|
||||||
|
|
||||||
|
// Resume the iframe and trigger another request.
|
||||||
|
const iframeSession = otherSessions[0];
|
||||||
|
await iframeSession.send('Runtime.runIfWaitingForDebugger');
|
||||||
|
await iframeSession.send('Runtime.evaluate', {
|
||||||
|
expression: `fetch('/fetch')`,
|
||||||
|
awaitPromise: true,
|
||||||
|
});
|
||||||
|
await browser.close();
|
||||||
|
|
||||||
|
const requests = networkEvents.map((event) => event.request.url);
|
||||||
|
expect(requests).toContain(`http://oopifdomain:${server.PORT}/fetch`);
|
||||||
|
});
|
||||||
it('should close browser with beforeunload page', async () => {
|
it('should close browser with beforeunload page', async () => {
|
||||||
const { server, puppeteer } = getTestState();
|
const { server, puppeteer } = getTestState();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user