Skip to content

Commit

Permalink
Bug 1785092 - [remote] Added Realm class for Windows and Sandboxes. r…
Browse files Browse the repository at this point in the history
…=webdriver-reviewers,jdescottes

Differential Revision: https://phabricator.services.mozilla.com/D154973
  • Loading branch information
whimboo committed Aug 19, 2022
1 parent e388e80 commit 63bb86f
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 133 deletions.
191 changes: 191 additions & 0 deletions remote/webdriver-bidi/Realm.jsm
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,
}
);
}
}
1 change: 1 addition & 0 deletions remote/webdriver-bidi/jar.mn
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ remote.jar:
% content remote %content/

content/webdriver-bidi/NewSessionHandler.jsm (NewSessionHandler.jsm)
content/webdriver-bidi/Realm.jsm (Realm.jsm)
content/webdriver-bidi/RemoteValue.jsm (RemoteValue.jsm)
content/webdriver-bidi/WebDriverBiDi.jsm (WebDriverBiDi.jsm)
content/webdriver-bidi/WebDriverBiDiConnection.jsm (WebDriverBiDiConnection.jsm)
Expand Down
2 changes: 1 addition & 1 deletion remote/webdriver-bidi/modules/root/script.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class ScriptModule extends Module {
}

#buildReturnValue(evaluationResult) {
const rv = { realm: evaluationResult.realm.realm };
const rv = { realm: evaluationResult.realmId };
switch (evaluationResult.evaluationStatus) {
// TODO: Compare with EvaluationStatus.Normal after Bug 1774444 is fixed.
case "normal":
Expand Down
Loading

0 comments on commit 63bb86f

Please sign in to comment.