diff options
Diffstat (limited to 'remote/webdriver-bidi/modules/windowglobal/browsingContext.sys.mjs')
-rw-r--r-- | remote/webdriver-bidi/modules/windowglobal/browsingContext.sys.mjs | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/remote/webdriver-bidi/modules/windowglobal/browsingContext.sys.mjs b/remote/webdriver-bidi/modules/windowglobal/browsingContext.sys.mjs new file mode 100644 index 0000000000..675626353c --- /dev/null +++ b/remote/webdriver-bidi/modules/windowglobal/browsingContext.sys.mjs @@ -0,0 +1,159 @@ +/* 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/. */ + +import { WindowGlobalBiDiModule } from "chrome://remote/content/webdriver-bidi/modules/WindowGlobalBiDiModule.sys.mjs"; + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + LoadListener: "chrome://remote/content/shared/listeners/LoadListener.sys.mjs", +}); + +class BrowsingContextModule extends WindowGlobalBiDiModule { + #loadListener; + #subscribedEvents; + + constructor(messageHandler) { + super(messageHandler); + + // Setup the LoadListener as early as possible. + this.#loadListener = new lazy.LoadListener(this.messageHandler.window); + this.#loadListener.on("DOMContentLoaded", this.#onDOMContentLoaded); + this.#loadListener.on("load", this.#onLoad); + + // Set of event names which have active subscriptions. + this.#subscribedEvents = new Set(); + } + + destroy() { + this.#loadListener.destroy(); + this.#subscribedEvents = null; + } + + #getNavigationInfo(data) { + return { + context: this.messageHandler.context, + // TODO: The navigation id should be a real id mapped to the navigation. + // See https://bugzilla.mozilla.org/show_bug.cgi?id=1763122 + navigation: null, + timestamp: Date.now(), + url: data.target.URL, + }; + } + + #startListening() { + if (this.#subscribedEvents.size == 0) { + this.#loadListener.startListening(); + } + } + + #stopListening() { + if (this.#subscribedEvents.size == 0) { + this.#loadListener.stopListening(); + } + } + + #subscribeEvent(event) { + switch (event) { + case "browsingContext._documentInteractive": + this.#startListening(); + this.#subscribedEvents.add("browsingContext._documentInteractive"); + break; + case "browsingContext.domContentLoaded": + this.#startListening(); + this.#subscribedEvents.add("browsingContext.domContentLoaded"); + break; + case "browsingContext.load": + this.#startListening(); + this.#subscribedEvents.add("browsingContext.load"); + break; + } + } + + #unsubscribeEvent(event) { + switch (event) { + case "browsingContext._documentInteractive": + this.#subscribedEvents.delete("browsingContext._documentInteractive"); + break; + case "browsingContext.domContentLoaded": + this.#subscribedEvents.delete("browsingContext.domContentLoaded"); + break; + case "browsingContext.load": + this.#subscribedEvents.delete("browsingContext.load"); + break; + } + + this.#stopListening(); + } + + #onDOMContentLoaded = (eventName, data) => { + if (this.#subscribedEvents.has("browsingContext._documentInteractive")) { + this.messageHandler.emitEvent("browsingContext._documentInteractive", { + baseURL: data.target.baseURI, + contextId: this.messageHandler.contextId, + documentURL: data.target.URL, + innerWindowId: this.messageHandler.innerWindowId, + readyState: data.target.readyState, + }); + } + + if (this.#subscribedEvents.has("browsingContext.domContentLoaded")) { + this.emitEvent( + "browsingContext.domContentLoaded", + this.#getNavigationInfo(data) + ); + } + }; + + #onLoad = (eventName, data) => { + if (this.#subscribedEvents.has("browsingContext.load")) { + this.emitEvent("browsingContext.load", this.#getNavigationInfo(data)); + } + }; + + /** + * Internal commands + */ + + _applySessionData(params) { + // TODO: Bug 1775231. Move this logic to a shared module or an abstract + // class. + const { category } = params; + if (category === "event") { + const filteredSessionData = params.sessionData.filter(item => + this.messageHandler.matchesContext(item.contextDescriptor) + ); + for (const event of this.#subscribedEvents.values()) { + const hasSessionItem = filteredSessionData.some( + item => item.value === event + ); + // If there are no session items for this context, we should unsubscribe from the event. + if (!hasSessionItem) { + this.#unsubscribeEvent(event); + } + } + + // Subscribe to all events, which have an item in SessionData. + for (const { value } of filteredSessionData) { + this.#subscribeEvent(value); + } + } + } + + _getBaseURL() { + return this.messageHandler.window.document.baseURI; + } + + _getScreenshotRect() { + const win = this.messageHandler.window; + return new DOMRect( + win.pageXOffset, + win.pageYOffset, + win.innerWidth, + win.innerHeight + ); + } +} + +export const browsingContext = BrowsingContextModule; |