tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GeckoViewConsole.sys.mjs (5011B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { GeckoViewUtils } from "resource://gre/modules/GeckoViewUtils.sys.mjs";
      6 
      7 const { debug, warn } = GeckoViewUtils.initLogging("Console");
      8 
      9 const lazy = {};
     10 
     11 ChromeUtils.defineLazyGetter(
     12  lazy,
     13  "l10n",
     14  () => new Localization(["mobile/android/geckoViewConsole.ftl"], true)
     15 );
     16 
     17 export var GeckoViewConsole = {
     18  _isEnabled: false,
     19 
     20  get enabled() {
     21    return this._isEnabled;
     22  },
     23 
     24  set enabled(aVal) {
     25    debug`enabled = ${aVal}`;
     26    if (!!aVal === this._isEnabled) {
     27      return;
     28    }
     29 
     30    this._isEnabled = !!aVal;
     31    const ConsoleAPIStorage = Cc[
     32      "@mozilla.org/consoleAPI-storage;1"
     33    ].getService(Ci.nsIConsoleAPIStorage);
     34    if (this._isEnabled) {
     35      this._consoleMessageListener = this._handleConsoleMessage.bind(this);
     36      ConsoleAPIStorage.addLogEventListener(
     37        this._consoleMessageListener,
     38        Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal)
     39      );
     40    } else if (this._consoleMessageListener) {
     41      ConsoleAPIStorage.removeLogEventListener(this._consoleMessageListener);
     42      delete this._consoleMessageListener;
     43    }
     44  },
     45 
     46  observe(aSubject, aTopic, aData) {
     47    if (aTopic == "nsPref:changed") {
     48      this.enabled = Services.prefs.getBoolPref(aData, false);
     49    }
     50  },
     51 
     52  _handleConsoleMessage(aMessage) {
     53    aMessage = aMessage.wrappedJSObject;
     54 
     55    const mappedArguments = Array.from(
     56      aMessage.arguments,
     57      this.formatResult,
     58      this
     59    );
     60    const joinedArguments = mappedArguments.join(" ");
     61 
     62    if (aMessage.level == "error" || aMessage.level == "warn") {
     63      const flag =
     64        aMessage.level == "error"
     65          ? Ci.nsIScriptError.errorFlag
     66          : Ci.nsIScriptError.warningFlag;
     67      const consoleMsg = Cc["@mozilla.org/scripterror;1"].createInstance(
     68        Ci.nsIScriptError
     69      );
     70      consoleMsg.init(joinedArguments, null, 0, 0, flag, "content javascript");
     71      Services.console.logMessage(consoleMsg);
     72    } else if (aMessage.level == "trace") {
     73      const args = aMessage.arguments;
     74      const msgDetails = args[0] ?? aMessage;
     75      const filename = this.abbreviateSourceURL(msgDetails.filename);
     76      const functionName =
     77        msgDetails.functionName ||
     78        lazy.l10n.formatValueSync("console-stacktrace-anonymous-function");
     79 
     80      let body = lazy.l10n.formatValueSync("console-stacktrace", {
     81        filename,
     82        functionName,
     83        lineNumber: msgDetails.lineNumber ?? "",
     84      });
     85      body += "\n";
     86      for (const aFrame of args) {
     87        const functionName =
     88          aFrame.functionName ||
     89          lazy.l10n.formatValueSync("console-stacktrace-anonymous-function");
     90        body += `  ${aFrame.filename} :: ${functionName} :: ${aFrame.lineNumber}\n`;
     91      }
     92 
     93      Services.console.logStringMessage(body);
     94    } else if (aMessage.level == "time" && aMessage.arguments) {
     95      const body = lazy.l10n.formatValueSync("console-timer-start", {
     96        name: aMessage.arguments.name ?? "",
     97      });
     98      Services.console.logStringMessage(body);
     99    } else if (aMessage.level == "timeEnd" && aMessage.arguments) {
    100      const body = lazy.l10n.formatValueSync("console-timer-end", {
    101        name: aMessage.arguments.name ?? "",
    102        duration: aMessage.arguments.duration ?? "",
    103      });
    104      Services.console.logStringMessage(body);
    105    } else if (
    106      ["group", "groupCollapsed", "groupEnd"].includes(aMessage.level)
    107    ) {
    108      // Do nothing yet
    109    } else {
    110      Services.console.logStringMessage(joinedArguments);
    111    }
    112  },
    113 
    114  getResultType(aResult) {
    115    let type = aResult === null ? "null" : typeof aResult;
    116    if (type == "object" && aResult.constructor && aResult.constructor.name) {
    117      type = aResult.constructor.name;
    118    }
    119    return type.toLowerCase();
    120  },
    121 
    122  formatResult(aResult) {
    123    let output = "";
    124    const type = this.getResultType(aResult);
    125    switch (type) {
    126      case "string":
    127      case "boolean":
    128      case "date":
    129      case "error":
    130      case "number":
    131      case "regexp":
    132        output = aResult.toString();
    133        break;
    134      case "null":
    135      case "undefined":
    136        output = type;
    137        break;
    138      default:
    139        output = aResult.toString();
    140        break;
    141    }
    142 
    143    return output;
    144  },
    145 
    146  abbreviateSourceURL(aSourceURL) {
    147    // Remove any query parameters.
    148    const hookIndex = aSourceURL.indexOf("?");
    149    if (hookIndex > -1) {
    150      aSourceURL = aSourceURL.substring(0, hookIndex);
    151    }
    152 
    153    // Remove a trailing "/".
    154    if (aSourceURL[aSourceURL.length - 1] == "/") {
    155      aSourceURL = aSourceURL.substring(0, aSourceURL.length - 1);
    156    }
    157 
    158    // Remove all but the last path component.
    159    const slashIndex = aSourceURL.lastIndexOf("/");
    160    if (slashIndex > -1) {
    161      aSourceURL = aSourceURL.substring(slashIndex + 1);
    162    }
    163 
    164    return aSourceURL;
    165  },
    166 };