Example #1
0
exports['test deprecated shared globals exception name'] = function(assert) {
  let uri = root + '/fixtures/loader/cycles/';
  let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
                        sharedGlobalBlacklist: ['b'] });

  let program = main(loader, 'main');

  assert.ok(loader.sharedGlobalBlocklist.includes("b"), "b should be in the blocklist");
  assert.equal(loader.sharedGlobalBlocklist.length, loader.sharedGlobalBlacklist.length,
               "both blocklists should have the same number of items.");
  assert.equal(loader.sharedGlobalBlocklist.join(","), loader.sharedGlobalBlacklist.join(","),
               "both blocklists should have the same items.");

  // As it is hard to verify what is the global of an object
  // (due to wrappers) we check that we see the `foo` symbol
  // being manually injected into the shared global object
  loader.sharedGlobalSandbox.foo = true;

  let m = loader.sandboxes[uri + 'main.js'];
  let a = loader.sandboxes[uri + 'a.js'];
  let b = loader.sandboxes[uri + 'b.js'];

  assert.ok(Cu.getGlobalForObject(m).foo, "main is shared");
  assert.ok(Cu.getGlobalForObject(a).foo, "a is shared");
  assert.ok(!Cu.getGlobalForObject(b).foo, "b isn't shared");

  unload(loader);
}
Example #2
0
exports.isSafeJSObject = function isSafeJSObject(aObj) {
  if (Cu.getGlobalForObject(aObj) ==
      Cu.getGlobalForObject(exports.isSafeJSObject)) {
    return true; // aObj is not a cross-compartment wrapper.
  }

  let principal = Services.scriptSecurityManager.getObjectPrincipal(aObj);
  if (Services.scriptSecurityManager.isSystemPrincipal(principal)) {
    return true; // allow chrome objects
  }

  return Cu.isXrayWrapper(aObj);
};
Example #3
0
  function TypedArray({obj, hooks}, grip) {
    if (!ObjectUtils.isTypedArray(obj)) {
      return false;
    }

    grip.preview = {
      kind: "ArrayLike",
      length: ObjectUtils.getArrayLength(obj),
    };

    if (hooks.getGripDepth() > 1) {
      return true;
    }

    let raw = obj.unsafeDereference();
    let global = Cu.getGlobalForObject(DebuggerServer);
    let classProto = global[obj.class].prototype;
    // The Xray machinery for TypedArrays denies indexed access on the grounds
    // that it's slow, and advises callers to do a structured clone instead.
    let safeView = Cu.cloneInto(classProto.subarray.call(raw, 0,
      OBJECT_PREVIEW_MAX_ITEMS), global);
    let items = grip.preview.items = [];
    for (let i = 0; i < safeView.length; i++) {
      items.push(safeView[i]);
    }

    return true;
  },
Example #4
0
  getCustomElementLocation: function() {
    // Get a reference to the custom element definition function.
    const name = this.rawNode.localName;

    const customElementsRegistry = this.rawNode.ownerGlobal.customElements;
    const customElement = customElementsRegistry && customElementsRegistry.get(name);
    if (!customElement) {
      return undefined;
    }
    // Create debugger object for the customElement function.
    const global = Cu.getGlobalForObject(customElement);
    const dbg = this.parent().targetActor.makeDebugger();
    const globalDO = dbg.addDebuggee(global);
    const customElementDO = globalDO.makeDebuggeeValue(customElement);

    // Return undefined if we can't find a script for the custom element definition.
    if (!customElementDO.script) {
      return undefined;
    }

    return {
      url: customElementDO.script.url,
      line: customElementDO.script.startLine,
    };
  },
Example #5
0
/**
 * Casts TypedArray to a normal array via a
 * new scope.
 */
function castToArray(typedArray) {
  // The Xray machinery for TypedArrays denies indexed access on the grounds
  // that it's slow, and advises callers to do a structured clone instead.
  let global = Cu.getGlobalForObject(this);
  let safeView = Cu.cloneInto(typedArray.subarray(), global);
  return copyInto([], safeView);
}
Example #6
0
defineLazyGetter(exports.modules, "Debugger", () => {
  const global = Cu.getGlobalForObject(this);
  // Debugger may already have been added by RecordReplayControl getter
  if (global.Debugger) {
    return global.Debugger;
  }
  const { addDebuggerToGlobal } = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm", {});
  addDebuggerToGlobal(global);
  return global.Debugger;
});
Example #7
0
exports.isSafeJSObject = function isSafeJSObject(aObj) {
  // If we are running on a worker thread, Cu is not available. In this case,
  // we always return false, just to be on the safe side.
  if (isWorker) {
    return false;
  }

  if (Cu.getGlobalForObject(aObj) ==
      Cu.getGlobalForObject(exports.isSafeJSObject)) {
    return true; // aObj is not a cross-compartment wrapper.
  }

  let principal = Cu.getObjectPrincipal(aObj);
  if (Services.scriptSecurityManager.isSystemPrincipal(principal)) {
    return true; // allow chrome objects
  }

  return Cu.isXrayWrapper(aObj);
};
Example #8
0
defineLazyGetter(exports.modules, "RecordReplayControl", () => {
  // addDebuggerToGlobal also adds the RecordReplayControl object.
  const global = Cu.getGlobalForObject(this);
  // RecordReplayControl may already have been added by Debugger getter
  if (global.RecordReplayControl) {
    return global.RecordReplayControl;
  }
  const { addDebuggerToGlobal } = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm", {});
  addDebuggerToGlobal(global);
  return global.RecordReplayControl;
});
  function selectInEditor(editor, start, end) {
    let win = Cu.getGlobalForObject(editor);
    let cloneIntoCMScope = (pos) => Wrapper.cloneIntoContentScope(win, pos);

    // Focusing looks to be required to select text in CodeMirror.
    editor.focus();

    editor.setSelection(
      cloneIntoCMScope(start),
      cloneIntoCMScope(end)
    );
  }
Example #10
0
exports.isSafeJSObject = function(obj) {
  // If we are running on a worker thread, Cu is not available. In this case,
  // we always return false, just to be on the safe side.
  if (isWorker) {
    return false;
  }

  if (Cu.getGlobalForObject(obj) ==
      Cu.getGlobalForObject(exports.isSafeJSObject)) {
    // obj is not a cross-compartment wrapper.
    return true;
  }

  // Xray wrappers protect against unintended code execution.
  if (Cu.isXrayWrapper(obj)) {
    return true;
  }

  // If there aren't Xrays, only allow chrome objects.
  const principal = Cu.getObjectPrincipal(obj);
  if (!Services.scriptSecurityManager.isSystemPrincipal(principal)) {
    return false;
  }

  // Scripted proxy objects without Xrays can run their proxy traps.
  if (Cu.isProxy(obj)) {
    return false;
  }

  // Even if `obj` looks safe, an unsafe object in its prototype chain may still
  // run unintended code, e.g. when using the `instanceof` operator.
  const proto = Object.getPrototypeOf(obj);
  if (proto && !exports.isSafeJSObject(proto)) {
    return false;
  }

  // Allow non-problematic chrome objects.
  return true;
};
Example #11
0
exports['test shared globals'] = function(assert) {
  let uri = root + '/fixtures/loader/cycles/';
  let loader = Loader({ paths: { '': uri }, sharedGlobal: true,
                        sharedGlobalBlocklist: ['b'] });

  let program = main(loader, 'main');

  // As it is hard to verify what is the global of an object
  // (due to wrappers) we check that we see the `foo` symbol
  // being manually injected into the shared global object
  loader.sharedGlobalSandbox.foo = true;

  let m = loader.sandboxes[uri + 'main.js'];
  let a = loader.sandboxes[uri + 'a.js'];
  let b = loader.sandboxes[uri + 'b.js'];

  assert.ok(Cu.getGlobalForObject(m).foo, "main is shared");
  assert.ok(Cu.getGlobalForObject(a).foo, "a is shared");
  assert.ok(!Cu.getGlobalForObject(b).foo, "b isn't shared");

  unload(loader);
}
Example #12
0
/**
 * Every highlighters should insert their markup content into the document's
 * canvasFrame anonymous content container (see dom/webidl/Document.webidl).
 *
 * Since this container gets cleared when the document navigates, highlighters
 * should use this helper to have their markup content automatically re-inserted
 * in the new document.
 *
 * Since the markup content is inserted in the canvasFrame using
 * insertAnonymousContent, this means that it can be modified using the API
 * described in AnonymousContent.webidl.
 * To retrieve the AnonymousContent instance, use the content getter.
 *
 * @param {HighlighterEnv} highlighterEnv
 *        The environemnt which windows will be used to insert the node.
 * @param {Function} nodeBuilder
 *        A function that, when executed, returns a DOM node to be inserted into
 *        the canvasFrame.
 */
function CanvasFrameAnonymousContentHelper(highlighterEnv, nodeBuilder) {
  this.highlighterEnv = highlighterEnv;
  this.nodeBuilder = nodeBuilder;
  this.anonymousContentDocument = this.highlighterEnv.document;
  // XXX the next line is a wallpaper for bug 1123362.
  this.anonymousContentGlobal = Cu.getGlobalForObject(
                                this.anonymousContentDocument);

  this._insert();

  this._onNavigate = this._onNavigate.bind(this);
  this.highlighterEnv.on("navigate", this._onNavigate);

  this.listeners = new Map();
}
Example #13
0
  addAutomationEvent: function (paramName, eventName, args = []) {
    let node = this.node.get();
    let timeline = this.automation[paramName];

    if (node === null) {
      return CollectedAudioNodeError();
    }

    if (!timeline || !node[paramName][eventName]) {
      return InvalidCommandError();
    }

    try {
      // Using the unwrapped node and parameter, the corresponding
      // WebAudioActor event will be fired, subsequently calling
      // `_recordAutomationEvent`. Some finesse is required to handle
      // the cast of TypedArray arguments over the protocol, which is
      // taken care of below. The event will cast the argument back
      // into an array to be broadcasted from WebAudioActor, but the
      // double-casting will only occur when starting from `addAutomationEvent`,
      // which is only used in tests.
      let param = XPCNativeWrapper.unwrap(node[paramName]);
      let contentGlobal = Cu.getGlobalForObject(param);
      let contentArgs = Cu.cloneInto(args, contentGlobal);

      // If calling `setValueCurveAtTime`, the first argument
      // is a Float32Array, which won't be able to be serialized
      // over the protocol. Cast a normal array to a Float32Array here.
      if (eventName === "setValueCurveAtTime") {
        // Create a Float32Array from the content, seeding with an array
        // from the same scope.
        let curve = new contentGlobal.Float32Array(contentArgs[0]);
        contentArgs[0] = curve;
      }

      // Apply the args back from the content scope, which is necessary
      // due to the method wrapping changing in bug 1130901 to be exported
      // directly to the content scope.
      param[eventName].apply(param, contentArgs);
    } catch (e) {
      return constructError(e);
    }
    return undefined;
  },
Example #14
0
/**
 * Every highlighters should insert their markup content into the document's
 * canvasFrame anonymous content container (see dom/webidl/Document.webidl).
 *
 * Since this container gets cleared when the document navigates, highlighters
 * should use this helper to have their markup content automatically re-inserted
 * in the new document.
 *
 * Since the markup content is inserted in the canvasFrame using
 * insertAnonymousContent, this means that it can be modified using the API
 * described in AnonymousContent.webidl.
 * To retrieve the AnonymousContent instance, use the content getter.
 *
 * @param {HighlighterEnv} highlighterEnv
 *        The environemnt which windows will be used to insert the node.
 * @param {Function} nodeBuilder
 *        A function that, when executed, returns a DOM node to be inserted into
 *        the canvasFrame.
 */
function CanvasFrameAnonymousContentHelper(highlighterEnv, nodeBuilder) {
  this.highlighterEnv = highlighterEnv;
  this.nodeBuilder = nodeBuilder;
  this.anonymousContentDocument = this.highlighterEnv.document;
  // XXX the next line is a wallpaper for bug 1123362.
  this.anonymousContentGlobal = Cu.getGlobalForObject(
                                this.anonymousContentDocument);

  // Only try to create the highlighter when the document is loaded,
  // otherwise, wait for the window-ready event to fire.
  let doc = this.highlighterEnv.document;
  if (doc.documentElement && doc.readyState != "uninitialized") {
    this._insert();
  }

  this._onWindowReady = this._onWindowReady.bind(this);
  this.highlighterEnv.on("window-ready", this._onWindowReady);

  this.listeners = new Map();
}
const protocol = require("devtools/shared/protocol");

const {Cc, Ci, Cu, Cr} = require("chrome");

const {DebuggerServer} = require("devtools/server/main");
const Services = require("Services");
const ChromeUtils = require("ChromeUtils");

loader.lazyGetter(this, "NodeActor", () => require("devtools/server/actors/inspector/node").NodeActor, true);

const {
  webExtensionInspectedWindowSpec,
} = require("devtools/shared/specs/addon/webextension-inspected-window");

const {WebExtensionPolicy} = Cu.getGlobalForObject(require("resource://gre/modules/XPCOMUtils.jsm"));

// A weak set of the documents for which a warning message has been
// already logged (so that we don't keep emitting the same warning if an
// extension keeps calling the devtools.inspectedWindow.eval API method
// when it fails to retrieve a result, but we do log the warning message
// if the user reloads the window):
//
// WeakSet<Document>
const deniedWarningDocuments = new WeakSet();

function isSystemPrincipalWindow(window) {
  return window.document.nodePrincipal.isSystemPrincipal;
}

// Create the exceptionInfo property in the format expected by a
Example #16
0
 *   // Do something
 *
 *   // If you want to log all the allocation sites, call this method:
 *   tracker.logAllocationSites();
 *   // Or, if you want to only print the number of objects being allocated, call this:
 *   tracker.logCount();
 *   // Once you are done, stop the tracker as it slow down execution a lot.
 *   tracker.stop();
 */

"use strict";

const { Cu } = require("chrome");
const ChromeUtils = require("ChromeUtils");

const global = Cu.getGlobalForObject(this);
const {addDebuggerToGlobal} = ChromeUtils.import("resource://gre/modules/jsdebugger.jsm");
addDebuggerToGlobal(global);

/**
 * Start recording JS object allocations.
 *
 * @param Object watchGlobal
 *        One global object to observe. Only allocation made from this global
 *        will be recorded.
 * @param Boolean watchAllGlobals
 *        If true, allocations from everywhere are going to be recorded.
 * @param Boolean watchAllGlobals
 *        If true, only allocations made from DevTools contexts are going to be recorded.
 */
exports.allocationTracker = function({
Example #17
0
 *
 * As it does so, the module itself doesn't have access to these globals,
 * nor the pseudo modules. Be careful to avoid loading any other js module as
 * they would also miss them.
 */

const { Cu, CC, Cc, Ci } = require("chrome");
const promise = require("resource://gre/modules/Promise.jsm").Promise;
const jsmScope = require("resource://devtools/shared/Loader.jsm");
const { Services } = jsmScope;
// Steal various globals only available in JSM scope (and not Sandbox one)
const {
  console,
  HeapSnapshot,
  StructuredCloneHolder,
} = Cu.getGlobalForObject(jsmScope);

// Create a single Sandbox to access global properties needed in this module.
// Sandbox are memory expensive, so we should create as little as possible.
const {
  atob,
  btoa,
  ChromeUtils,
  CSS,
  CSSRule,
  DOMParser,
  Element,
  Event,
  FileReader,
  FormData,
  indexedDB,
Example #18
0
loader.lazyGetter(this, "Debugger", () => {
  let global = Cu.getGlobalForObject({});
  let JsDebugger = Cu.import("resource://gre/modules/jsdebugger.jsm", {});
  JsDebugger.addDebuggerToGlobal(global);
  return global.Debugger;
});
Example #19
0
    exec: function(args, context) {
      let globalObj;
      let contentWindow = context.environment.window;

      if (args.sourceType == "jsm") {
        try {
          globalObj = Cu.import(args.source);
        }
        catch (e) {
          return l10n.lookup("callLogChromeInvalidJSM");
        }
      } else if (args.sourceType == "content-variable") {
        if (args.source in contentWindow) {
          globalObj = Cu.getGlobalForObject(contentWindow[args.source]);
        } else {
          throw new Error(l10n.lookup("callLogChromeVarNotFoundContent"));
        }
      } else if (args.sourceType == "chrome-variable") {
        let chromeWin = context.environment.chromeDocument.defaultView;
        if (args.source in chromeWin) {
          globalObj = Cu.getGlobalForObject(chromeWin[args.source]);
        } else {
          return l10n.lookup("callLogChromeVarNotFoundChrome");
        }
      } else {
        let chromeWin = context.environment.chromeDocument.defaultView;
        let sandbox = new Cu.Sandbox(chromeWin,
                                    {
                                      sandboxPrototype: chromeWin,
                                      wantXrays: false,
                                      sandboxName: "gcli-cmd-calllog-chrome"
                                    });
        let returnVal;
        try {
          returnVal = Cu.evalInSandbox(args.source, sandbox, "ECMAv5");
          sandboxes.push(sandbox);
        } catch(e) {
          // We need to save the message before cleaning up else e contains a dead
          // object.
          let msg = l10n.lookup("callLogChromeEvalException") + ": " + e;
          Cu.nukeSandbox(sandbox);
          return msg;
        }

        if (typeof returnVal == "undefined") {
          return l10n.lookup("callLogChromeEvalNeedsObject");
        }

        globalObj = Cu.getGlobalForObject(returnVal);
      }

      let dbg = new Debugger(globalObj);
      chromeDebuggers.push(dbg);

      dbg.onEnterFrame = function(frame) {
        // BUG 773652 -  Make the output from the GCLI calllog command nicer
        contentWindow.console.log(l10n.lookup("callLogChromeMethodCall") +
                                  ": " + this.callDescription(frame));
      }.bind(this);

      let gBrowser = context.environment.chromeDocument.defaultView.gBrowser;
      let target = TargetFactory.forTab(gBrowser.selectedTab);
      gDevTools.showToolbox(target, "webconsole");

      return l10n.lookup("calllogChromeStartReply");
    },
Example #20
0
const client = require("./adb-client");
const { getFileForBinary } = require("./binary-manager");
const { setTimeout } = Cu.import("resource://gre/modules/Timer.jsm", {});
const { Subprocess } = Cu.import("resource://gre/modules/Subprocess.jsm", {});
const { PromiseUtils } = Cu.import("resource://gre/modules/PromiseUtils.jsm", {});
const env = Cc["@mozilla.org/process/environment;1"].
              getService(Ci.nsIEnvironment);
const { OS } = require("resource://gre/modules/osfile.jsm");
const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});

// When loaded as a CommonJS module, get the TextEncoder and TextDecoder
// interfaces from the Services JavaScript Module, since they aren't defined
// in a CommonJS module by default.
// Starting with FF57, jsm share the same global and this require pulling it from it.
const { TextEncoder, TextDecoder } =
  Cu.getGlobalForObject(Cu.import("resource://gre/modules/Services.jsm", {}));

let ready = false;
let didRunInitially = false;
const psRegexNix = /.*? \d+ .*? .*? \d+\s+\d+ .*? .*? .*? .*? adb .*fork\-server/;
const psRegexWin = /adb.exe.*/;

const OKAY = 0x59414b4f;
// const FAIL = 0x4c494146;
// const STAT = 0x54415453;
const DATA = 0x41544144;
const DONE = 0x454e4f44;

const ADB = {
  get didRunInitially() {
    return didRunInitially;
Example #21
0
  processHandlerForEvent: function(node, listenerArray, dbg, listener) {
    const { handler } = listener;
    const global = Cu.getGlobalForObject(handler);
    const globalDO = dbg.addDebuggee(global);
    let listenerDO = globalDO.makeDebuggeeValue(handler);

    const { normalizeListener } = listener;

    if (normalizeListener) {
      listenerDO = normalizeListener(listenerDO, listener);
    }

    const { capturing } = listener;
    let dom0 = false;
    let functionSource = handler.toString();
    const hide = listener.hide || {};
    let line = 0;
    let native = false;
    const override = listener.override || {};
    const tags = listener.tags || "";
    const type = listener.type || "";
    let url = "";

    // If the listener is an object with a 'handleEvent' method, use that.
    if (listenerDO.class === "Object" || /^XUL\w*Element$/.test(listenerDO.class)) {
      let desc;

      while (!desc && listenerDO) {
        desc = listenerDO.getOwnPropertyDescriptor("handleEvent");
        listenerDO = listenerDO.proto;
      }

      if (desc && desc.value) {
        listenerDO = desc.value;
      }
    }

    // If the listener is bound to a different context then we need to switch
    // to the bound function.
    if (listenerDO.isBoundFunction) {
      listenerDO = listenerDO.boundTargetFunction;
    }

    const { isArrowFunction, name, script, parameterNames } = listenerDO;

    if (script) {
      const scriptSource = script.source.text;

      // Scripts are provided via script tags. If it wasn't provided by a
      // script tag it must be a DOM0 event.
      if (script.source.element) {
        dom0 = script.source.element.class !== "HTMLScriptElement";
      } else {
        dom0 = false;
      }

      line = script.startLine;
      url = script.url;

      // Checking for the string "[native code]" is the only way at this point
      // to check for native code. Even if this provides a false positive then
      // grabbing the source code a second time is harmless.
      if (functionSource === "[object Object]" ||
          functionSource === "[object XULElement]" ||
          functionSource.includes("[native code]")) {
        functionSource =
          scriptSource.substr(script.sourceStart, script.sourceLength);

        // At this point the script looks like this:
        // () { ... }
        // We prefix this with "function" if it is not a fat arrow function.
        if (!isArrowFunction) {
          functionSource = "function " + functionSource;
        }
      }
    } else {
      // If the listener is a native one (provided by C++ code) then we have no
      // access to the script. We use the native flag to prevent showing the
      // debugger button because the script is not available.
      native = true;
    }

    // Fat arrow function text always contains the parameters. Function
    // parameters are often missing e.g. if Array.sort is used as a handler.
    // If they are missing we provide the parameters ourselves.
    if (parameterNames && parameterNames.length > 0) {
      const prefix = "function " + name + "()";
      const paramString = parameterNames.join(", ");

      if (functionSource.startsWith(prefix)) {
        functionSource = functionSource.substr(prefix.length);

        functionSource = `function ${name} (${paramString})${functionSource}`;
      }
    }

    // If the listener is native code we display the filename "[native code]."
    // This is the official string and should *not* be translated.
    let origin;
    if (native) {
      origin = "[native code]";
    } else {
      origin = url + ((dom0 || line === 0) ? "" : ":" + line);
    }

    const eventObj = {
      type: override.type || type,
      handler: override.handler || functionSource.trim(),
      origin: override.origin || origin,
      tags: override.tags || tags,
      DOM0: typeof override.dom0 !== "undefined" ? override.dom0 : dom0,
      capturing: typeof override.capturing !== "undefined" ?
                 override.capturing : capturing,
      hide: typeof override.hide !== "undefined" ? override.hide : hide,
      native
    };

    // Hide the debugger icon for DOM0 and native listeners. DOM0 listeners are
    // generated dynamically from e.g. an onclick="" attribute so the script
    // doesn't actually exist.
    if (native || dom0) {
      eventObj.hide.debugger = true;
    }

    listenerArray.push(eventObj);

    dbg.removeDebuggee(globalDO);
  },