mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 05:37:20 +03:00
fix: filechooser interception in OOPIFs (#14432)
This commit is contained in:
parent
962d933c78
commit
abced7223c
@ -219,8 +219,8 @@ export class CRPage implements PageDelegate {
|
|||||||
await this._forAllFrameSessions(frame => frame._updateRequestInterception());
|
await this._forAllFrameSessions(frame => frame._updateRequestInterception());
|
||||||
}
|
}
|
||||||
|
|
||||||
async setFileChooserIntercepted(enabled: boolean) {
|
async updateFileChooserInterception() {
|
||||||
await this._forAllFrameSessions(frame => frame.setFileChooserIntercepted(enabled));
|
await this._forAllFrameSessions(frame => frame._updateFileChooserInterception(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
async reload(): Promise<void> {
|
async reload(): Promise<void> {
|
||||||
@ -559,6 +559,7 @@ class FrameSession {
|
|||||||
promises.push(this._updateOffline(true));
|
promises.push(this._updateOffline(true));
|
||||||
promises.push(this._updateHttpCredentials(true));
|
promises.push(this._updateHttpCredentials(true));
|
||||||
promises.push(this._updateEmulateMedia(true));
|
promises.push(this._updateEmulateMedia(true));
|
||||||
|
promises.push(this._updateFileChooserInterception(true));
|
||||||
for (const binding of this._crPage._page.allBindings())
|
for (const binding of this._crPage._page.allBindings())
|
||||||
promises.push(this._initBinding(binding));
|
promises.push(this._initBinding(binding));
|
||||||
for (const source of this._crPage._browserContext.initScripts)
|
for (const source of this._crPage._browserContext.initScripts)
|
||||||
@ -1082,7 +1083,10 @@ class FrameSession {
|
|||||||
await this._networkManager.setRequestInterception(this._page._needsRequestInterception());
|
await this._networkManager.setRequestInterception(this._page._needsRequestInterception());
|
||||||
}
|
}
|
||||||
|
|
||||||
async setFileChooserIntercepted(enabled: boolean) {
|
async _updateFileChooserInterception(initial: boolean) {
|
||||||
|
const enabled = this._page._state.interceptFileChooser;
|
||||||
|
if (initial && !enabled)
|
||||||
|
return;
|
||||||
await this._client.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
await this._client.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ export class FFPage implements PageDelegate {
|
|||||||
await this._networkManager.setRequestInterception(this._page._needsRequestInterception());
|
await this._networkManager.setRequestInterception(this._page._needsRequestInterception());
|
||||||
}
|
}
|
||||||
|
|
||||||
async setFileChooserIntercepted(enabled: boolean) {
|
async updateFileChooserInterception(enabled: boolean) {
|
||||||
await this._session.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
await this._session.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ export interface PageDelegate {
|
|||||||
setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void>;
|
setEmulatedSize(emulatedSize: types.EmulatedSize): Promise<void>;
|
||||||
updateEmulateMedia(): Promise<void>;
|
updateEmulateMedia(): Promise<void>;
|
||||||
updateRequestInterception(): Promise<void>;
|
updateRequestInterception(): Promise<void>;
|
||||||
setFileChooserIntercepted(enabled: boolean): Promise<void>;
|
updateFileChooserInterception(enabled: boolean): Promise<void>;
|
||||||
bringToFront(): Promise<void>;
|
bringToFront(): Promise<void>;
|
||||||
|
|
||||||
setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void>;
|
setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void>;
|
||||||
@ -104,6 +104,7 @@ type PageState = {
|
|||||||
reducedMotion: types.ReducedMotion | null;
|
reducedMotion: types.ReducedMotion | null;
|
||||||
forcedColors: types.ForcedColors | null;
|
forcedColors: types.ForcedColors | null;
|
||||||
extraHTTPHeaders: types.HeadersArray | null;
|
extraHTTPHeaders: types.HeadersArray | null;
|
||||||
|
interceptFileChooser: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ExpectScreenshotOptions = {
|
type ExpectScreenshotOptions = {
|
||||||
@ -183,6 +184,7 @@ export class Page extends SdkObject {
|
|||||||
reducedMotion: browserContext._options.reducedMotion !== undefined ? browserContext._options.reducedMotion : 'no-preference',
|
reducedMotion: browserContext._options.reducedMotion !== undefined ? browserContext._options.reducedMotion : 'no-preference',
|
||||||
forcedColors: browserContext._options.forcedColors !== undefined ? browserContext._options.forcedColors : 'none',
|
forcedColors: browserContext._options.forcedColors !== undefined ? browserContext._options.forcedColors : 'none',
|
||||||
extraHTTPHeaders: null,
|
extraHTTPHeaders: null,
|
||||||
|
interceptFileChooser: false,
|
||||||
};
|
};
|
||||||
this.accessibility = new accessibility.Accessibility(delegate.getAccessibilityTree.bind(delegate));
|
this.accessibility = new accessibility.Accessibility(delegate.getAccessibilityTree.bind(delegate));
|
||||||
this.keyboard = new input.Keyboard(delegate.rawKeyboard, this);
|
this.keyboard = new input.Keyboard(delegate.rawKeyboard, this);
|
||||||
@ -620,7 +622,8 @@ export class Page extends SdkObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async setFileChooserIntercepted(enabled: boolean): Promise<void> {
|
async setFileChooserIntercepted(enabled: boolean): Promise<void> {
|
||||||
await this._delegate.setFileChooserIntercepted(enabled);
|
this._state.interceptFileChooser = enabled;
|
||||||
|
await this._delegate.updateFileChooserInterception(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
frameNavigatedToNewDocument(frame: frames.Frame) {
|
frameNavigatedToNewDocument(frame: frames.Frame) {
|
||||||
|
@ -77,7 +77,6 @@ export class WKPage implements PageDelegate {
|
|||||||
private _nextWindowOpenPopupFeatures?: string[];
|
private _nextWindowOpenPopupFeatures?: string[];
|
||||||
private _recordingVideoFile: string | null = null;
|
private _recordingVideoFile: string | null = null;
|
||||||
private _screencastGeneration: number = 0;
|
private _screencastGeneration: number = 0;
|
||||||
private _interceptingFileChooser = false;
|
|
||||||
|
|
||||||
constructor(browserContext: WKBrowserContext, pageProxySession: WKSession, opener: WKPage | null) {
|
constructor(browserContext: WKBrowserContext, pageProxySession: WKSession, opener: WKPage | null) {
|
||||||
this._pageProxySession = pageProxySession;
|
this._pageProxySession = pageProxySession;
|
||||||
@ -218,7 +217,7 @@ export class WKPage implements PageDelegate {
|
|||||||
promises.push(session.send('Page.setTimeZone', { timeZone: contextOptions.timezoneId }).
|
promises.push(session.send('Page.setTimeZone', { timeZone: contextOptions.timezoneId }).
|
||||||
catch(e => { throw new Error(`Invalid timezone ID: ${contextOptions.timezoneId}`); }));
|
catch(e => { throw new Error(`Invalid timezone ID: ${contextOptions.timezoneId}`); }));
|
||||||
}
|
}
|
||||||
if (this._interceptingFileChooser)
|
if (this._page._state.interceptFileChooser)
|
||||||
promises.push(session.send('Page.setInterceptFileChooserDialog', { enabled: true }));
|
promises.push(session.send('Page.setInterceptFileChooserDialog', { enabled: true }));
|
||||||
promises.push(session.send('Page.overrideSetting', { setting: 'DeviceOrientationEventEnabled' as any, value: contextOptions.isMobile }));
|
promises.push(session.send('Page.overrideSetting', { setting: 'DeviceOrientationEventEnabled' as any, value: contextOptions.isMobile }));
|
||||||
promises.push(session.send('Page.overrideSetting', { setting: 'FullScreenEnabled' as any, value: !contextOptions.isMobile }));
|
promises.push(session.send('Page.overrideSetting', { setting: 'FullScreenEnabled' as any, value: !contextOptions.isMobile }));
|
||||||
@ -725,8 +724,8 @@ export class WKPage implements PageDelegate {
|
|||||||
await this._pageProxySession.send('Emulation.setAuthCredentials', { username: credentials.username, password: credentials.password });
|
await this._pageProxySession.send('Emulation.setAuthCredentials', { username: credentials.username, password: credentials.password });
|
||||||
}
|
}
|
||||||
|
|
||||||
async setFileChooserIntercepted(enabled: boolean) {
|
async updateFileChooserInterception() {
|
||||||
this._interceptingFileChooser = enabled;
|
const enabled = this._page._state.interceptFileChooser;
|
||||||
await this._session.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
await this._session.send('Page.setInterceptFileChooserDialog', { enabled }).catch(e => {}); // target can be closed.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,6 +311,21 @@ it('should allow cdp sessions on oopifs', async function({ page, browser, server
|
|||||||
expect(JSON.stringify(oopif)).toContain('./digits/1.png');
|
expect(JSON.stringify(oopif)).toContain('./digits/1.png');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emit filechooser event for iframe', async ({ page, server, browser }) => {
|
||||||
|
// Add listener before OOPIF is created.
|
||||||
|
const chooserPromise = page.waitForEvent('filechooser');
|
||||||
|
await page.goto(server.PREFIX + '/dynamic-oopif.html');
|
||||||
|
expect(await countOOPIFs(browser)).toBe(1);
|
||||||
|
expect(page.frames().length).toBe(2);
|
||||||
|
const frame = page.frames()[1];
|
||||||
|
await frame.setContent(`<input type=file>`);
|
||||||
|
const [chooser] = await Promise.all([
|
||||||
|
chooserPromise,
|
||||||
|
frame.click('input'),
|
||||||
|
]);
|
||||||
|
expect(chooser).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
async function countOOPIFs(browser) {
|
async function countOOPIFs(browser) {
|
||||||
const browserSession = await browser.newBrowserCDPSession();
|
const browserSession = await browser.newBrowserCDPSession();
|
||||||
const oopifs = [];
|
const oopifs = [];
|
||||||
|
@ -517,3 +517,17 @@ it('should emit event after navigation', async ({ page, server, browserName, bro
|
|||||||
]);
|
]);
|
||||||
expect(logs).toEqual(['filechooser', 'filechooser']);
|
expect(logs).toEqual(['filechooser', 'filechooser']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should trigger listener added before navigation', async ({ page, server }) => {
|
||||||
|
// Add listener before cross process navigation.
|
||||||
|
const chooserPromise = new Promise(f => page.once('filechooser', f));
|
||||||
|
await page.goto(server.PREFIX + '/empty.html');
|
||||||
|
await page.goto(server.CROSS_PROCESS_PREFIX + '/empty.html');
|
||||||
|
await page.setContent(`<input type=file>`);
|
||||||
|
const [chooser] = await Promise.all([
|
||||||
|
chooserPromise,
|
||||||
|
page.click('input'),
|
||||||
|
]);
|
||||||
|
expect(chooser).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user