summaryrefslogtreecommitdiffstats
path: root/remote/shared
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
commit086c044dc34dfc0f74fbe41f4ecb402b2cd34884 (patch)
treea4f824bd33cb075dd5aa3eb5a0a94af221bbe83a /remote/shared
parentAdding debian version 124.0.1-1. (diff)
downloadfirefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.tar.xz
firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.zip
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'remote/shared')
-rw-r--r--remote/shared/AppInfo.sys.mjs2
-rw-r--r--remote/shared/RecommendedPreferences.sys.mjs14
-rw-r--r--remote/shared/WebSocketConnection.sys.mjs7
-rw-r--r--remote/shared/js-window-actors/NavigationListenerChild.sys.mjs4
-rw-r--r--remote/shared/listeners/ContextualIdentityListener.sys.mjs2
-rw-r--r--remote/shared/listeners/NetworkEventRecord.sys.mjs31
-rw-r--r--remote/shared/listeners/test/browser/browser_NetworkListener.js8
-rw-r--r--remote/shared/listeners/test/browser/browser_PromptListener.js4
-rw-r--r--remote/shared/messagehandler/MessageHandler.sys.mjs13
-rw-r--r--remote/shared/messagehandler/Module.sys.mjs4
-rw-r--r--remote/shared/messagehandler/RootMessageHandler.sys.mjs2
-rw-r--r--remote/shared/messagehandler/sessiondata/SessionDataReader.sys.mjs2
-rw-r--r--remote/shared/messagehandler/test/browser/resources/modules/windowglobal/retry.sys.mjs8
-rw-r--r--remote/shared/messagehandler/test/browser/resources/modules/windowglobal/windowglobaltoroot.sys.mjs4
-rw-r--r--remote/shared/test/browser/browser_UserContextManager.js5
-rw-r--r--remote/shared/test/xpcshell/test_RecommendedPreferences.js5
-rw-r--r--remote/shared/test/xpcshell/test_Sync.js10
-rw-r--r--remote/shared/webdriver/Actions.sys.mjs57
-rw-r--r--remote/shared/webdriver/Capabilities.sys.mjs6
-rw-r--r--remote/shared/webdriver/Errors.sys.mjs17
-rw-r--r--remote/shared/webdriver/Event.sys.mjs295
-rw-r--r--remote/shared/webdriver/process-actors/WebDriverProcessDataChild.sys.mjs2
-rw-r--r--remote/shared/webdriver/test/xpcshell/test_Errors.js9
23 files changed, 393 insertions, 118 deletions
diff --git a/remote/shared/AppInfo.sys.mjs b/remote/shared/AppInfo.sys.mjs
index 9e354503ef..16db0191de 100644
--- a/remote/shared/AppInfo.sys.mjs
+++ b/remote/shared/AppInfo.sys.mjs
@@ -24,7 +24,7 @@ const ID_THUNDERBIRD = "{3550f703-e582-4d05-9a08-453d09bdfdc6}";
export const AppInfo = new Proxy(
{},
{
- get(target, prop, receiver) {
+ get(target, prop) {
if (target.hasOwnProperty(prop)) {
return target[prop];
}
diff --git a/remote/shared/RecommendedPreferences.sys.mjs b/remote/shared/RecommendedPreferences.sys.mjs
index d0a7739e52..b52057ee2b 100644
--- a/remote/shared/RecommendedPreferences.sys.mjs
+++ b/remote/shared/RecommendedPreferences.sys.mjs
@@ -145,6 +145,9 @@ const COMMON_PREFERENCES = new Map([
// Do not redirect user when a milstone upgrade of Firefox is detected
["browser.startup.homepage_override.mstone", "ignore"],
+ // Unload the previously selected tab immediately
+ ["browser.tabs.remote.unloadDelayMs", 0],
+
// Don't unload tabs when available memory is running low
["browser.tabs.unloadOnLowMemory", false],
@@ -310,6 +313,9 @@ const COMMON_PREFERENCES = new Map([
// Privacy and Tracking Protection
["privacy.trackingprotection.enabled", false],
+ // Used to check if recommended preferences are applied
+ ["remote.prefs.recommended.applied", true],
+
// Don't do network connections for mitm priming
["security.certerrors.mitm.priming.enabled", false],
@@ -362,7 +368,7 @@ export const RecommendedPreferences = {
* @param {Map<string, object>=} preferences
* Map of preference name to preference value.
*/
- applyPreferences(preferences) {
+ applyPreferences(preferences = new Map()) {
if (!lazy.useRecommendedPrefs) {
// If remote.prefs.recommended is set to false, do not set any preference
// here. Needed for our Firefox CI.
@@ -374,11 +380,7 @@ export const RecommendedPreferences = {
if (!this.isInitialized) {
// Merge common preferences and optionally provided preferences in a
// single map. Hereby the extra preferences have higher priority.
- if (preferences) {
- preferences = new Map([...COMMON_PREFERENCES, ...preferences]);
- } else {
- preferences = COMMON_PREFERENCES;
- }
+ preferences = new Map([...COMMON_PREFERENCES, ...preferences]);
Services.obs.addObserver(this, "quit-application");
this.isInitialized = true;
diff --git a/remote/shared/WebSocketConnection.sys.mjs b/remote/shared/WebSocketConnection.sys.mjs
index c9ef050dc5..57b533fffb 100644
--- a/remote/shared/WebSocketConnection.sys.mjs
+++ b/remote/shared/WebSocketConnection.sys.mjs
@@ -85,11 +85,8 @@ export class WebSocketConnection {
* Register a new Session to forward the messages to.
*
* Needs to be implemented in the sub class.
- *
- * @param {Session} session
- * The session to register.
*/
- registerSession(session) {
+ registerSession() {
throw new Error("Not implemented");
}
@@ -140,7 +137,7 @@ export class WebSocketConnection {
/**
* Called by the `transport` when the connection is closed.
*/
- onConnectionClose(status) {
+ onConnectionClose() {
lazy.logger.debug(`${this.constructor.name} ${this.id} closed`);
}
diff --git a/remote/shared/js-window-actors/NavigationListenerChild.sys.mjs b/remote/shared/js-window-actors/NavigationListenerChild.sys.mjs
index a2cd8ccf10..728d9b6e8c 100644
--- a/remote/shared/js-window-actors/NavigationListenerChild.sys.mjs
+++ b/remote/shared/js-window-actors/NavigationListenerChild.sys.mjs
@@ -56,12 +56,12 @@ export class NavigationListenerChild extends JSWindowActorChild {
/**
* See note above
*/
- handleEvent(event) {}
+ handleEvent() {}
/**
* See note above
*/
- receiveMessage(message) {}
+ receiveMessage() {}
/**
* A browsing context might be replaced before reaching the parent process,
diff --git a/remote/shared/listeners/ContextualIdentityListener.sys.mjs b/remote/shared/listeners/ContextualIdentityListener.sys.mjs
index d93b44ed77..42954d223c 100644
--- a/remote/shared/listeners/ContextualIdentityListener.sys.mjs
+++ b/remote/shared/listeners/ContextualIdentityListener.sys.mjs
@@ -49,7 +49,7 @@ export class ContextualIdentityListener {
this.stopListening();
}
- observe(subject, topic, data) {
+ observe(subject, topic) {
switch (topic) {
case OBSERVER_TOPIC_CREATED:
this.emit("created", { identity: subject.wrappedJSObject });
diff --git a/remote/shared/listeners/NetworkEventRecord.sys.mjs b/remote/shared/listeners/NetworkEventRecord.sys.mjs
index a41f3edd7d..72b43e3de1 100644
--- a/remote/shared/listeners/NetworkEventRecord.sys.mjs
+++ b/remote/shared/listeners/NetworkEventRecord.sys.mjs
@@ -163,13 +163,8 @@ export class NetworkEventRecord {
* Required API for a NetworkObserver event owner.
*
* Not used for RemoteAgent.
- *
- * @param {object} info
- * The object containing security information.
- * @param {boolean} isRacing
- * True if the corresponding channel raced the cache and network requests.
*/
- addSecurityInfo(info, isRacing) {}
+ addSecurityInfo() {}
/**
* Add network event timings.
@@ -177,15 +172,8 @@ export class NetworkEventRecord {
* Required API for a NetworkObserver event owner.
*
* Not used for RemoteAgent.
- *
- * @param {number} total
- * The total time for the request.
- * @param {object} timings
- * The har-like timings.
- * @param {object} offsets
- * The har-like timings, but as offset from the request start.
*/
- addEventTimings(total, timings, offsets) {}
+ addEventTimings() {}
/**
* Add response cache entry.
@@ -193,11 +181,8 @@ export class NetworkEventRecord {
* Required API for a NetworkObserver event owner.
*
* Not used for RemoteAgent.
- *
- * @param {object} options
- * An object which contains a single responseCache property.
*/
- addResponseCache(options) {}
+ addResponseCache() {}
/**
* Add response content.
@@ -233,11 +218,8 @@ export class NetworkEventRecord {
* Required API for a NetworkObserver event owner.
*
* Not used for RemoteAgent.
- *
- * @param {Array} serverTimings
- * The server timings.
*/
- addServerTimings(serverTimings) {}
+ addServerTimings() {}
/**
* Add service worker timings.
@@ -245,11 +227,8 @@ export class NetworkEventRecord {
* Required API for a NetworkObserver event owner.
*
* Not used for RemoteAgent.
- *
- * @param {object} serviceWorkerTimings
- * The server timings.
*/
- addServiceWorkerTimings(serviceWorkerTimings) {}
+ addServiceWorkerTimings() {}
onAuthPrompt(authDetails, authCallbacks) {
this.#emitAuthRequired(authCallbacks);
diff --git a/remote/shared/listeners/test/browser/browser_NetworkListener.js b/remote/shared/listeners/test/browser/browser_NetworkListener.js
index 78865f6b80..cc1b42f2fc 100644
--- a/remote/shared/listeners/test/browser/browser_NetworkListener.js
+++ b/remote/shared/listeners/test/browser/browser_NetworkListener.js
@@ -32,22 +32,22 @@ add_task(async function test_beforeRequestSent() {
listener.startListening();
await fetch(tab1.linkedBrowser, "https://example.com/?1");
- ok(events.length == 1, "One event was received");
+ Assert.equal(events.length, 1, "One event was received");
assertNetworkEvent(events[0], contextId1, "https://example.com/?1");
info("Check that events are no longer emitted after calling stopListening");
listener.stopListening();
await fetch(tab1.linkedBrowser, "https://example.com/?2");
- ok(events.length == 1, "No new event was received");
+ Assert.equal(events.length, 1, "No new event was received");
listener.startListening();
await fetch(tab1.linkedBrowser, "https://example.com/?3");
- ok(events.length == 2, "A new event was received");
+ Assert.equal(events.length, 2, "A new event was received");
assertNetworkEvent(events[1], contextId1, "https://example.com/?3");
info("Check network event from the new tab");
await fetch(tab2.linkedBrowser, "https://example.com/?4");
- ok(events.length == 3, "A new event was received");
+ Assert.equal(events.length, 3, "A new event was received");
assertNetworkEvent(events[2], contextId2, "https://example.com/?4");
gBrowser.removeTab(tab1);
diff --git a/remote/shared/listeners/test/browser/browser_PromptListener.js b/remote/shared/listeners/test/browser/browser_PromptListener.js
index 0d3f23db3f..30503ef4fa 100644
--- a/remote/shared/listeners/test/browser/browser_PromptListener.js
+++ b/remote/shared/listeners/test/browser/browser_PromptListener.js
@@ -156,7 +156,7 @@ add_task(async function test_events_in_another_browser() {
await createScriptNode(`setTimeout(() => window.confirm('test'))`);
const dialogWin = await dialogPromise;
- ok(events.length === 0, "No event was received");
+ Assert.strictEqual(events.length, 0, "No event was received");
dialogWin.document.querySelector("dialog").acceptDialog();
@@ -166,7 +166,7 @@ add_task(async function test_events_in_another_browser() {
setTimeout(resolve, 500);
});
- ok(events.length === 0, "No event was received");
+ Assert.strictEqual(events.length, 0, "No event was received");
listener.destroy();
await BrowserTestUtils.closeWindow(win);
diff --git a/remote/shared/messagehandler/MessageHandler.sys.mjs b/remote/shared/messagehandler/MessageHandler.sys.mjs
index 18ec6b820c..61c8b5c40e 100644
--- a/remote/shared/messagehandler/MessageHandler.sys.mjs
+++ b/remote/shared/messagehandler/MessageHandler.sys.mjs
@@ -215,7 +215,7 @@ export class MessageHandler extends EventEmitter {
/**
* Retrieve all module classes matching the moduleName and destination.
- * See `getAllModuleClasses` (ModuleCache.jsm) for more details.
+ * See `getAllModuleClasses` (ModuleCache.sys.mjs) for more details.
*
* @param {string} moduleName
* The name of the module.
@@ -267,11 +267,8 @@ export class MessageHandler extends EventEmitter {
* provided to this MessageHandler on startup. Implementation is specific to each MessageHandler class.
*
* By default the implementation is a no-op.
- *
- * @param {Array<SessionDataItem>} sessionDataItems
- * Initial session data items for this MessageHandler.
*/
- async initialize(sessionDataItems) {}
+ async initialize() {}
/**
* Returns the module path corresponding to this MessageHandler class.
@@ -297,7 +294,7 @@ export class MessageHandler extends EventEmitter {
*
* Needs to be implemented in the sub class.
*/
- static getIdFromContext(context) {
+ static getIdFromContext() {
throw new Error("Not implemented");
}
@@ -306,7 +303,7 @@ export class MessageHandler extends EventEmitter {
*
* Needs to be implemented in the sub class.
*/
- forwardCommand(command) {
+ forwardCommand() {
throw new Error("Not implemented");
}
@@ -316,7 +313,7 @@ export class MessageHandler extends EventEmitter {
*
* Needs to be implemented in the sub class.
*/
- matchesContext(contextDescriptor) {
+ matchesContext() {
throw new Error("Not implemented");
}
diff --git a/remote/shared/messagehandler/Module.sys.mjs b/remote/shared/messagehandler/Module.sys.mjs
index 30b26938e2..c526c7ce6c 100644
--- a/remote/shared/messagehandler/Module.sys.mjs
+++ b/remote/shared/messagehandler/Module.sys.mjs
@@ -61,12 +61,12 @@ export class Module {
*
* @param {string} name
* Name of the event.
- * @param {object} payload
+ * @param {object} _payload
* The event's payload.
* @returns {object}
* The modified event payload.
*/
- interceptEvent(name, payload) {
+ interceptEvent(name, _payload) {
throw new Error(
`Could not intercept event ${name}, interceptEvent is not implemented in windowglobal-in-root module`
);
diff --git a/remote/shared/messagehandler/RootMessageHandler.sys.mjs b/remote/shared/messagehandler/RootMessageHandler.sys.mjs
index 06a8cd6f18..ce571c3c12 100644
--- a/remote/shared/messagehandler/RootMessageHandler.sys.mjs
+++ b/remote/shared/messagehandler/RootMessageHandler.sys.mjs
@@ -51,7 +51,7 @@ export class RootMessageHandler extends MessageHandler {
* The ROOT MessageHandler is unique for a given MessageHandler network
* (ie for a given sessionId). Reuse the type as context id here.
*/
- static getIdFromContext(context) {
+ static getIdFromContext() {
return RootMessageHandler.type;
}
diff --git a/remote/shared/messagehandler/sessiondata/SessionDataReader.sys.mjs b/remote/shared/messagehandler/sessiondata/SessionDataReader.sys.mjs
index 6d5ea08e59..f7c91e6bbf 100644
--- a/remote/shared/messagehandler/sessiondata/SessionDataReader.sys.mjs
+++ b/remote/shared/messagehandler/sessiondata/SessionDataReader.sys.mjs
@@ -18,7 +18,7 @@ ChromeUtils.defineLazyGetter(lazy, "sharedData", () => {
/**
* Returns a snapshot of the session data map, which is cloned from the
- * sessionDataMap singleton of SessionData.jsm.
+ * sessionDataMap singleton of SessionData.sys.mjs.
*
* @returns {Map.<string, Array<SessionDataItem>>}
* Map of session id to arrays of SessionDataItems.
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
index f7b2279018..3022744e7c 100644
--- a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/retry.sys.mjs
+++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/retry.sys.mjs
@@ -27,7 +27,7 @@ class RetryModule extends Module {
// processes.
const uri = this.messageHandler.window.document.baseURI;
if (!uri.includes("example.net")) {
- await new Promise(r => {});
+ await new Promise(() => {});
}
return { ...params };
@@ -37,7 +37,7 @@ class RetryModule extends Module {
async blockedOneTime(params) {
callsToBlockedOneTime++;
if (callsToBlockedOneTime < 2) {
- await new Promise(r => {});
+ await new Promise(() => {});
}
// Return:
@@ -51,7 +51,7 @@ class RetryModule extends Module {
async blockedTenTimes(params) {
callsToBlockedTenTimes++;
if (callsToBlockedTenTimes < 11) {
- await new Promise(r => {});
+ await new Promise(() => {});
}
// Return:
@@ -65,7 +65,7 @@ class RetryModule extends Module {
async blockedElevenTimes(params) {
callsToBlockedElevenTimes++;
if (callsToBlockedElevenTimes < 12) {
- await new Promise(r => {});
+ await new Promise(() => {});
}
// Return:
diff --git a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/windowglobaltoroot.sys.mjs b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/windowglobaltoroot.sys.mjs
index 815a836d9c..1d9238f1bc 100644
--- a/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/windowglobaltoroot.sys.mjs
+++ b/remote/shared/messagehandler/test/browser/resources/modules/windowglobal/windowglobaltoroot.sys.mjs
@@ -17,7 +17,7 @@ class WindowGlobalToRootModule extends Module {
* Commands
*/
- testHandleCommandToRoot(params, destination) {
+ testHandleCommandToRoot() {
return this.messageHandler.handleCommand({
moduleName: "windowglobaltoroot",
commandName: "getValueFromRoot",
@@ -27,7 +27,7 @@ class WindowGlobalToRootModule extends Module {
});
}
- testSendRootCommand(params, destination) {
+ testSendRootCommand() {
return this.messageHandler.sendRootCommand({
moduleName: "windowglobaltoroot",
commandName: "getValueFromRoot",
diff --git a/remote/shared/test/browser/browser_UserContextManager.js b/remote/shared/test/browser/browser_UserContextManager.js
index 2060c2bacd..cfae75dbe2 100644
--- a/remote/shared/test/browser/browser_UserContextManager.js
+++ b/remote/shared/test/browser/browser_UserContextManager.js
@@ -159,8 +159,9 @@ add_task(async function test_several_managers() {
"manager2 has a valid id for the user context created by manager 1"
);
- ok(
- contextId1 != contextId2,
+ Assert.notEqual(
+ contextId1,
+ contextId2,
"manager1 and manager2 have different ids for the same internal context id"
);
diff --git a/remote/shared/test/xpcshell/test_RecommendedPreferences.js b/remote/shared/test/xpcshell/test_RecommendedPreferences.js
index 20de07a528..88dc717be8 100644
--- a/remote/shared/test/xpcshell/test_RecommendedPreferences.js
+++ b/remote/shared/test/xpcshell/test_RecommendedPreferences.js
@@ -76,6 +76,11 @@ add_task(async function test_disabled() {
add_task(async function test_noCustomPreferences() {
info("Applying preferences without any custom preference should not throw");
+
+ // First call invokes setting of default preferences
+ RecommendedPreferences.applyPreferences();
+
+ // Second call does nothing
RecommendedPreferences.applyPreferences();
cleanup();
diff --git a/remote/shared/test/xpcshell/test_Sync.js b/remote/shared/test/xpcshell/test_Sync.js
index de4a4d30fe..a85c47adc2 100644
--- a/remote/shared/test/xpcshell/test_Sync.js
+++ b/remote/shared/test/xpcshell/test_Sync.js
@@ -50,14 +50,14 @@ class MockElement {
}
}
- dispatchEvent(event) {
+ dispatchEvent() {
if (this.wantUntrusted) {
this.untrusted = true;
}
this.click();
}
- removeEventListener(name, func) {
+ removeEventListener() {
this.capture = false;
this.eventName = null;
this.func = null;
@@ -213,12 +213,12 @@ add_task(async function test_EventPromise_checkFnCallback() {
{ checkFn: null, expected_count: 0 },
{ checkFn: undefined, expected_count: 0 },
{
- checkFn: event => {
+ checkFn: () => {
throw new Error("foo");
},
expected_count: 0,
},
- { checkFn: event => count++ > 0, expected_count: 2 },
+ { checkFn: () => count++ > 0, expected_count: 2 },
];
for (const { checkFn, expected_count } of data) {
@@ -417,7 +417,7 @@ add_task(async function test_PollPromise_resolve() {
const timeout = 100;
await new PollPromise(
- (resolve, reject) => {
+ resolve => {
resolve();
},
{ timeout, errorMessage }
diff --git a/remote/shared/webdriver/Actions.sys.mjs b/remote/shared/webdriver/Actions.sys.mjs
index 4f5a41a421..2639c4dc9f 100644
--- a/remote/shared/webdriver/Actions.sys.mjs
+++ b/remote/shared/webdriver/Actions.sys.mjs
@@ -13,7 +13,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
clearTimeout: "resource://gre/modules/Timer.sys.mjs",
dom: "chrome://remote/content/shared/DOM.sys.mjs",
error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs",
- event: "chrome://remote/content/marionette/event.sys.mjs",
+ event: "chrome://remote/content/shared/webdriver/Event.sys.mjs",
keyData: "chrome://remote/content/shared/webdriver/KeyData.sys.mjs",
Log: "chrome://remote/content/shared/Log.sys.mjs",
pprint: "chrome://remote/content/shared/Format.sys.mjs",
@@ -508,11 +508,8 @@ class Origin {
* Viewport coordinates of the origin of this coordinate system.
*
* This is overridden in subclasses to provide a class-specific origin.
- *
- * @param {InputSource} inputSource - State of current input device.
- * @param {WindowProxy} win - Current window global
*/
- getOriginCoordinates(inputSource, win) {
+ getOriginCoordinates() {
throw new Error(
`originCoordinates not defined for ${this.constructor.name}`
);
@@ -559,13 +556,13 @@ class Origin {
}
class ViewportOrigin extends Origin {
- getOriginCoordinates(inputSource, win) {
+ getOriginCoordinates() {
return { x: 0, y: 0 };
}
}
class PointerOrigin extends Origin {
- getOriginCoordinates(inputSource, win) {
+ getOriginCoordinates(inputSource) {
return { x: inputSource.x, y: inputSource.y };
}
}
@@ -624,13 +621,9 @@ class Action {
* This is overridden by subclasses to implement the type-specific
* dispatch of the action.
*
- * @param {State} state - Actions state.
- * @param {InputSource} inputSource - State of the current input device.
- * @param {number} tickDuration - Length of the current tick, in ms.
- * @param {WindowProxy} win - Current window global.
* @returns {Promise} - Promise that is resolved once the action is complete.
*/
- dispatch(state, inputSource, tickDuration, win) {
+ dispatch() {
throw new Error(
`Action subclass ${this.constructor.name} must override dispatch()`
);
@@ -708,10 +701,9 @@ class PauseAction extends NullAction {
* @param {State} state - Actions state.
* @param {InputSource} inputSource - State of the current input device.
* @param {number} tickDuration - Length of the current tick, in ms.
- * @param {WindowProxy} win - Current window global.
* @returns {Promise} - Promise that is resolved once the action is complete.
*/
- dispatch(state, inputSource, tickDuration, win) {
+ dispatch(state, inputSource, tickDuration) {
const ms = this.duration ?? tickDuration;
lazy.logger.trace(
@@ -1416,15 +1408,9 @@ class TouchActionGroup {
* This is overridden by subclasses to implement the type-specific
* dispatch of the action.
*
- * @param {State} state - Actions state.
- * @param {null} inputSource
- * This is always null; the argument only exists for compatibility
- * with {@link Action.dispatch}.
- * @param {number} tickDuration - Length of the current tick, in ms.
- * @param {WindowProxy} win - Current window global.
* @returns {Promise} - Promise that is resolved once the action is complete.
*/
- dispatch(state, inputSource, tickDuration, win) {
+ dispatch() {
throw new Error(
"TouchActionGroup subclass missing dispatch implementation"
);
@@ -1622,7 +1608,7 @@ class PointerMoveTouchActionGroup extends TouchActionGroup {
}
);
const reachedTarget = perPointerData.every(
- ([inputSource, action, target]) =>
+ ([inputSource, , target]) =>
target[0] === inputSource.x && target[1] === inputSource.y
);
@@ -1778,38 +1764,22 @@ class Pointer {
/**
* Implementation of depressing the pointer.
- *
- * @param {State} state - Actions state.
- * @param {InputSource} inputSource - State of the current input device.
- * @param {Action} action - The Action object invoking the pointer
- * @param {WindowProxy} win - Current window global.
*/
- pointerDown(state, inputSource, action, win) {
+ pointerDown() {
throw new Error(`Unimplemented pointerDown for pointerType ${this.type}`);
}
/**
* Implementation of releasing the pointer.
- *
- * @param {State} state - Actions state.
- * @param {InputSource} inputSource - State of the current input device.
- * @param {Action} action - The Action object invoking the pointer
- * @param {WindowProxy} win - Current window global.
*/
- pointerUp(state, inputSource, action, win) {
+ pointerUp() {
throw new Error(`Unimplemented pointerUp for pointerType ${this.type}`);
}
/**
* Implementation of moving the pointer.
- *
- * @param {State} state - Actions state.
- * @param {InputSource} inputSource - State of the current input device.
- * @param {number} targetX - Target X coordinate of the pointer move
- * @param {number} targetY - Target Y coordinate of the pointer move
- * @param {WindowProxy} win - Current window global.
*/
- pointerMove(state, inputSource, targetX, targetY, win) {
+ pointerMove() {
throw new Error(`Unimplemented pointerMove for pointerType ${this.type}`);
}
@@ -2138,11 +2108,8 @@ class InputEventData {
/**
* Update the input data based on global and input state
- *
- * @param {State} state - Actions state.
- * @param {InputSource} inputSource - State of the current input device.
*/
- update(state, inputSource) {}
+ update() {}
toString() {
return `${this.constructor.name} ${JSON.stringify(this)}`;
diff --git a/remote/shared/webdriver/Capabilities.sys.mjs b/remote/shared/webdriver/Capabilities.sys.mjs
index e3761315f2..3c30ea0789 100644
--- a/remote/shared/webdriver/Capabilities.sys.mjs
+++ b/remote/shared/webdriver/Capabilities.sys.mjs
@@ -445,6 +445,12 @@ export class Capabilities extends Map {
["timeouts", new Timeouts()],
["strictFileInteractability", false],
["unhandledPromptBehavior", UnhandledPromptBehavior.DismissAndNotify],
+ [
+ "userAgent",
+ Cc["@mozilla.org/network/protocol;1?name=http"].getService(
+ Ci.nsIHttpProtocolHandler
+ ).userAgent,
+ ],
["webSocketUrl", null],
// proprietary
diff --git a/remote/shared/webdriver/Errors.sys.mjs b/remote/shared/webdriver/Errors.sys.mjs
index 53b9d4426b..7060131075 100644
--- a/remote/shared/webdriver/Errors.sys.mjs
+++ b/remote/shared/webdriver/Errors.sys.mjs
@@ -41,6 +41,7 @@ const ERRORS = new Set([
"TimeoutError",
"UnableToCaptureScreen",
"UnableToSetCookieError",
+ "UnableToSetFileInputError",
"UnexpectedAlertOpenError",
"UnknownCommandError",
"UnknownError",
@@ -757,6 +758,21 @@ class UnableToSetCookieError extends WebDriverError {
}
/**
+ * A command to set a file could not be satisfied.
+ *
+ * @param {string=} message
+ * Optional string describing error situation.
+ * @param {object=} data
+ * Additional error data helpful in diagnosing the error.
+ */
+class UnableToSetFileInputError extends WebDriverError {
+ constructor(message, data = {}) {
+ super(message, data);
+ this.status = "unable to set file input";
+ }
+}
+
+/**
* A command to capture a screenshot could not be satisfied.
*
* @param {string=} message
@@ -865,6 +881,7 @@ const STATUSES = new Map([
["timeout", TimeoutError],
["unable to capture screen", UnableToCaptureScreen],
["unable to set cookie", UnableToSetCookieError],
+ ["unable to set file input", UnableToSetFileInputError],
["unexpected alert open", UnexpectedAlertOpenError],
["unknown command", UnknownCommandError],
["unknown error", UnknownError],
diff --git a/remote/shared/webdriver/Event.sys.mjs b/remote/shared/webdriver/Event.sys.mjs
new file mode 100644
index 0000000000..2240f1f2b2
--- /dev/null
+++ b/remote/shared/webdriver/Event.sys.mjs
@@ -0,0 +1,295 @@
+/* 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/. */
+
+/* eslint-disable no-restricted-globals */
+
+const lazy = {};
+
+ChromeUtils.defineESModuleGetters(lazy, {
+ keyData: "chrome://remote/content/shared/webdriver/KeyData.sys.mjs",
+});
+
+/** Provides functionality for creating and sending DOM events. */
+export const event = {};
+
+const _eventUtils = new WeakMap();
+
+function _getEventUtils(win) {
+ if (!_eventUtils.has(win)) {
+ const eventUtilsObject = {
+ window: win,
+ parent: win,
+ _EU_Ci: Ci,
+ _EU_Cc: Cc,
+ };
+ Services.scriptloader.loadSubScript(
+ "chrome://remote/content/external/EventUtils.js",
+ eventUtilsObject
+ );
+ _eventUtils.set(win, eventUtilsObject);
+ }
+ return _eventUtils.get(win);
+}
+
+event.MouseEvents = {
+ click: 0,
+ dblclick: 1,
+ mousedown: 2,
+ mouseup: 3,
+ mouseover: 4,
+ mouseout: 5,
+};
+
+event.Modifiers = {
+ shiftKey: 0,
+ ctrlKey: 1,
+ altKey: 2,
+ metaKey: 3,
+};
+
+event.MouseButton = {
+ isPrimary(button) {
+ return button === 0;
+ },
+ isAuxiliary(button) {
+ return button === 1;
+ },
+ isSecondary(button) {
+ return button === 2;
+ },
+};
+
+/**
+ * Synthesise a mouse event at a point.
+ *
+ * If the type is specified in opts, an mouse event of that type is
+ * fired. Otherwise, a mousedown followed by a mouseup is performed.
+ *
+ * @param {number} left
+ * Offset from viewport left, in CSS pixels
+ * @param {number} top
+ * Offset from viewport top, in CSS pixels
+ * @param {object} opts
+ * Object which may contain the properties "shiftKey", "ctrlKey",
+ * "altKey", "metaKey", "accessKey", "clickCount", "button", and
+ * "type".
+ * @param {Window} win
+ * Window object.
+ *
+ * @returns {boolean} defaultPrevented
+ */
+event.synthesizeMouseAtPoint = function (left, top, opts, win) {
+ return _getEventUtils(win).synthesizeMouseAtPoint(left, top, opts, win);
+};
+
+/**
+ * Synthesise a touch event at a point.
+ *
+ * If the type is specified in opts, a touch event of that type is
+ * fired. Otherwise, a touchstart followed by a touchend is performed.
+ *
+ * @param {number} left
+ * Offset from viewport left, in CSS pixels
+ * @param {number} top
+ * Offset from viewport top, in CSS pixels
+ * @param {object} opts
+ * Object which may contain the properties "id", "rx", "ry", "angle",
+ * "force", "shiftKey", "ctrlKey", "altKey", "metaKey", "accessKey",
+ * "type".
+ * @param {Window} win
+ * Window object.
+ *
+ * @returns {boolean} defaultPrevented
+ */
+event.synthesizeTouchAtPoint = function (left, top, opts, win) {
+ return _getEventUtils(win).synthesizeTouchAtPoint(left, top, opts, win);
+};
+
+/**
+ * Synthesise a wheel scroll event at a point.
+ *
+ * @param {number} left
+ * Offset from viewport left, in CSS pixels
+ * @param {number} top
+ * Offset from viewport top, in CSS pixels
+ * @param {object} opts
+ * Object which may contain the properties "shiftKey", "ctrlKey",
+ * "altKey", "metaKey", "accessKey", "deltaX", "deltaY", "deltaZ",
+ * "deltaMode", "lineOrPageDeltaX", "lineOrPageDeltaY", "isMomentum",
+ * "isNoLineOrPageDelta", "isCustomizedByPrefs", "expectedOverflowDeltaX",
+ * "expectedOverflowDeltaY"
+ * @param {Window} win
+ * Window object.
+ */
+event.synthesizeWheelAtPoint = function (left, top, opts, win) {
+ const dpr = win.devicePixelRatio;
+
+ // All delta properties expect the value in device pixels while the
+ // WebDriver specification uses CSS pixels.
+ if (typeof opts.deltaX !== "undefined") {
+ opts.deltaX *= dpr;
+ }
+ if (typeof opts.deltaY !== "undefined") {
+ opts.deltaY *= dpr;
+ }
+ if (typeof opts.deltaZ !== "undefined") {
+ opts.deltaZ *= dpr;
+ }
+
+ return _getEventUtils(win).synthesizeWheelAtPoint(left, top, opts, win);
+};
+
+event.synthesizeMultiTouch = function (opts, win) {
+ const modifiers = _getEventUtils(win)._parseModifiers(opts);
+ win.windowUtils.sendTouchEvent(
+ opts.type,
+ opts.id,
+ opts.x,
+ opts.y,
+ opts.rx,
+ opts.ry,
+ opts.angle,
+ opts.force,
+ opts.tiltx,
+ opts.tilty,
+ opts.twist,
+ modifiers
+ );
+};
+
+/**
+ * Synthesize a keydown event for a single key.
+ *
+ * @param {object} key
+ * Key data as returned by keyData.getData
+ * @param {Window} win
+ * Window object.
+ */
+event.sendKeyDown = function (key, win) {
+ event.sendSingleKey(key, win, "keydown");
+};
+
+/**
+ * Synthesize a keyup event for a single key.
+ *
+ * @param {object} key
+ * Key data as returned by keyData.getData
+ * @param {Window} win
+ * Window object.
+ */
+event.sendKeyUp = function (key, win) {
+ event.sendSingleKey(key, win, "keyup");
+};
+
+/**
+ * Synthesize a key event for a single key.
+ *
+ * @param {object} key
+ * Key data as returned by keyData.getData
+ * @param {Window} win
+ * Window object.
+ * @param {string=} type
+ * Event to emit. By default the full keydown/keypressed/keyup event
+ * sequence is emitted.
+ */
+event.sendSingleKey = function (key, win, type = null) {
+ let keyValue = key.key;
+ if (!key.printable) {
+ keyValue = `KEY_${keyValue}`;
+ }
+ const event = {
+ code: key.code,
+ location: key.location,
+ altKey: key.altKey ?? false,
+ shiftKey: key.shiftKey ?? false,
+ ctrlKey: key.ctrlKey ?? false,
+ metaKey: key.metaKey ?? false,
+ repeat: key.repeat ?? false,
+ };
+ if (type) {
+ event.type = type;
+ }
+ _getEventUtils(win).synthesizeKey(keyValue, event, win);
+};
+
+/**
+ * Send a string as a series of keypresses.
+ *
+ * @param {string} keyString
+ * Sequence of characters to send as key presses
+ * @param {Window} win
+ * Window object
+ */
+event.sendKeys = function (keyString, win) {
+ const modifiers = {};
+ for (let modifier in event.Modifiers) {
+ modifiers[modifier] = false;
+ }
+
+ for (let keyValue of keyString) {
+ // keyValue will contain enough to represent the UTF-16 encoding of a single abstract character
+ // i.e. either a single scalar value, or a surrogate pair
+ if (modifiers.shiftKey) {
+ keyValue = lazy.keyData.getShiftedKey(keyValue);
+ }
+ const data = lazy.keyData.getData(keyValue);
+ const key = { ...data, ...modifiers };
+ if (data.modifier) {
+ // Negating the state of the modifier here is not spec compliant but
+ // makes us compatible to Chrome's behavior for now. That's fine unless
+ // we know the correct behavior.
+ //
+ // @see: https://github.com/w3c/webdriver/issues/1734
+ modifiers[data.modifier] = !modifiers[data.modifier];
+ }
+ event.sendSingleKey(key, win);
+ }
+};
+
+event.sendEvent = function (eventType, el, modifiers = {}, opts = {}) {
+ opts.canBubble = opts.canBubble || true;
+
+ let doc = el.ownerDocument || el.document;
+ let ev = doc.createEvent("Event");
+
+ ev.shiftKey = modifiers.shift;
+ ev.metaKey = modifiers.meta;
+ ev.altKey = modifiers.alt;
+ ev.ctrlKey = modifiers.ctrl;
+
+ ev.initEvent(eventType, opts.canBubble, true);
+ el.dispatchEvent(ev);
+};
+
+event.mouseover = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("mouseover", el, modifiers, opts);
+};
+
+event.mousemove = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("mousemove", el, modifiers, opts);
+};
+
+event.mousedown = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("mousedown", el, modifiers, opts);
+};
+
+event.mouseup = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("mouseup", el, modifiers, opts);
+};
+
+event.cancel = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("cancel", el, modifiers, opts);
+};
+
+event.click = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("click", el, modifiers, opts);
+};
+
+event.change = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("change", el, modifiers, opts);
+};
+
+event.input = function (el, modifiers = {}, opts = {}) {
+ return event.sendEvent("input", el, modifiers, opts);
+};
diff --git a/remote/shared/webdriver/process-actors/WebDriverProcessDataChild.sys.mjs b/remote/shared/webdriver/process-actors/WebDriverProcessDataChild.sys.mjs
index 39db9d939e..8101240abe 100644
--- a/remote/shared/webdriver/process-actors/WebDriverProcessDataChild.sys.mjs
+++ b/remote/shared/webdriver/process-actors/WebDriverProcessDataChild.sys.mjs
@@ -17,7 +17,7 @@ class BrowsingContextObserver {
this.actor = actor;
}
- async observe(subject, topic, data) {
+ async observe(subject, topic) {
if (topic === "browsing-context-discarded") {
this.actor.cleanUp({ browsingContext: subject });
}
diff --git a/remote/shared/webdriver/test/xpcshell/test_Errors.js b/remote/shared/webdriver/test/xpcshell/test_Errors.js
index 22e3526039..d4803dee87 100644
--- a/remote/shared/webdriver/test/xpcshell/test_Errors.js
+++ b/remote/shared/webdriver/test/xpcshell/test_Errors.js
@@ -36,6 +36,7 @@ const errors = [
error.StaleElementReferenceError,
error.TimeoutError,
error.UnableToSetCookieError,
+ error.UnableToSetFileInputError,
error.UnexpectedAlertOpenError,
error.UnknownCommandError,
error.UnknownError,
@@ -510,6 +511,14 @@ add_task(function test_UnableToSetCookieError() {
ok(err instanceof error.WebDriverError);
});
+add_task(function test_UnableToSetFileInputError() {
+ let err = new error.UnableToSetFileInputError("foo");
+ equal("UnableToSetFileInputError", err.name);
+ equal("foo", err.message);
+ equal("unable to set file input", err.status);
+ ok(err instanceof error.WebDriverError);
+});
+
add_task(function test_UnexpectedAlertOpenError() {
let err = new error.UnexpectedAlertOpenError("foo");
equal("UnexpectedAlertOpenError", err.name);