Skip to content

Commit

Permalink
fix: ignore frames removed by PDF viewer
Browse files Browse the repository at this point in the history
PDF viewer in Chrome replaces the inner iframes
with an extension web view. The iframes are still
observable in Puppeteer up until the point when
they get replaces. In this case, Chrome sends
the frameDetached event with the reason swap.

Unlike the regular swap where a frame is replace with
an OOPIF or vice versa, with PDF viewer the frame is
just gone. This PR works around this issue by
ignoring any frames that are being swapped.
  • Loading branch information
OrKoN committed Apr 30, 2024
1 parent bed9a76 commit f715ed5
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 3 deletions.
12 changes: 12 additions & 0 deletions packages/puppeteer-core/src/cdp/Frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import type {CdpPage} from './Page.js';
export class CdpFrame extends Frame {
#url = '';
#detached = false;
#isBeingSwapped = false;
#client!: CDPSession;
worlds!: IsolatedWorldChart;

Expand Down Expand Up @@ -86,6 +87,7 @@ export class CdpFrame extends Frame {
}

updateClient(client: CDPSession, keepWorlds = false): void {
this.#isBeingSwapped = false;
this.#client = client;
if (!keepWorlds) {
// Clear the current contexts on previous world instances.
Expand Down Expand Up @@ -320,6 +322,7 @@ export class CdpFrame extends Frame {
_navigated(framePayload: Protocol.Page.Frame): void {
this._name = framePayload.name;
this.#url = `${framePayload.url}${framePayload.urlFragment || ''}`;
this.#isBeingSwapped = false;
}

_navigatedWithinDocument(url: string): void {
Expand Down Expand Up @@ -359,4 +362,13 @@ export class CdpFrame extends Frame {
exposeFunction(): never {
throw new UnsupportedOperation();
}

onFrameSwap(): void {
this.#isBeingSwapped = true;
this.emit(FrameEvent.FrameSwapped, undefined);
}

get isBeingSwapped(): boolean {
return this.#isBeingSwapped;
}
}
6 changes: 4 additions & 2 deletions packages/puppeteer-core/src/cdp/FrameManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,9 @@ export class FrameManager extends EventEmitter<FrameManagerEvents> {
}

frames(): CdpFrame[] {
return Array.from(this._frameTree.frames());
return Array.from(this._frameTree.frames()).filter(frame => {
return !frame.isBeingSwapped;
});
}

frame(frameId: string): CdpFrame | null {
Expand Down Expand Up @@ -463,7 +465,7 @@ export class FrameManager extends EventEmitter<FrameManagerEvents> {
break;
case 'swap':
this.emit(FrameManagerEvent.FrameSwapped, frame);
frame.emit(FrameEvent.FrameSwapped, undefined);
frame.onFrameSwap();
break;
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/puppeteer-core/src/cdp/LifecycleWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ export class LifecycleWatcher {
for (const child of frame.childFrames()) {
if (
child._hasStartedLoading &&
!child.isBeingSwapped &&
!checkLifecycle(child, expectedLifecycle)
) {
return false;
Expand Down
7 changes: 7 additions & 0 deletions test/TestExpectations.json
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,13 @@
"expectations": ["SKIP"],
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
},
{
"testIdPattern": "[oopif.spec] OOPIF should load a page with a PDF viewer",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome-headless-shell"],
"expectations": ["FAIL"],
"comment": "chrome-headless-shell does not have a PDF viewer"
},
{
"testIdPattern": "[page.spec] Page Page.addScriptTag should throw when added with content to the CSP page",
"platforms": ["darwin", "linux", "win32"],
Expand Down
3 changes: 3 additions & 0 deletions test/assets/pdf-viewer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<!DOCTYPE html>

<iframe src="sample.pdf"></iframe>
Binary file added test/assets/sample.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion test/src/cdp/TargetManager.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('TargetManager', () => {
expect(targetManager.getAvailableTargets().size).toBe(5);
expect(page.frames()).toHaveLength(2);

// // attach a remote frame iframe.
// attach a remote frame iframe.
framePromise = page.waitForFrame(frame => {
return frame.url() === server.CROSS_PROCESS_PREFIX + '/empty.html';
});
Expand Down
18 changes: 18 additions & 0 deletions test/src/oopif.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,24 @@ describe('OOPIF', function () {
).toEqual([true, true, false]);
});

it('should load a page with a PDF viewer', async () => {
const {page, server} = state;

await page.goto(server.PREFIX + '/pdf-viewer.html', {
waitUntil: 'networkidle2',
});

expect(
await Promise.all(
page.frames().map(async frame => {
return await frame.evaluate(() => {
return window.location.pathname;
});
})
)
).toEqual(['/pdf-viewer.html', '/sample.pdf']);
});

describe('waitForFrame', () => {
it('should resolve immediately if the frame already exists', async () => {
const {server, page} = state;
Expand Down

0 comments on commit f715ed5

Please sign in to comment.