From 99658c2d32a6e1f6d1b7a0df1c7cef614ffa020b Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Tue, 21 Jul 2020 09:36:54 -0700 Subject: [PATCH] feat(bringToFront): enable on all browsers (#3052) --- browsers.json | 2 +- docs/api.md | 9 +++++++++ src/chromium/crPage.ts | 4 ++++ src/firefox/ffPage.ts | 4 ++++ src/firefox/protocol.ts | 5 +++++ src/page.ts | 5 +++++ src/rpc/channels.ts | 3 +++ src/rpc/client/page.ts | 6 ++++++ src/rpc/protocol.pdl | 2 ++ src/rpc/server/pageDispatcher.ts | 4 ++++ src/webkit/wkPage.ts | 6 ++++++ test/headful.jest.js | 18 ++++++++++++++++++ 12 files changed, 67 insertions(+), 1 deletion(-) diff --git a/browsers.json b/browsers.json index 2d9fc67c8bd74..4cef872285083 100644 --- a/browsers.json +++ b/browsers.json @@ -7,7 +7,7 @@ }, { "name": "firefox", - "revision": "1128" + "revision": "1134" }, { "name": "webkit", diff --git a/docs/api.md b/docs/api.md index f69cc7ba878b2..99095ae44029f 100644 --- a/docs/api.md +++ b/docs/api.md @@ -702,6 +702,7 @@ page.removeListener('request', logRequest); - [page.addInitScript(script[, arg])](#pageaddinitscriptscript-arg) - [page.addScriptTag(options)](#pageaddscripttagoptions) - [page.addStyleTag(options)](#pageaddstyletagoptions) +- [page.bringToFront()](#pagebringtofront) - [page.check(selector, [options])](#pagecheckselector-options) - [page.click(selector[, options])](#pageclickselector-options) - [page.close([options])](#pagecloseoptions) @@ -1007,6 +1008,14 @@ Adds a `` tag into the page with the desired url or a ` + +Brings page to front (activates tab). + + #### page.check(selector, [options]) - `selector` <[string]> A selector to search for checkbox or radio button to check. If there are multiple elements satisfying the selector, the first will be checked. See [working with selectors](#working-with-selectors) for more details. - `options` <[Object]> diff --git a/src/chromium/crPage.ts b/src/chromium/crPage.ts index d9b5084142dd6..96eb89583128d 100644 --- a/src/chromium/crPage.ts +++ b/src/chromium/crPage.ts @@ -143,6 +143,10 @@ export class CRPage implements PageDelegate { await this._mainFrameSession._updateViewport(); } + async bringToFront(): Promise { + await this._mainFrameSession._client.send('Page.bringToFront'); + } + async updateEmulateMedia(): Promise { await this._forAllFrameSessions(frame => frame._updateEmulateMedia()); } diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index 444a655fc4031..4855609745fc2 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -286,6 +286,10 @@ export class FFPage implements PageDelegate { }); } + async bringToFront(): Promise { + await this._session.send('Page.bringToFront', {}); + } + async updateEmulateMedia(): Promise { const colorScheme = this._page._state.colorScheme || this._browserContext._options.colorScheme || 'light'; await this._session.send('Page.setEmulatedMedia', { diff --git a/src/firefox/protocol.ts b/src/firefox/protocol.ts index 60af6f935d5e9..6b8a88a3545b9 100644 --- a/src/firefox/protocol.ts +++ b/src/firefox/protocol.ts @@ -409,6 +409,9 @@ export module Protocol { }|null; }; export type setViewportSizeReturnValue = void; + export type bringToFrontParameters = { + }; + export type bringToFrontReturnValue = void; export type setEmulatedMediaParameters = { type?: ("screen"|"print"|""); colorScheme?: ("dark"|"light"|"no-preference"); @@ -963,6 +966,7 @@ export module Protocol { "Page.setFileInputFiles": Page.setFileInputFilesParameters; "Page.addBinding": Page.addBindingParameters; "Page.setViewportSize": Page.setViewportSizeParameters; + "Page.bringToFront": Page.bringToFrontParameters; "Page.setEmulatedMedia": Page.setEmulatedMediaParameters; "Page.setCacheDisabled": Page.setCacheDisabledParameters; "Page.describeNode": Page.describeNodeParameters; @@ -1033,6 +1037,7 @@ export module Protocol { "Page.setFileInputFiles": Page.setFileInputFilesReturnValue; "Page.addBinding": Page.addBindingReturnValue; "Page.setViewportSize": Page.setViewportSizeReturnValue; + "Page.bringToFront": Page.bringToFrontReturnValue; "Page.setEmulatedMedia": Page.setEmulatedMediaReturnValue; "Page.setCacheDisabled": Page.setCacheDisabledReturnValue; "Page.describeNode": Page.describeNodeReturnValue; diff --git a/src/page.ts b/src/page.ts index aa476a76dbf33..803c2a44eef87 100644 --- a/src/page.ts +++ b/src/page.ts @@ -53,6 +53,7 @@ export interface PageDelegate { updateEmulateMedia(): Promise; updateRequestInterception(): Promise; setFileChooserIntercepted(enabled: boolean): Promise; + bringToFront(): Promise; canScreenshotOutsideViewport(): boolean; resetViewport(): Promise; // Only called if canScreenshotOutsideViewport() returns false. @@ -403,6 +404,10 @@ export class Page extends EventEmitter { return this._state.viewportSize; } + async bringToFront(): Promise { + await this._delegate.bringToFront(); + } + async evaluate(pageFunction: js.Func1, arg: Arg): Promise; async evaluate(pageFunction: js.Func1, arg?: any): Promise; async evaluate(pageFunction: js.Func1, arg: Arg): Promise { diff --git a/src/rpc/channels.ts b/src/rpc/channels.ts index 1e3054deb93ac..46f522777af4a 100644 --- a/src/rpc/channels.ts +++ b/src/rpc/channels.ts @@ -544,6 +544,7 @@ export interface PageChannel extends Channel { crStopJSCoverage(params?: PageCrStopJSCoverageParams): Promise; crStartCSSCoverage(params: PageCrStartCSSCoverageParams): Promise; crStopCSSCoverage(params?: PageCrStopCSSCoverageParams): Promise; + bringToFront(params?: PageBringToFrontParams): Promise; } export type PageBindingCallEvent = { binding: BindingCallChannel, @@ -798,6 +799,8 @@ export type PageCrStopCSSCoverageResult = { }[], }[], }; +export type PageBringToFrontParams = {}; +export type PageBringToFrontResult = void; // ----------- Frame ----------- export type FrameInitializer = { diff --git a/src/rpc/client/page.ts b/src/rpc/client/page.ts index 4ac3ac35e1235..dce4f1983ff87 100644 --- a/src/rpc/client/page.ts +++ b/src/rpc/client/page.ts @@ -414,6 +414,12 @@ export class Page extends ChannelOwner { return this._attributeToPage(() => this._mainFrame.title()); } + async bringToFront(): Promise { + return this._wrapApiCall('page.bringToFront', async () => { + await this._channel.bringToFront(); + }); + } + async close(options: { runBeforeUnload?: boolean } = {runBeforeUnload: undefined}) { return this._wrapApiCall('page.close', async () => { await this._channel.close(options); diff --git a/src/rpc/protocol.pdl b/src/rpc/protocol.pdl index 665c858de1da9..b2bdb403ebd5a 100644 --- a/src/rpc/protocol.pdl +++ b/src/rpc/protocol.pdl @@ -718,6 +718,8 @@ interface Page start: number end: number + command bringToFront + interface Frame initializer url: string diff --git a/src/rpc/server/pageDispatcher.ts b/src/rpc/server/pageDispatcher.ts index a0f68f59b538c..50a9e398bf097 100644 --- a/src/rpc/server/pageDispatcher.ts +++ b/src/rpc/server/pageDispatcher.ts @@ -195,6 +195,10 @@ export class PageDispatcher extends Dispatcher implements return { pdf: buffer.toString('base64') }; } + async bringToFront(): Promise { + await this._page.bringToFront(); + } + async crStartJSCoverage(params: types.JSCoverageOptions): Promise { const coverage = this._page.coverage as CRCoverage; await coverage.startJSCoverage(params); diff --git a/src/webkit/wkPage.ts b/src/webkit/wkPage.ts index 6726195831ec4..0e20f19f6eec5 100644 --- a/src/webkit/wkPage.ts +++ b/src/webkit/wkPage.ts @@ -576,6 +576,12 @@ export class WKPage implements PageDelegate { await this._updateViewport(); } + async bringToFront(): Promise { + this._pageProxySession.send('Target.activate', { + targetId: this._session.sessionId + }); + } + async _updateViewport(): Promise { const options = this._browserContext._options; const viewportSize = this._page._state.viewportSize; diff --git a/test/headful.jest.js b/test/headful.jest.js index 1612139587a3a..0f0c8631745e4 100644 --- a/test/headful.jest.js +++ b/test/headful.jest.js @@ -143,4 +143,22 @@ describe('Headful', function() { await context.close(); await browser.close(); }); + it('Page.bringToFront should work', async ({browserType, defaultBrowserOptions}) => { + const browser = await browserType.launch({...defaultBrowserOptions, headless: false }); + const page1 = await browser.newPage(); + await page1.setContent('Page1') + const page2 = await browser.newPage(); + await page2.setContent('Page2') + + await page1.bringToFront(); + expect(await page1.evaluate('document.visibilityState')).toBe('visible'); + expect(await page2.evaluate('document.visibilityState')).toBe('visible'); + + await page2.bringToFront(); + expect(await page1.evaluate('document.visibilityState')).toBe('visible'); + expect(await page2.evaluate('document.visibilityState')).toBe( + 'visible' + ); + await browser.close(); + }); });