diff options
Diffstat (limited to 'remote/shared/messagehandler/test/browser/resources/modules/windowglobal')
6 files changed, 362 insertions, 0 deletions
diff --git a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/command.sys.mjs b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/command.sys.mjs new file mode 100644 index 0000000000..23655a464a --- /dev/null +++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/command.sys.mjs @@ -0,0 +1,114 @@ +/* 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 { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs"; + +class CommandModule extends Module { + constructor(messageHandler) { + super(messageHandler); + this._lastSessionDataUpdate = {}; + this._subscribedEvents = new Set(); + this._testCategorySessionData = []; + + this._createdByMessageHandlerConstructor = this._isCreatedByMessageHandlerConstructor(); + } + destroy() {} + + /** + * Commands + */ + + _applySessionData(params) { + if (params.category === "testCategory") { + const added = []; + const removed = []; + + 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._subscribedEvents.delete(event); + removed.push(event); + } + } + + // Subscribe to all events, which have an item in SessionData + for (const { value } of filteredSessionData) { + if (!this._subscribedEvents.has(value)) { + this._subscribedEvents.add(value); + added.push(value); + } + } + + this._testCategorySessionData = this._testCategorySessionData + .concat(added) + .filter(value => !removed.includes(value)); + + this._lastSessionDataUpdate = { + addedData: added.join(", "), + removedData: removed.join(", "), + sessionData: this._testCategorySessionData.join(", "), + contextId: this.messageHandler.contextId, + }; + } + + if (params.category === "browser_session_data_browser_element") { + this.emitEvent("received-session-data", { + contextId: this.messageHandler.contextId, + }); + } + + return {}; + } + + _getSessionDataUpdate(params) { + const lastUpdate = this._lastSessionDataUpdate; + + // Each "lastUpdate" should only be returned once, so that the caller can + // assert when a SessionData update had no impact. + this._lastSessionDataUpdate = null; + + return lastUpdate; + } + + testWindowGlobalModule() { + return "windowglobal-value"; + } + + testSetValue(params) { + const { value } = params; + + this._testValue = value; + } + + testGetValue() { + return this._testValue; + } + + testForwardToWindowGlobal() { + return "forward-to-windowglobal-value"; + } + + testIsCreatedByMessageHandlerConstructor() { + return this._createdByMessageHandlerConstructor; + } + + _isCreatedByMessageHandlerConstructor() { + let caller = Components.stack.caller; + while (caller) { + if (caller.name === this.messageHandler.constructor.name) { + return true; + } + caller = caller.caller; + } + return false; + } +} + +export const command = CommandModule; diff --git a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/commandwindowglobalonly.sys.mjs b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/commandwindowglobalonly.sys.mjs new file mode 100644 index 0000000000..1e4e6c1574 --- /dev/null +++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/commandwindowglobalonly.sys.mjs @@ -0,0 +1,41 @@ +/* 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 { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs"; + +class CommandWindowGlobalOnlyModule extends Module { + destroy() {} + + /** + * Commands + */ + + testOnlyInWindowGlobal() { + return "only-in-windowglobal"; + } + + testBroadcast() { + return `broadcast-${this.messageHandler.contextId}`; + } + + testBroadcastWithParameter(params) { + return `broadcast-${this.messageHandler.contextId}-${params.value}`; + } + + testError() { + throw new Error("error-from-module"); + } + + testMissingIntermediaryMethod(params, destination) { + // Spawn a new internal command, but with a commandName which doesn't match + // any method. + return this.messageHandler.handleCommand({ + moduleName: "commandwindowglobalonly", + commandName: "missingMethod", + destination, + }); + } +} + +export const commandwindowglobalonly = CommandWindowGlobalOnlyModule; diff --git a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/event.sys.mjs b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/event.sys.mjs new file mode 100644 index 0000000000..5bb50cb83d --- /dev/null +++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/event.sys.mjs @@ -0,0 +1,26 @@ +/* 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 { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs"; + +class EventModule extends Module { + destroy() {} + + /** + * Commands + */ + + testEmitEvent() { + // Emit a payload including the contextId to check which context emitted + // a specific event. + const text = `event from ${this.messageHandler.contextId}`; + this.emitEvent("event-from-window-global", { text }); + } + + testEmitEventWithInterception() { + this.emitEvent("event.testEventWithInterception", {}); + } +} + +export const event = EventModule; diff --git a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/eventemitter.sys.mjs b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/eventemitter.sys.mjs new file mode 100644 index 0000000000..c86954c5e0 --- /dev/null +++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/eventemitter.sys.mjs @@ -0,0 +1,81 @@ +/* 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 { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs"; + +class EventEmitterModule extends Module { + #isSubscribed; + #subscribedEvents; + + constructor(messageHandler) { + super(messageHandler); + this.#isSubscribed = false; + this.#subscribedEvents = new Set(); + } + + destroy() {} + + /** + * Commands + */ + + emitTestEvent() { + if (this.#isSubscribed) { + const text = `event from ${this.messageHandler.contextId}`; + this.emitEvent("eventemitter.testEvent", { text }); + } + + // Emit another event consistently for monitoring during the test. + this.emitEvent("eventemitter.monitoringEvent", {}); + } + + isSubscribed() { + return this.#isSubscribed; + } + + _applySessionData(params) { + 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); + } + } + } + + #subscribeEvent(event) { + if (event === "eventemitter.testEvent") { + if (this.#isSubscribed) { + throw new Error("Already subscribed to eventemitter.testEvent"); + } + this.#isSubscribed = true; + this.#subscribedEvents.add(event); + } + } + + #unsubscribeEvent(event) { + if (event === "eventemitter.testEvent") { + if (!this.#isSubscribed) { + throw new Error("Not subscribed to eventemitter.testEvent"); + } + this.#isSubscribed = false; + this.#subscribedEvents.delete(event); + } + } +} + +export const eventemitter = EventEmitterModule; diff --git a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/eventnointercept.sys.mjs b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/eventnointercept.sys.mjs new file mode 100644 index 0000000000..48bbfbf951 --- /dev/null +++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/eventnointercept.sys.mjs @@ -0,0 +1,16 @@ +/* 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 { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs"; + +class EventNoInterceptModule extends Module { + destroy() {} + + testEvent() { + const text = `event no interception`; + this.emitEvent("eventnointercept.testEvent", { text }); + } +} + +export const eventnointercept = EventNoInterceptModule; diff --git a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/retry.sys.mjs b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/retry.sys.mjs new file mode 100644 index 0000000000..f7b2279018 --- /dev/null +++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/retry.sys.mjs @@ -0,0 +1,84 @@ +/* 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 { Module } from "chrome://remote/content/shared/messagehandler/Module.sys.mjs"; + +// Store counters in the JSM scope to persist them across reloads. +let callsToBlockedOneTime = 0; +let callsToBlockedTenTimes = 0; +let callsToBlockedElevenTimes = 0; + +// This module provides various commands which all hang for various reasons. +// The test is supposed to trigger the command and then destroy the +// JSWindowActor pair by any mean (eg a navigation) in order to trigger an +// AbortError and a retry. +class RetryModule extends Module { + destroy() {} + + /** + * Commands + */ + + // Resolves only if called while on the example.net domain. + async blockedOnNetDomain(params) { + // Note: we do not store a call counter here, because this is used for a + // cross-group navigation test, and the JSM will be loaded in different + // processes. + const uri = this.messageHandler.window.document.baseURI; + if (!uri.includes("example.net")) { + await new Promise(r => {}); + } + + return { ...params }; + } + + // Resolves only if called more than once. + async blockedOneTime(params) { + callsToBlockedOneTime++; + if (callsToBlockedOneTime < 2) { + await new Promise(r => {}); + } + + // Return: + // - params sent to the command to check that retries have correct params + // - the call counter + return { ...params, callsToCommand: callsToBlockedOneTime }; + } + + // Resolves only if called more than ten times (which is exactly the maximum + // of retry attempts). + async blockedTenTimes(params) { + callsToBlockedTenTimes++; + if (callsToBlockedTenTimes < 11) { + await new Promise(r => {}); + } + + // Return: + // - params sent to the command to check that retries have correct params + // - the call counter + return { ...params, callsToCommand: callsToBlockedTenTimes }; + } + + // Resolves only if called more than eleven times (which is greater than the + // maximum of retry attempts). + async blockedElevenTimes(params) { + callsToBlockedElevenTimes++; + if (callsToBlockedElevenTimes < 12) { + await new Promise(r => {}); + } + + // Return: + // - params sent to the command to check that retries have correct params + // - the call counter + return { ...params, callsToCommand: callsToBlockedElevenTimes }; + } + + cleanup() { + callsToBlockedOneTime = 0; + callsToBlockedTenTimes = 0; + callsToBlockedElevenTimes = 0; + } +} + +export const retry = RetryModule; |