From 76ab83f581a35548b715ac6aa444b9297e6e177e Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Mon, 2 Dec 2019 10:53:23 -0800 Subject: [PATCH] chore: reuse Dialog between browsers (#115) --- src/chromium/Page.ts | 21 +++----- src/chromium/api.ts | 2 +- src/{chromium/Dialog.ts => dialog.ts} | 31 +++++------- src/firefox/Dialog.ts | 51 ------------------- src/firefox/Page.ts | 10 +++- src/firefox/api.ts | 2 +- src/webkit/Dialog.ts | 70 --------------------------- src/webkit/Page.ts | 21 +++----- src/webkit/api.ts | 2 +- 9 files changed, 38 insertions(+), 172 deletions(-) rename src/{chromium/Dialog.ts => dialog.ts} (68%) delete mode 100644 src/firefox/Dialog.ts delete mode 100644 src/webkit/Dialog.ts diff --git a/src/chromium/Page.ts b/src/chromium/Page.ts index 3dd1545e7c..addc749843 100644 --- a/src/chromium/Page.ts +++ b/src/chromium/Page.ts @@ -24,7 +24,6 @@ import { TimeoutSettings } from '../TimeoutSettings'; import { Browser } from './Browser'; import { BrowserContext } from './BrowserContext'; import { CDPSession, CDPSessionEvents } from './Connection'; -import { Dialog, DialogType } from './Dialog'; import { EmulationManager } from './EmulationManager'; import { Events } from './events'; import { Accessibility } from './features/accessibility'; @@ -47,6 +46,7 @@ import * as dom from '../dom'; import * as frames from '../frames'; import * as js from '../javascript'; import * as network from '../network'; +import * as dialog from '../dialog'; import { DOMWorldDelegate } from './JSHandle'; const writeFileAsync = helper.promisify(fs.writeFile); @@ -379,18 +379,13 @@ export class Page extends EventEmitter { } _onDialog(event : Protocol.Page.javascriptDialogOpeningPayload) { - let dialogType = null; - if (event.type === 'alert') - dialogType = DialogType.Alert; - else if (event.type === 'confirm') - dialogType = DialogType.Confirm; - else if (event.type === 'prompt') - dialogType = DialogType.Prompt; - else if (event.type === 'beforeunload') - dialogType = DialogType.BeforeUnload; - assert(dialogType, 'Unknown javascript dialog type: ' + event.type); - const dialog = new Dialog(this._client, dialogType, event.message, event.defaultPrompt); - this.emit(Events.Page.Dialog, dialog); + this.emit(Events.Page.Dialog, new dialog.Dialog( + event.type as dialog.DialogType, + event.message, + async (accept: boolean, promptText?: string) => { + await this._client.send('Page.handleJavaScriptDialog', { accept, promptText }); + }, + event.defaultPrompt)); } url(): string { diff --git a/src/chromium/api.ts b/src/chromium/api.ts index c649754f0c..ed5ede0afd 100644 --- a/src/chromium/api.ts +++ b/src/chromium/api.ts @@ -7,7 +7,7 @@ export { BrowserContext } from './BrowserContext'; export { BrowserFetcher } from './BrowserFetcher'; export { Chromium } from './features/chromium'; export { CDPSession } from './Connection'; -export { Dialog } from './Dialog'; +export { Dialog } from '../dialog'; export { ExecutionContext, JSHandle } from '../javascript'; export { ElementHandle } from '../dom'; export { Accessibility } from './features/accessibility'; diff --git a/src/chromium/Dialog.ts b/src/dialog.ts similarity index 68% rename from src/chromium/Dialog.ts rename to src/dialog.ts index 722385a506..c439b987bd 100644 --- a/src/chromium/Dialog.ts +++ b/src/dialog.ts @@ -15,21 +15,24 @@ * limitations under the License. */ -import { CDPSession } from './Connection'; -import { assert } from '../helper'; +import { assert } from './helper'; + +type OnHandle = (accept: boolean, promptText?: string) => Promise; + +export type DialogType = 'alert' | 'beforeunload' | 'confirm' | 'prompt'; export class Dialog { - private _client: CDPSession; private _type: string; private _message: string; + private _onHandle: OnHandle; private _handled = false; private _defaultValue: string; - constructor(client: CDPSession, type: string, message: string, defaultValue: (string | undefined) = '') { - this._client = client; + constructor(type: string, message: string, onHandle: OnHandle, defaultValue?: string) { this._type = type; this._message = message; - this._defaultValue = defaultValue; + this._onHandle = onHandle; + this._defaultValue = defaultValue || ''; } type(): string { @@ -47,24 +50,12 @@ export class Dialog { async accept(promptText: string | undefined) { assert(!this._handled, 'Cannot accept dialog which is already handled!'); this._handled = true; - await this._client.send('Page.handleJavaScriptDialog', { - accept: true, - promptText: promptText - }); + await this._onHandle(true, promptText); } async dismiss() { assert(!this._handled, 'Cannot dismiss dialog which is already handled!'); this._handled = true; - await this._client.send('Page.handleJavaScriptDialog', { - accept: false - }); + await this._onHandle(false); } } - -export const DialogType = { - Alert: 'alert', - BeforeUnload: 'beforeunload', - Confirm: 'confirm', - Prompt: 'prompt' -}; diff --git a/src/firefox/Dialog.ts b/src/firefox/Dialog.ts deleted file mode 100644 index ec3c236dec..0000000000 --- a/src/firefox/Dialog.ts +++ /dev/null @@ -1,51 +0,0 @@ -import {assert, debugError} from '../helper'; - -export class Dialog { - private _client: any; - private _dialogId: any; - private _type: string; - private _message: string; - private _handled: boolean; - private _defaultValue: string; - - constructor(client, payload) { - this._client = client; - this._dialogId = payload.dialogId; - this._type = payload.type; - this._message = payload.message; - this._handled = false; - this._defaultValue = payload.defaultValue || ''; - } - - type(): string { - return this._type; - } - - message(): string { - return this._message; - } - - defaultValue(): string { - return this._defaultValue; - } - - async accept(promptText: string | undefined) { - assert(!this._handled, 'Cannot accept dialog which is already handled!'); - this._handled = true; - await this._client.send('Page.handleDialog', { - dialogId: this._dialogId, - accept: true, - promptText: promptText - }).catch(debugError); - } - - async dismiss() { - assert(!this._handled, 'Cannot dismiss dialog which is already handled!'); - this._handled = true; - await this._client.send('Page.handleDialog', { - dialogId: this._dialogId, - accept: false - }).catch(debugError); - } -} - diff --git a/src/firefox/Page.ts b/src/firefox/Page.ts index 3a77f4555a..55307cefe7 100644 --- a/src/firefox/Page.ts +++ b/src/firefox/Page.ts @@ -23,7 +23,6 @@ import { assert, debugError, helper, RegisteredListener } from '../helper'; import { TimeoutSettings } from '../TimeoutSettings'; import { BrowserContext, Target } from './Browser'; import { JugglerSession, JugglerSessionEvents } from './Connection'; -import { Dialog } from './Dialog'; import { Events } from './events'; import { Accessibility } from './features/accessibility'; import { Interception } from './features/interception'; @@ -38,6 +37,7 @@ import * as js from '../javascript'; import * as network from '../network'; import * as frames from '../frames'; import { toHandle, toPayload, deserializeValue } from './ExecutionContext'; +import * as dialog from '../dialog'; const writeFileAsync = helper.promisify(fs.writeFile); @@ -304,7 +304,13 @@ export class Page extends EventEmitter { } _onDialogOpened(params) { - this.emit(Events.Page.Dialog, new Dialog(this._session, params)); + this.emit(Events.Page.Dialog, new dialog.Dialog( + params.type as dialog.DialogType, + params.message, + async (accept: boolean, promptText?: string) => { + await this._session.send('Page.handleDialog', { dialogId: params.dialogId, accept, promptText }).catch(debugError); + }, + params.defaultValue)); } mainFrame(): frames.Frame { diff --git a/src/firefox/api.ts b/src/firefox/api.ts index 60ae22b6e8..ca25af68b3 100644 --- a/src/firefox/api.ts +++ b/src/firefox/api.ts @@ -5,7 +5,7 @@ export { TimeoutError } from '../Errors'; export { Keyboard, Mouse } from '../input'; export { Browser, BrowserContext, Target } from './Browser'; export { BrowserFetcher } from './BrowserFetcher'; -export { Dialog } from './Dialog'; +export { Dialog } from '../dialog'; export { ExecutionContext, JSHandle } from '../javascript'; export { Accessibility } from './features/accessibility'; export { Interception } from './features/interception'; diff --git a/src/webkit/Dialog.ts b/src/webkit/Dialog.ts deleted file mode 100644 index fdf41678bb..0000000000 --- a/src/webkit/Dialog.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * Modifications copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { TargetSession } from './Connection'; -import { assert } from '../helper'; - -export class Dialog { - private _client: TargetSession; - private _type: string; - private _message: string; - private _handled = false; - private _defaultValue: string; - - constructor(client: TargetSession, type: string, message: string, defaultValue: (string | undefined) = '') { - this._client = client; - this._type = type; - this._message = message; - this._defaultValue = defaultValue; - } - - type(): string { - return this._type; - } - - message(): string { - return this._message; - } - - defaultValue(): string { - return this._defaultValue; - } - - async accept(promptText: string | undefined) { - assert(!this._handled, 'Cannot accept dialog which is already handled!'); - this._handled = true; - await this._client.send('Dialog.handleJavaScriptDialog', { - accept: true, - promptText: promptText - }); - } - - async dismiss() { - assert(!this._handled, 'Cannot dismiss dialog which is already handled!'); - this._handled = true; - await this._client.send('Dialog.handleJavaScriptDialog', { - accept: false - }); - } -} - -export const DialogType = { - Alert: 'alert', - BeforeUnload: 'beforeunload', - Confirm: 'confirm', - Prompt: 'prompt' -}; diff --git a/src/webkit/Page.ts b/src/webkit/Page.ts index ffe9c2ff90..d1775a3bed 100644 --- a/src/webkit/Page.ts +++ b/src/webkit/Page.ts @@ -38,7 +38,7 @@ import * as dom from '../dom'; import * as frames from '../frames'; import * as js from '../javascript'; import * as network from '../network'; -import { Dialog, DialogType } from './Dialog'; +import * as dialog from '../dialog'; const writeFileAsync = helper.promisify(fs.writeFile); @@ -119,18 +119,13 @@ export class Page extends EventEmitter { } _onDialog(event: Protocol.Dialog.javascriptDialogOpeningPayload) { - let dialogType = null; - if (event.type === 'alert') - dialogType = DialogType.Alert; - else if (event.type === 'confirm') - dialogType = DialogType.Confirm; - else if (event.type === 'prompt') - dialogType = DialogType.Prompt; - else if (event.type === 'beforeunload') - dialogType = DialogType.BeforeUnload; - assert(dialogType, 'Unknown javascript dialog type: ' + event.type); - const dialog = new Dialog(this._session, dialogType, event.message, event.defaultPrompt); - this.emit(Events.Page.Dialog, dialog); + this.emit(Events.Page.Dialog, new dialog.Dialog( + event.type as dialog.DialogType, + event.message, + async (accept: boolean, promptText?: string) => { + await this._session.send('Dialog.handleJavaScriptDialog', { accept, promptText }); + }, + event.defaultPrompt)); } _setTarget(newTarget: Target) { diff --git a/src/webkit/api.ts b/src/webkit/api.ts index 99603f3457..b167943692 100644 --- a/src/webkit/api.ts +++ b/src/webkit/api.ts @@ -12,4 +12,4 @@ export { Request, Response } from '../network'; export { ConsoleMessage, Page } from './Page'; export { Playwright } from './Playwright'; export { Target } from './Target'; - +export { Dialog } from '../dialog';