forked from mozilla/gecko-dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1785092 - [remote] Added Realm class for Windows and Sandboxes. r…
…=webdriver-reviewers,jdescottes Differential Revision: https://phabricator.services.mozilla.com/D154973
- Loading branch information
Showing
4 changed files
with
238 additions
and
133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
/* 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 = ["WindowRealm"]; | ||
|
||
const { XPCOMUtils } = ChromeUtils.importESModule( | ||
"resource://gre/modules/XPCOMUtils.sys.mjs" | ||
); | ||
|
||
const lazy = {}; | ||
XPCOMUtils.defineLazyModuleGetters(lazy, { | ||
addDebuggerToGlobal: "resource://gre/modules/jsdebugger.jsm", | ||
}); | ||
|
||
XPCOMUtils.defineLazyGetter(lazy, "dbg", () => { | ||
// eslint-disable-next-line mozilla/reject-globalThis-modification | ||
lazy.addDebuggerToGlobal(globalThis); | ||
return new Debugger(); | ||
}); | ||
|
||
/** | ||
* @typedef {string} RealmType | ||
**/ | ||
|
||
/** | ||
* Enum of realm types. | ||
* | ||
* @readonly | ||
* @enum {RealmType} | ||
**/ | ||
const RealmType = { | ||
AudioWorklet: "audio-worklet", | ||
DedicatedWorker: "dedicated-worker", | ||
PaintWorklet: "paint-worklet", | ||
ServiceWorker: "service-worker", | ||
SharedWorker: "shared-worker", | ||
Window: "window", | ||
Worker: "worker", | ||
Worklet: "worklet", | ||
}; | ||
|
||
/** | ||
* Base class that wraps any kind of WebDriver BiDi realm. | ||
*/ | ||
class Realm { | ||
#id; | ||
|
||
constructor() { | ||
this.#id = Services.uuid | ||
.generateUUID() | ||
.toString() | ||
.slice(1, -1); | ||
} | ||
|
||
/** | ||
* Get the unique identifier of the realm instance. | ||
* | ||
* @return {string} The unique identifier. | ||
*/ | ||
get id() { | ||
return this.#id; | ||
} | ||
} | ||
|
||
/** | ||
* Wrapper for Window realms including sandbox objects. | ||
*/ | ||
class WindowRealm extends Realm { | ||
#globalObject; | ||
#globalObjectReference; | ||
#window; | ||
|
||
static type = RealmType.Window; | ||
|
||
/** | ||
* | ||
* @param {Window} window | ||
* The window global to wrap. | ||
* @param {Object} options | ||
* @param {string=} options.sandboxName | ||
* Name of the sandbox to create if specified. Defaults to `null`. | ||
*/ | ||
constructor(window, options = {}) { | ||
const { sandboxName = null } = options; | ||
|
||
super(); | ||
|
||
this.#window = window; | ||
this.#globalObject = | ||
sandboxName === null ? this.#window : this.#createSandbox(); | ||
this.#globalObjectReference = lazy.dbg.makeGlobalObjectReference( | ||
this.#globalObject | ||
); | ||
|
||
lazy.dbg.enableAsyncStack(this.#globalObject); | ||
} | ||
|
||
destroy() { | ||
lazy.dbg.disableAsyncStack(this.#globalObject); | ||
|
||
this.#globalObjectReference = null; | ||
this.#globalObject = null; | ||
this.#window = null; | ||
} | ||
|
||
get globalObjectReference() { | ||
return this.#globalObjectReference; | ||
} | ||
|
||
#cloneAsDebuggerObject(obj) { | ||
// To use an object created in the priviledged Debugger compartment from | ||
// the content compartment, we need to first clone it into the target | ||
// compartment and then retrieve the corresponding Debugger.Object wrapper. | ||
const proxyObject = Cu.cloneInto( | ||
obj, | ||
this.#globalObjectReference.unsafeDereference() | ||
); | ||
|
||
return this.#globalObjectReference.makeDebuggeeValue(proxyObject); | ||
} | ||
|
||
#createSandbox() { | ||
const win = this.#window; | ||
const opts = { | ||
sameZoneAs: win, | ||
sandboxPrototype: win, | ||
wantComponents: false, | ||
wantXrays: true, | ||
}; | ||
|
||
return new Cu.Sandbox(win, opts); | ||
} | ||
|
||
/** | ||
* Evaluates a provided expression in the context of the current realm. | ||
* | ||
* @param {string} expression | ||
* The expression to evaluate. | ||
* | ||
* @return {Object} | ||
* - evaluationStatus {EvaluationStatus} One of "normal", "throw". | ||
* - exceptionDetails {ExceptionDetails=} the details of the exception if | ||
* the evaluation status was "throw". | ||
* - result {RemoteValue=} the result of the evaluation serialized as a | ||
* RemoteValue if the evaluation status was "normal". | ||
*/ | ||
executeInGlobal(expression) { | ||
return this.#globalObjectReference.executeInGlobal(expression, { | ||
url: this.#window.document.baseURI, | ||
}); | ||
} | ||
|
||
/** | ||
* Call a function in the context of the current realm. | ||
* | ||
* @param {string} functionDeclaration | ||
* The body of the function to call. | ||
* @param {Array<Object>} functionArguments | ||
* The arguments to pass to the function call. | ||
* @param {Object} thisParameter | ||
* The value of the `this` keyword for the function call. | ||
* | ||
* @return {Object} | ||
* - evaluationStatus {EvaluationStatus} One of "normal", "throw". | ||
* - exceptionDetails {ExceptionDetails=} the details of the exception if | ||
* the evaluation status was "throw". | ||
* - result {RemoteValue=} the result of the evaluation serialized as a | ||
* RemoteValue if the evaluation status was "normal". | ||
*/ | ||
executeInGlobalWithBindings( | ||
functionDeclaration, | ||
functionArguments, | ||
thisParameter | ||
) { | ||
const expression = `(${functionDeclaration}).apply(__bidi_this, __bidi_args)`; | ||
|
||
return this.#globalObjectReference.executeInGlobalWithBindings( | ||
expression, | ||
{ | ||
__bidi_args: this.#cloneAsDebuggerObject(functionArguments), | ||
__bidi_this: this.#cloneAsDebuggerObject(thisParameter), | ||
}, | ||
{ | ||
url: this.#window.document.baseURI, | ||
} | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.