executeRecipe: Task.async(function* (recipe, extraContext) {
    const sandbox = new Cu.Sandbox(null, {
      wantComponents: false,
      wantGlobalProperties: ['URL', 'URLSearchParams'],
    });

    sandbox.setTimeout = Cu.cloneInto(setTimeout, sandbox, {cloneFunctions: true});

    let action = yield NormandyApi.fetchAction(recipe.action);
    let response = yield Http.get({url: action.implementation_url});

    const actionScript = response.text;
    const registerActionScript = `
      function registerAction(name, Action) {
        let a = new Action(sandboxedDriver, sandboxedRecipe);
        a.execute()
        .catch(err => sandboxedDriver.log(err, 'error'));
      };

      window.registerAction = registerAction;
    `;

    const driver = new NormandyDriver(this, sandbox, extraContext);
    sandbox.sandboxedDriver = Cu.cloneInto(driver, sandbox, {cloneFunctions: true});
    sandbox.sandboxedRecipe = Cu.cloneInto(recipe, sandbox);
    sandbox.window = Cu.cloneInto({}, sandbox);

    Cu.evalInSandbox(registerActionScript, sandbox);
    Cu.evalInSandbox(actionScript, sandbox);
  }),
Example #2
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 #3
0
// Exports variables that will be accessed by the non-privileged scripts.
function exportData(win, headers) {
  const json = new win.Text();
  const JSONView = Cu.cloneInto({
    debugJsModules,
    headers,
    json,
    readyState: "uninitialized",
    Locale: {
      $STR: key => {
        try {
          return jsonViewStrings.GetStringFromName(key);
        } catch (err) {
          console.error(err);
          return undefined;
        }
      },
    },
  }, win, {
    cloneFunctions: true,
    wrapReflectors: true,
  });
  try {
    Object.defineProperty(Cu.waiveXrays(win), "JSONView", {
      value: JSONView,
      configurable: true,
      enumerable: true,
      writable: true,
    });
  } catch (error) {
    Cu.reportError(error);
  }
  return {json};
}
Example #4
0
 onEcho: function(request) {
   /*
    * Request packets are frozen. Copy request, so that
    * DebuggerServerConnection.onPacket can attach a 'from' property.
    */
   return Cu.cloneInto(request, {});
 },
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
// Exports variables that will be accessed by the non-privileged scripts.
function exportData(win, request) {
  let data = Cu.createObjectIn(win, {
    defineAs: "JSONView"
  });

  data.debug = debug;

  data.json = new win.Text();

  data.readyState = "uninitialized";

  let Locale = {
    $STR: key => {
      try {
        return jsonViewStrings.GetStringFromName(key);
      } catch (err) {
        console.error(err);
        return undefined;
      }
    }
  };
  data.Locale = Cu.cloneInto(Locale, win, {cloneFunctions: true});

  let headers = {
    response: [],
    request: []
  };
  // The request doesn't have to be always nsIHttpChannel
  // (e.g. in case of data: URLs)
  if (request instanceof Ci.nsIHttpChannel) {
    request.visitResponseHeaders({
      visitHeader: function (name, value) {
        headers.response.push({name: name, value: value});
      }
    });
    request.visitRequestHeaders({
      visitHeader: function (name, value) {
        headers.request.push({name: name, value: value});
      }
    });
  }
  data.headers = Cu.cloneInto(headers, win);

  return data;
}
Example #7
0
  _onRemoteUpdate: function(update) {
    log("GOT REMOTE UPDATE");

    const remoteDevice = update.device;
    const remoteHost = update.from;

    // Record the reply as received so it won't be purged as missing
    this._expectingReplies.from.delete(remoteDevice);

    // First, loop over the known services
    for (const service in this.remoteServices) {
      const devicesWithService = this.remoteServices[service];
      const hadServiceForDevice = !!devicesWithService[remoteDevice];
      const haveServiceForDevice = service in update.services;
      // If the remote device used to have service, but doesn't any longer, then
      // it was deleted, so we remove it here.
      if (hadServiceForDevice && !haveServiceForDevice) {
        delete devicesWithService[remoteDevice];
        log("REMOVED " + service + ", DEVICE " + remoteDevice);
        this.emit(service + "-device-removed", remoteDevice);
      }
    }

    // Second, loop over the services in the received update
    for (const service in update.services) {
      // Detect if this is a new device for this service
      const newDevice = !this.remoteServices[service] ||
                      !this.remoteServices[service][remoteDevice];

      // Look up the service info we may have received previously from the same
      // remote device
      const devicesWithService = this.remoteServices[service] || {};
      const oldDeviceInfo = devicesWithService[remoteDevice];

      // Store the service info from the remote device
      const newDeviceInfo = Cu.cloneInto(update.services[service], {});
      newDeviceInfo.host = remoteHost;
      devicesWithService[remoteDevice] = newDeviceInfo;
      this.remoteServices[service] = devicesWithService;

      // If this is a new service for the remote device, announce the addition
      if (newDevice) {
        log("ADDED " + service + ", DEVICE " + remoteDevice);
        this.emit(service + "-device-added", remoteDevice, newDeviceInfo);
      }

      // If we've seen this service from the remote device, but the details have
      // changed, announce the update
      if (!newDevice &&
          JSON.stringify(oldDeviceInfo) != JSON.stringify(newDeviceInfo)) {
        log("UPDATED " + service + ", DEVICE " + remoteDevice);
        this.emit(service + "-device-updated", remoteDevice, newDeviceInfo);
      }
    }
  },
Example #8
0
WebConsoleCommands._registerOriginal("values", function (owner, object) {
  let values = [];
  // Need to waive Xrays so we can iterate functions and accessor properties
  let waived = Cu.waiveXrays(object);
  let names = Object.getOwnPropertyNames(waived);

  for (let name of names) {
    values.push(waived[name]);
  }

  return Cu.cloneInto(values, owner.window);
});
Example #9
0
  on(events, "content-script-before-inserted", ({ window, worker }) => {
    assert.pass("content-script-before-inserted");

    if (isAddonContent({ contentURL: window.location.href })) {
      let extraStuff = Cu.cloneInto(extrasVal, window, {
        cloneFunctions: true
      });
      getUnsafeWindow(window).extras = extraStuff;

      assert.pass("content-script-before-inserted done!");
    }
  });
Example #10
0
function createChromeAPI (scope) {
  return Cu.cloneInto({
    timers: {
      setTimeout: timer.setTimeout.bind(timer),
      setInterval: timer.setInterval.bind(timer),
      clearTimeout: timer.clearTimeout.bind(timer),
      clearInterval: timer.clearInterval.bind(timer),
    },
    sandbox: {
      evaluate: evaluate,
    },
  }, scope, {cloneFunctions: true});
}
Example #11
0
/**
 * This function is called to simulate camera effects
 */
function simulateCameraEffect(document, effect) {
  let window = document.defaultView;
  if (effect === "shutter") {
    if (Services.prefs.getBoolPref("devtools.screenshot.audio.enabled")) {
      const audioCamera = new window.Audio("resource://devtools/client/themes/audio/shutter.wav");
      audioCamera.play();
    }
  }
  if (effect == "flash") {
    const frames = Cu.cloneInto({ opacity: [ 0, 1 ] }, window);
    document.documentElement.animate(frames, CONTAINER_FLASHING_DURATION);
  }
}
 setTimeout(() => {
   if (!(eventName in listeners)) {
     Log.debug(`EventEmitter: Event fired with no listeners: ${eventName}`);
     return;
   }
   let frozenEvent = Object.freeze(event);
   if (sandbox) {
     frozenEvent = Cu.cloneInto(frozenEvent, sandbox);
   }
   const callbacks = listeners[eventName];
   for (let cb of callbacks) {
     cb(frozenEvent);
   }
 }, 0);
Example #13
0
  function handlePageShow(url) {
    if (url == null || url.startsWith("about:")) {
      PledgeButton.setCurrentSite(null);
      return;
    }

    try {
      let uri = NetUtil.newURI(url);
      let host = uri.host.replace(/^www\./, "");
      let siteInfo = Cu.cloneInto(PledgedSites.getPledgedSite(host), {});
      siteInfo.host = host;
      PledgeButton.setCurrentSite(siteInfo);
    }
    catch (e) {
      dump(e + " ERROR\b");
    }
  };
Example #14
0
exports.exportIntoContentScope = function (win, obj, defineAs) {
  let clone = Cu.createObjectIn(win, {
    defineAs: defineAs
  });

  let props = Object.getOwnPropertyNames(obj);
  for (let i = 0; i < props.length; i++) {
    let propName = props[i];
    let propValue = obj[propName];
    if (typeof propValue == "function") {
      Cu.exportFunction(propValue, clone, {
        defineAs: propName
      });
    } else {
      clone[propName] = Cu.cloneInto(propValue, win);
    }
  }
};
Example #15
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 #16
0
  startRecording: Task.async(function*() {
    let { isActive, currentTime } = yield this._request("profiler", "isActive");

    // Start the profiler only if it wasn't already active. The built-in
    // nsIProfiler module will be kept recording, because it's the same instance
    // for all toolboxes and interacts with the whole platform, so we don't want
    // to affect other clients by stopping (or restarting) it.
    if (!isActive) {
      // Make a copy of the options, because eventually _request wants
      // to freeze the packet.
      let localOptions = Cu.cloneInto(this._customProfilerOptions, {});
      yield this._request("profiler", "startProfiler", localOptions);
      this._profilingStartTime = 0;
      this.emit("profiler-activated");
    } else {
      this._profilingStartTime = currentTime;
      this.emit("profiler-already-active");
    }

    // The framerate actor is target-dependent, so just make sure
    // it's recording.
    yield this._request("framerate", "startRecording");
  }),
 function clone(obj) {
   return Cu.cloneInto(obj, target);
 }
Example #18
0
  attach: function (window, innerId) {
    this._innerId = innerId,
    this._window = window;
    this._proto = Cu.createObjectIn(this._window);

    var id = this._scriptId;
    var uri = this._scriptCode;

    this._sandbox = sandbox(window, {
      sandboxName: uri,
      sandboxPrototype: this._proto,
      sameZoneAs: window,
      wantXrays: true,
      wantComponents: false,
      wantExportHelpers: false,
      metadata: {
        URI: uri,
        addonID: id,
        SDKDirectorScript: true,
        "inner-window-id": innerId
      }
    });

    // create a CommonJS module object which match the interface from addon-sdk
    // (addon-sdk/sources/lib/toolkit/loader.js#L678-L686)
    var module = Cu.cloneInto(Object.create(null, {
      id: { enumerable: true, value: id },
      uri: { enumerable: true, value: uri },
      exports: { enumerable: true, value: Cu.createObjectIn(this._sandbox) }
    }), this._sandbox);

    // create a console API object
    let directorScriptConsole = new PlainTextConsole(null, this._innerId);

    // inject CommonJS module globals into the sandbox prototype
    Object.defineProperties(this._proto, {
      module: { enumerable: true, value: module },
      exports: { enumerable: true, value: module.exports },
      console: {
        enumerable: true,
        value: Cu.cloneInto(directorScriptConsole, this._sandbox, { cloneFunctions: true })
      }
    });

    Object.defineProperties(this._sandbox, {
      require: {
        enumerable: true,
        value: Cu.cloneInto(function () {
          throw Error("NOT IMPLEMENTED");
        }, this._sandbox, { cloneFunctions: true })
      }
    });

    // TODO: if the debugger target is local, the debugger client could pass
    // to the director actor the resource url instead of the entire javascript source code.

    // evaluate the director script source in the sandbox
    evaluate(this._sandbox, this._scriptCode, "javascript:" + this._scriptCode);

    // prepare the messageport connected to the debugger client
    let { port1, port2 } = new this._window.MessageChannel();

    // prepare the unload callbacks queue
    var sandboxOnUnloadQueue = this._sandboxOnUnloadQueue = [];

    // create the attach options
    var attachOptions = this._attachOptions = Cu.createObjectIn(this._sandbox);
    Object.defineProperties(attachOptions, {
      port: { enumerable: true, value: port1 },
      window: { enumerable: true, value: window },
      scriptOptions: { enumerable: true, value: Cu.cloneInto(this._scriptOptions, this._sandbox) },
      onUnload: {
        enumerable: true,
        value: Cu.cloneInto(function (cb) {
          // collect unload callbacks
          if (typeof cb == "function") {
            sandboxOnUnloadQueue.push(cb);
          }
        }, this._sandbox, { cloneFunctions: true })
      }
    });

    // select the attach method
    var exports = this._proto.module.exports;
    if (this._scriptOptions && "attachMethod" in this._scriptOptions) {
      this._sandboxOnAttach = exports[this._scriptOptions.attachMethod];
    } else {
      this._sandboxOnAttach = exports;
    }

    if (typeof this._sandboxOnAttach !== "function") {
      throw Error("the configured attachMethod '" +
                  (this._scriptOptions.attachMethod || "module.exports") +
                  "' is not exported by the directorScript");
    }

    // call the attach method
    this._sandboxOnAttach.call(this._sandbox, attachOptions);

    return port2;
  },
Example #19
0
WebConsoleCommands._registerOriginal("keys", function JSTH_keys(aOwner, aObject)
{
  // Need to waive Xrays so we can iterate functions and accessor properties
  return Cu.cloneInto(Object.keys(Cu.waiveXrays(aObject)), aOwner.window);
});
Example #20
0
/**
 * This function is called to simulate camera effects
 * @param object document
 *        The target document.
 */
function simulateCameraFlash(document) {
  const window = document.defaultView;
  const frames = Cu.cloneInto({ opacity: [ 0, 1 ] }, window);
  document.documentElement.animate(frames, CONTAINER_FLASHING_DURATION);
}