summaryrefslogtreecommitdiffstats
path: root/remote/Error.jsm
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /remote/Error.jsm
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'remote/Error.jsm')
-rw-r--r--remote/Error.jsm137
1 files changed, 137 insertions, 0 deletions
diff --git a/remote/Error.jsm b/remote/Error.jsm
new file mode 100644
index 0000000000..d7a83400cb
--- /dev/null
+++ b/remote/Error.jsm
@@ -0,0 +1,137 @@
+/* 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 = [
+ "FatalError",
+ "RemoteAgentError",
+ "UnknownMethodError",
+ "UnsupportedError",
+];
+
+const { Log } = ChromeUtils.import("chrome://remote/content/Log.jsm");
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+const { XPCOMUtils } = ChromeUtils.import(
+ "resource://gre/modules/XPCOMUtils.jsm"
+);
+
+XPCOMUtils.defineLazyGetter(this, "log", Log.get);
+
+class RemoteAgentError extends Error {
+ constructor(message = "", cause = undefined) {
+ cause = cause || message;
+ super(cause);
+
+ this.name = this.constructor.name;
+ this.message = message;
+ this.cause = cause;
+
+ this.notify();
+ }
+
+ notify() {
+ Cu.reportError(this);
+ log.error(this.toString({ stack: true }));
+ }
+
+ toString({ stack = false } = {}) {
+ return RemoteAgentError.format(this, { stack });
+ }
+
+ static format(e, { stack = false } = {}) {
+ return formatError(e, { stack });
+ }
+
+ /**
+ * Takes a serialised CDP error and reconstructs it
+ * as a RemoteAgentError.
+ *
+ * The error must be of this form:
+ *
+ * {"message": "TypeError: foo is not a function\n
+ * execute@chrome://remote/content/sessions/Session.jsm:73:39\n
+ * onMessage@chrome://remote/content/sessions/TabSession.jsm:65:20"}
+ *
+ * This approach has the notable deficiency that it cannot deal
+ * with causes to errors because of the unstructured nature of CDP
+ * errors. A possible future improvement would be to extend the
+ * error serialisation to include discrete fields for each data
+ * property.
+ *
+ * @param {Object} json
+ * CDP error encoded as a JSON object, which must have a
+ * "message" field, where the first line will make out the error
+ * message and the subsequent lines the stacktrace.
+ *
+ * @return {RemoteAgentError}
+ */
+ static fromJSON(json) {
+ const [message, ...stack] = json.message.split("\n");
+ const err = new RemoteAgentError();
+ err.message = message.slice(0, -1);
+ err.stack = stack.map(s => s.trim()).join("\n");
+ err.cause = null;
+ return err;
+ }
+}
+
+/**
+ * A fatal error that it is not possible to recover from
+ * or send back to the client.
+ *
+ * Constructing this error will force the application to quit.
+ */
+class FatalError extends RemoteAgentError {
+ constructor(...args) {
+ super(...args);
+ this.quit();
+ }
+
+ notify() {
+ log.fatal(this.toString({ stack: true }));
+ }
+
+ quit(mode = Ci.nsIAppStartup.eForceQuit) {
+ Services.startup.quit(mode);
+ }
+}
+
+/** When an operation is not yet implemented. */
+class UnsupportedError extends RemoteAgentError {}
+
+/** The requested remote method does not exist. */
+class UnknownMethodError extends RemoteAgentError {
+ constructor(domain, command = null) {
+ if (command) {
+ super(`${domain}.${command}`);
+ } else {
+ super(domain);
+ }
+ }
+}
+
+function formatError(error, { stack = false } = {}) {
+ const els = [];
+
+ els.push(error.name);
+ if (error.message) {
+ els.push(": ");
+ els.push(error.message);
+ }
+
+ if (stack && error.stack) {
+ els.push(":\n");
+
+ const stack = error.stack.trim().split("\n");
+ els.push(stack.map(line => `\t${line}`).join("\n"));
+
+ if (error.cause) {
+ els.push("\n");
+ els.push("caused by: " + formatError(error.cause, { stack }));
+ }
+ }
+
+ return els.join("");
+}