diff options
Diffstat (limited to '')
-rw-r--r-- | mobile/android/actors/GeckoViewPrompterParent.jsm | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/mobile/android/actors/GeckoViewPrompterParent.jsm b/mobile/android/actors/GeckoViewPrompterParent.jsm new file mode 100644 index 0000000000..67d87922ee --- /dev/null +++ b/mobile/android/actors/GeckoViewPrompterParent.jsm @@ -0,0 +1,162 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +var EXPORTED_SYMBOLS = ["GeckoViewPrompterParent"]; + +const { GeckoViewActorParent } = ChromeUtils.importESModule( + "resource://gre/modules/GeckoViewActorParent.sys.mjs" +); + +const DIALOGS = [ + "alert", + "alertCheck", + "confirm", + "confirmCheck", + "prompt", + "promptCheck", +]; + +class GeckoViewPrompterParent extends GeckoViewActorParent { + constructor() { + super(); + this._prompts = new Map(); + } + + get rootActor() { + return this.browsingContext.top.currentWindowGlobal.getActor( + "GeckoViewPrompter" + ); + } + + registerPrompt(promptId, promptType, actor) { + return this._prompts.set( + promptId, + new RemotePrompt(promptId, promptType, actor) + ); + } + + unregisterPrompt(promptId) { + this._prompts.delete(promptId); + } + + notifyPromptShow(promptId) { + // ToDo: Bug 1761480 - GeckoView can send additional prompts to Marionette + if (this._prompts.get(promptId).isDialog) { + Services.obs.notifyObservers({ id: promptId }, "geckoview-prompt-show"); + } + } + + getPrompts() { + const self = this; + const prompts = []; + // Marionette expects this event to be fired from the parent + const dialogClosedEvent = new CustomEvent("DOMModalDialogClosed", { + cancelable: true, + bubbles: true, + }); + for (const [, prompt] of this._prompts) { + // Adding only WebDriver compliant dialogs to the window + if (prompt.isDialog) { + prompts.push({ + args: { + modalType: "GeckoViewPrompter", + promptType: prompt.type, + isDialog: prompt.isDialog, + }, + setInputText(text) { + prompt.setInputText(text); + }, + async getPromptText() { + return prompt.getPromptText(); + }, + async getInputText() { + return prompt.getInputText(); + }, + acceptPrompt() { + prompt.acceptPrompt(); + self.window.dispatchEvent(dialogClosedEvent); + }, + dismissPrompt() { + prompt.dismissPrompt(); + self.window.dispatchEvent(dialogClosedEvent); + }, + }); + } + } + return prompts; + } + + /** + * Handles the message coming from GeckoViewPrompterChild. + * + * @param {string} message.name The subject of the message. + * @param {object} message.data The data of the message. + */ + // eslint-disable-next-line consistent-return + async receiveMessage({ name, data }) { + switch (name) { + case "RegisterPrompt": { + this.rootActor.registerPrompt(data.id, data.promptType, this); + break; + } + case "UnregisterPrompt": { + this.rootActor.unregisterPrompt(data.id); + break; + } + case "NotifyPromptShow": { + this.rootActor.notifyPromptShow(data.id); + break; + } + default: { + return super.receiveMessage({ name, data }); + } + } + } +} + +class RemotePrompt { + constructor(id, type, actor) { + this.id = id; + this.type = type; + this.actor = actor; + } + + // Checks if the prompt conforms to a WebDriver simple dialog. + get isDialog() { + return DIALOGS.includes(this.type); + } + + getPromptText() { + return this.actor.sendQuery("GetPromptText", { + id: this.id, + }); + } + + getInputText() { + return this.actor.sendQuery("GetInputText", { + id: this.id, + }); + } + + setInputText(inputText) { + this.actor.sendAsyncMessage("SetInputText", { + id: this.id, + text: inputText, + }); + } + + acceptPrompt() { + this.actor.sendAsyncMessage("AcceptPrompt", { + id: this.id, + }); + } + + dismissPrompt() { + this.actor.sendAsyncMessage("DismissPrompt", { + id: this.id, + }); + } +} |