Esempio n. 1
0
function initNetMonitor(aUrl, aWindow, aEnableCache) {
  info("Initializing a network monitor pane.");

  return Task.spawn(function* () {
    let tab = yield addTab(aUrl);
    info("Net tab added successfully: " + aUrl);

    let target = TargetFactory.forTab(tab);

    yield target.makeRemote();
    info("Target remoted.");

    if (!aEnableCache) {
      yield toggleCache(target, true);
      info("Cache disabled when the current and all future toolboxes are open.");
      // Remove any requests generated by the reload while toggling the cache to
      // avoid interfering with the test.
      isnot([...target.activeConsole.getNetworkEvents()].length, 0,
         "Request to reconfigure the tab was recorded.");
      target.activeConsole.clearNetworkRequests();
    }

    let toolbox = yield gDevTools.showToolbox(target, "netmonitor");
    info("Netork monitor pane shown successfully.");

    let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
    let monitor = toolbox.getCurrentPanel();
    return [tab, debuggee, monitor];
  });
}
Esempio n. 2
0
 disconnectRuntime: function () {
   let disconnecting = Task.spawn(function* () {
     yield UI.destroyToolbox();
     yield AppManager.disconnectRuntime();
   });
   return UI.busyUntil(disconnecting, "disconnecting from runtime");
 },
Esempio n. 3
0
  open: function () {
    this._validateOptions();
    DebuggerServer._addListener(this);

    let flags = Ci.nsIServerSocket.KeepWhenOffline;
    // A preference setting can force binding on the loopback interface.
    if (Services.prefs.getBoolPref("devtools.debugger.force-local")) {
      flags |= Ci.nsIServerSocket.LoopbackOnly;
    }

    let self = this;
    return Task.spawn(function* () {
      let backlog = 4;
      self._socket = self._createSocketInstance();
      if (self.isPortBased) {
        let port = Number(self.portOrPath);
        self._socket.initSpecialConnection(port, flags, backlog);
      } else {
        let file = nsFile(self.portOrPath);
        if (file.exists()) {
          file.remove(false);
        }
        self._socket.initWithFilename(file, parseInt("666", 8), backlog);
      }
      yield self._setAdditionalSocketOptions();
      self._socket.asyncListen(self);
      dumpn("Socket listening on: " + (self.port || self.portOrPath));
    }).then(() => {
      this._advertise();
    }).catch(e => {
      dumpn("Could not start debugging listener on '" + this.portOrPath +
            "': " + e);
      this.close();
    });
  },
Esempio n. 4
0
  _getImported: function (doc, styleSheet) {
    return Task.spawn(function* () {
      let rules = yield styleSheet.getCSSRules();
      let imported = [];

      for (let i = 0; i < rules.length; i++) {
        let rule = rules[i];
        if (rule.type == Ci.nsIDOMCSSRule.IMPORT_RULE) {
          // With the Gecko style system, the associated styleSheet may be null
          // if it has already been seen because an import cycle for the same
          // URL.  With Stylo, the styleSheet will exist (which is correct per
          // the latest CSSOM spec), so we also need to check ancestors for the
          // same URL to avoid cycles.
          let sheet = rule.styleSheet;
          if (!sheet || this._haveAncestorWithSameURL(sheet) ||
              !this._shouldListSheet(doc, sheet)) {
            continue;
          }
          let actor = this.parentActor.createStyleSheetActor(rule.styleSheet);
          imported.push(actor);

          // recurse imports in this stylesheet as well
          let children = yield this._getImported(doc, actor);
          imported = imported.concat(children);
        } else if (rule.type != Ci.nsIDOMCSSRule.CHARSET_RULE) {
          // @import rules must precede all others except @charset
          break;
        }
      }

      return imported;
    }.bind(this));
  },
Esempio n. 5
0
  _addStyleSheets: function (win) {
    return Task.spawn(function* () {
      let doc = win.document;
      // readyState can be uninitialized if an iframe has just been created but
      // it has not started to load yet.
      if (doc.readyState === "loading" || doc.readyState === "uninitialized") {
        // Wait for the document to load first.
        yield listenOnce(win, "DOMContentLoaded", true);

        // Make sure we have the actual document for this window. If the
        // readyState was initially uninitialized, the initial dummy document
        // was replaced with the actual document (bug 1171919).
        doc = win.document;
      }

      let isChrome = Services.scriptSecurityManager.isSystemPrincipal(doc.nodePrincipal);
      let styleSheets = isChrome ? DOMUtils.getAllStyleSheets(doc) : doc.styleSheets;
      let actors = [];
      for (let i = 0; i < styleSheets.length; i++) {
        let sheet = styleSheets[i];
        if (!this._shouldListSheet(doc, sheet)) {
          continue;
        }

        let actor = this.parentActor.createStyleSheetActor(sheet);
        actors.push(actor);

        // Get all sheets, including imported ones
        let imports = yield this._getImported(doc, actor);
        actors = actors.concat(imports);
      }
      return actors;
    }.bind(this));
  },
function test() {
  const options = {
    tabContent: 'test if view menu items "Larger Font" and "Smaller Font" are enabled/disabled.'
  };
  openTabAndScratchpad(options)
    .then(Task.async(runTests))
    .then(finish, console.error);
}
 let requireInspector = generator => {
   return Task.async(function* (...args) {
     if (!isInspectorInitialized) {
       yield toolbox.initInspector();
       isInspectorInitialized = true;
     }
     return yield generator.apply(null, args);
   });
 };
Esempio n. 8
0
function removeAllProjects() {
  return Task.spawn(function* () {
    yield AppProjects.load();
    // use a new array so we're not iterating over the same
    // underlying array that's being modified by AppProjects
    let projects = AppProjects.projects.map(p => p.location);
    for (let i = 0; i < projects.length; i++) {
      yield AppProjects.remove(projects[i]);
    }
  });
}
Esempio n. 9
0
/**
 * Wait for a specific action type to be dispatch.
 * If an async action, will wait for it to be done.
 *
 * @memberof mochitest/waits
 * @param {Object} dbg
 * @param {String} type
 * @param {Number} eventRepeat
 * @return {Promise}
 * @static
 */
function waitForDispatch(dbg, type, eventRepeat = 1) {
  let count = 0;

  return Task.spawn(function*() {
    info(`Waiting for ${type} to dispatch ${eventRepeat} time(s)`);
    while (count < eventRepeat) {
      yield _afterDispatchDone(dbg.store, type);
      count++;
      info(`${type} dispatched ${count} time(s)`);
    }
  });
}
Esempio n. 10
0
  getTarget: function () {
    if (this.selectedProject.type == "mainProcess") {
      // Fx >=39 exposes a ChromeActor to debug the main process
      if (this.connection.client.mainRoot.traits.allowChromeProcess) {
        return this.connection.client.getProcess()
                   .then(aResponse => {
                     return TargetFactory.forRemoteTab({
                       form: aResponse.form,
                       client: this.connection.client,
                       chrome: true
                     });
                   });
      } else {
        // Fx <39 exposes tab actors on the root actor
        return TargetFactory.forRemoteTab({
          form: this._listTabsResponse,
          client: this.connection.client,
          chrome: true,
          isTabActor: false
        });
      }
    }

    if (this.selectedProject.type == "tab") {
      return this.tabStore.getTargetForTab();
    }

    let app = this._getProjectFront(this.selectedProject);
    if (!app) {
      return promise.reject("Can't find app front for selected project");
    }

    return Task.spawn(function* () {
      // Once we asked the app to launch, the app isn't necessary completely loaded.
      // launch request only ask the app to launch and immediatly returns.
      // We have to keep trying to get app tab actors required to create its target.

      for (let i = 0; i < 10; i++) {
        try {
          return yield app.getTarget();
        } catch (e) {}
        let deferred = promise.defer();
        setTimeout(deferred.resolve, 500);
        yield deferred.promise;
      }

      AppManager.reportError("error_cantConnectToApp", app.manifest.manifestURL);
      throw new Error("can't connect to app");
    });
  },
Esempio n. 11
0
    this.actions.togglePrettyPrint(source);
  },

  /**
   * Toggle the black boxed state of the selected source.
   */
  toggleBlackBoxing: Task.async(function* () {
    const source = getSelectedSource(this.getState());
    const shouldBlackBox = !source.isBlackBoxed;

    // Be optimistic that the (un-)black boxing will succeed, so
    // enable/disable the pretty print button and check/uncheck the
    // black box button immediately.
    if (shouldBlackBox) {
      this._prettyPrintButton.setAttribute("disabled", true);
      this._blackBoxButton.setAttribute("checked", true);
    } else {
      this._prettyPrintButton.removeAttribute("disabled");
      this._blackBoxButton.removeAttribute("checked");
    }

    this.actions.blackbox(source, shouldBlackBox);
  }),

  renderBlackBoxed: function (source) {
    const sourceItem = this.getItemByValue(source.actor);
    sourceItem.prebuiltNode.classList.toggle(
      "black-boxed",
      source.isBlackBoxed
    );
Esempio n. 12
0
  Services.prefs.clearUserPref("devtools.webide.busyTimeout");
  Services.prefs.clearUserPref("devtools.webide.lastSelectedProject");
  Services.prefs.clearUserPref("devtools.webide.lastConnectedRuntime");
});

var openWebIDE = Task.async(function* (autoInstallAddons) {
  info("opening WebIDE");

  Services.prefs.setBoolPref("devtools.webide.autoinstallADBHelper", !!autoInstallAddons);
  Services.prefs.setBoolPref("devtools.webide.autoinstallFxdtAdapters", !!autoInstallAddons);

  let ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);
  let win = ww.openWindow(null, "chrome://webide/content/", "webide", "chrome,centerscreen,resizable", null);

  yield new Promise(resolve => {
    win.addEventListener("load", function onLoad() {
      win.removeEventListener("load", onLoad);
      SimpleTest.requestCompleteLog();
      SimpleTest.executeSoon(resolve);
    });
  });

  info("WebIDE open");

  return win;
});

function closeWebIDE(win) {
  info("Closing WebIDE");

  let deferred = promise.defer();
  /**
   * Executed when the AnimationPlayerActor emits a "changed" event. Used to
   * update the local knowledge of the state.
   */
  onChanged: preEvent("changed", function (partialState) {
    let {state} = this.reconstructState(partialState);
    this.state = state;
  }),

  /**
   * Refresh the current state of this animation on the client from information
   * found on the server. Doesn't return anything, just stores the new state.
   */
  refreshState: Task.async(function* () {
    let data = yield this.getCurrentState();
    if (this.currentStateHasChanged) {
      this.state = data;
    }
  }),

  /**
   * getCurrentState interceptor re-constructs incomplete states since the actor
   * only sends the values that have changed.
   */
  getCurrentState: custom(function () {
    this.currentStateHasChanged = false;
    return this._getCurrentState().then(partialData => {
      let {state, hasChanged} = this.reconstructState(partialData);
      this.currentStateHasChanged = hasChanged;
      return state;
    });
  }, {
Esempio n. 14
0
  let deferred = defer();

  if ("@mozilla.org/settingsService;1" in Cc) {
    let settingsService;

    // settingsService fails in b2g child processes
    // TODO bug 1205797, make this work in child processes.
    try {
      settingsService = Cc["@mozilla.org/settingsService;1"]
                          .getService(Ci.nsISettingsService);
    } catch (e) {
      return promise.reject(e);
    }

    settingsService.createLock().get(name, {
      handle: (_, value) => deferred.resolve(value),
      handleError: (error) => deferred.reject(error),
    });
  } else {
    deferred.reject(new Error("No settings service"));
  }
  return deferred.promise;
}

exports.getSystemInfo = Task.async(getSystemInfo);
exports.getAppIniString = getAppIniString;
exports.getSetting = getSetting;
exports.getScreenDimensions = getScreenDimensions;
exports.getOSCPU = getOSCPU;
exports.constants = AppConstants;
Esempio n. 15
0
    iframe.removeAttribute("src");
  },

  /**
   * Remove an existing tab.
   * @param {String} tabId The ID of the tab that was used to register it, or
   * the tab id attribute value if the tab existed before the sidebar
   * got created.
   * @param {String} tabPanelId Optional. If provided, this ID will be used
   * instead of the tabId to retrieve and remove the corresponding <tabpanel>
   */
  removeTab: Task.async(function* (tabId, tabPanelId) {
    this._tabbar.removeTab(tabId);

    let win = this.getWindowForTab(tabId);
    if (win && ("destroy" in win)) {
      yield win.destroy();
    }

    this.emit("tab-unregistered", tabId);
  }),

  /**
   * Show or hide a specific tab.
   * @param {Boolean} isVisible True to show the tab/tabpanel, False to hide it.
   * @param {String} id The ID of the tab to be hidden.
   */
  toggleTab: function (isVisible, id) {
    this._tabbar.toggleTab(id, isVisible);
  },

  /**
Esempio n. 16
0
    if (updateButton) {
      let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor");
      nodeGeometry.removeAttribute("checked");
    }
  },

  /**
   * Update the visibility and the state of the geometry editor button,
   * based on the selected node.
   */
  updateGeometryButton: Task.async(function* () {
    let node = this.inspector.selection.nodeFront;
    let isEditable = false;

    if (node) {
      isEditable = yield this.inspector.pageStyle.isPositionEditable(node);
    }

    let nodeGeometry = this.doc.getElementById("old-layout-geometry-editor");
    nodeGeometry.style.visibility = isEditable ? "visible" : "hidden";
  }),

  manageOverflowingText: function (span) {
    let classList = span.parentNode.classList;

    if (classList.contains("old-boxmodel-left") ||
        classList.contains("old-boxmodel-right")) {
      let force = span.textContent.length > LONG_TEXT_ROTATE_LIMIT;
      classList.toggle("old-boxmodel-rotate", force);
    }
  }
Esempio n. 17
0
    }
  }),

  /**
   * Forces the reflow and waits for the next repaint.
   */
  reflow: protocol.method(function () {
    let deferred = promise.defer();
    this.content.document.documentElement.offsetWidth;
    this.content.requestAnimationFrame(deferred.resolve);

    return deferred.promise;
  }),

  getNodeRect: protocol.method(Task.async(function* (selector) {
    let node = this._querySelector(selector);
    return getRect(this.content, node, this.content);
  }), {
    request: {
      selector: Arg(0, "string")
    },
    response: {
      value: RetVal("json")
    }
  }),

  /**
   * Get information about a DOM element, identified by a selector.
   * @param {String} selector The CSS selector to get the node (can be an array
   * of selectors to get elements in an iframe).
   * @return {Object} data Null if selector didn't match any node, otherwise:
   * - {String} tagName.
Esempio n. 18
0
  validateAndUpdateProject: function (project) {
    if (!project) {
      return promise.reject();
    }

    return Task.spawn(function* () {

      let packageDir = yield ProjectBuilding.getPackageDir(project);
      let validation = new AppValidator({
        type: project.type,
        // Build process may place the manifest in a non-root directory
        location: packageDir
      });

      yield validation.validate();

      if (validation.manifest) {
        let manifest = validation.manifest;
        let iconPath;
        if (manifest.icons) {
          let size = Object.keys(manifest.icons).sort((a, b) => b - a)[0];
          if (size) {
            iconPath = manifest.icons[size];
          }
        }
        if (!iconPath) {
          project.icon = AppManager.DEFAULT_PROJECT_ICON;
        } else {
          if (project.type == "hosted") {
            let manifestURL = Services.io.newURI(project.location);
            let origin = Services.io.newURI(manifestURL.prePath);
            project.icon = Services.io.newURI(iconPath, null, origin).spec;
          } else if (project.type == "packaged") {
            let projectFolder = FileUtils.File(packageDir);
            let folderURI = Services.io.newFileURI(projectFolder).spec;
            project.icon = folderURI + iconPath.replace(/^\/|\\/, "");
          }
        }
        project.manifest = validation.manifest;

        if ("name" in project.manifest) {
          project.name = project.manifest.name;
        } else {
          project.name = AppManager.DEFAULT_PROJECT_NAME;
        }
      } else {
        project.manifest = null;
        project.icon = AppManager.DEFAULT_PROJECT_ICON;
        project.name = AppManager.DEFAULT_PROJECT_NAME;
      }

      project.validationStatus = "valid";

      if (validation.warnings.length > 0) {
        project.warningsCount = validation.warnings.length;
        project.warnings = validation.warnings;
        project.validationStatus = "warning";
      } else {
        project.warnings = "";
        project.warningsCount = 0;
      }

      if (validation.errors.length > 0) {
        project.errorsCount = validation.errors.length;
        project.errors = validation.errors;
        project.validationStatus = "error";
      } else {
        project.errors = "";
        project.errorsCount = 0;
      }

      if (project.warningsCount && project.errorsCount) {
        project.validationStatus = "error warning";
      }

      if (project.type === "hosted" && project.location !== validation.manifestURL) {
        yield AppProjects.updateLocation(project, validation.manifestURL);
      } else if (AppProjects.get(project.location)) {
        yield AppProjects.update(project);
      }

      if (AppManager.selectedProject === project) {
        AppManager.update("project-validated");
      }
    });
  },
Esempio n. 19
0
  /**
   * @see MemoryFront.prototype.transferHeapSnapshot
   */
  transferHeapSnapshot: method(Task.async(function* (snapshotId) {
    const snapshotFilePath =
          HeapSnapshotFileUtils.getHeapSnapshotTempFilePath(snapshotId);
    if (!snapshotFilePath) {
      throw new Error(`No heap snapshot with id: ${snapshotId}`);
    }

    const streamPromise = DevToolsUtils.openFileStream(snapshotFilePath);

    const { size } = yield OS.File.stat(snapshotFilePath);
    const bulkPromise = this.conn.startBulkSend({
      actor: this.actorID,
      type: "heap-snapshot",
      length: size
    });

    const [bulk, stream] = yield Promise.all([bulkPromise, streamPromise]);

    try {
      yield bulk.copyFrom(stream);
    } finally {
      stream.close();
    }
  }), {
    request: {
      snapshotId: Arg(0, "string")
    }
  }),
Esempio n. 20
0
 * HighlighterLock is a helper used to lock the highlighter on DOM nodes in the
 * page.
 * It instantiates a new highlighter that is then shared amongst all instances
 * of DomNodePreview. This is useful because that means showing the highlighter
 * on one node will unhighlight the previously highlighted one, but will not
 * interfere with the default inspector highlighter.
 */
var HighlighterLock = {
  highlighter: null,
  isShown: false,

  highlight: Task.async(function* (animationTargetNode) {
    if (!this.highlighter) {
      let util = animationTargetNode.inspector.toolbox.highlighterUtils;
      this.highlighter = yield util.getHighlighterByType("BoxModelHighlighter");
    }

    yield this.highlighter.show(animationTargetNode.nodeFront);
    this.isShown = true;
    this.emit("highlighted", animationTargetNode);
  }),

  unhighlight: Task.async(function* () {
    if (!this.highlighter || !this.isShown) {
      return;
    }

    yield this.highlighter.hide();
    this.isShown = false;
    this.emit("unhighlighted");
  })
};
Esempio n. 21
0
   * Initializes the grid inspector by fetching the LayoutFront from the walker, loading
   * the highlighter settings and initalizing the SwatchColorPicker instance.
   */
  init: Task.async(function* () {
    if (!this.inspector) {
      return;
    }

    this.layoutInspector = yield this.inspector.walker.getLayoutInspector();

    this.loadHighlighterSettings();

    // Create a shared SwatchColorPicker instance to be reused by all GridItem components.
    this.swatchColorPickerTooltip = new SwatchColorPickerTooltip(
      this.inspector.toolbox.doc,
      this.inspector,
      {
        supportsCssColor4ColorFunction: () => false
      }
    );

    this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
    this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
    this.inspector.on("markupmutation", this.onMarkupMutation);
    this.inspector.sidebar.on("select", this.onSidebarSelect);

    this.onSidebarSelect();
  }),

  /**
   * Destruction function called when the inspector is destroyed. Removes event listeners
Esempio n. 22
0
  update: function () {
    let lastRequest = Task.spawn((function* () {
      if (!this.isViewVisibleAndNodeValid()) {
        this.wrapper.hidden = true;
        this.inspector.emit("boxmodel-view-updated");
        return null;
      }

      let node = this.inspector.selection.nodeFront;
      let layout = yield this.inspector.pageStyle.getLayout(node, {
        autoMargins: this.isActive
      });
      let styleEntries = yield this.inspector.pageStyle.getApplied(node, {});

      yield this.updateGeometryButton();

      // If a subsequent request has been made, wait for that one instead.
      if (this._lastRequest != lastRequest) {
        return this._lastRequest;
      }

      this._lastRequest = null;
      let width = layout.width;
      let height = layout.height;
      let newLabel = SHARED_L10N.getFormatStr("dimensions", width, height);

      if (this.sizeHeadingLabel.textContent != newLabel) {
        this.sizeHeadingLabel.textContent = newLabel;
      }

      for (let i in this.map) {
        let property = this.map[i].property;
        if (!(property in layout)) {
          // Depending on the actor version, some properties
          // might be missing.
          continue;
        }
        let parsedValue = parseFloat(layout[property]);
        if (Number.isNaN(parsedValue)) {
          // Not a number. We use the raw string.
          // Useful for "position" for example.
          this.map[i].value = layout[property];
        } else {
          this.map[i].value = parsedValue;
        }
      }

      let margins = layout.autoMargins;
      if ("top" in margins) {
        this.map.marginTop.value = "auto";
      }
      if ("right" in margins) {
        this.map.marginRight.value = "auto";
      }
      if ("bottom" in margins) {
        this.map.marginBottom.value = "auto";
      }
      if ("left" in margins) {
        this.map.marginLeft.value = "auto";
      }

      for (let i in this.map) {
        let selector = this.map[i].selector;
        let span = this.doc.querySelector(selector);
        this.updateSourceRuleTooltip(span, this.map[i].property, styleEntries);
        if (span.textContent.length > 0 &&
            span.textContent == this.map[i].value) {
          continue;
        }
        span.textContent = this.map[i].value;
        this.manageOverflowingText(span);
      }

      width -= this.map.borderLeft.value + this.map.borderRight.value +
               this.map.paddingLeft.value + this.map.paddingRight.value;
      width = parseFloat(width.toPrecision(6));
      height -= this.map.borderTop.value + this.map.borderBottom.value +
                this.map.paddingTop.value + this.map.paddingBottom.value;
      height = parseFloat(height.toPrecision(6));

      let newValue = width + "\u00D7" + height;
      if (this.sizeLabel.textContent != newValue) {
        this.sizeLabel.textContent = newValue;
      }

      this.elementRules = styleEntries.map(e => e.rule);

      this.wrapper.hidden = false;

      this.inspector.emit("boxmodel-view-updated");
      return null;
    }).bind(this)).catch(console.error);

    this._lastRequest = lastRequest;
    return this._lastRequest;
  },
Esempio n. 23
0
      }
    }

    this.update("project");
    this.checkIfProjectIsRunning();
  },
  get selectedProject() {
    return this._selectedProject;
  },

  removeSelectedProject: Task.async(function* () {
    let location = this.selectedProject.location;
    AppManager.selectedProject = null;
    // If the user cancels the removeProject operation, don't remove the project
    if (AppManager.selectedProject != null) {
      return;
    }

    yield AppProjects.remove(location);
    AppManager.update("project-removed");
  }),

  packageProject: Task.async(function* (project) {
    if (!project) {
      return;
    }
    if (project.type == "packaged" ||
        project.type == "hosted") {
      yield ProjectBuilding.build({
        project: project,
        logger: this.update.bind(this, "pre-package")
Esempio n. 24
0
  /**
   * Initializes a connection to the profiler and other miscellaneous actors.
   * If in the process of opening, or already open, nothing happens.
   *
   * @return object
   *         A promise that is resolved once the connection is established.
   */
  connect: Task.async(function* () {
    if (this._connecting) {
      return this._connecting.promise;
    }

    // Create a promise that gets resolved upon connecting, so that
    // other attempts to open the connection use the same resolution promise
    this._connecting = promise.defer();

    // Sets `this._profiler`, `this._timeline`.
    // Only initialize the timeline fronts if the respective actors
    // are available. Older Gecko versions don't have existing implementations,
    // in which case all the methods we need can be easily mocked.
    yield this._connectActors();
    yield this._registerListeners();

    this._connecting.resolve();
  }),

  /**
   * Destroys this connection.
   */
  destroy: Task.async(function* () {
    if (this._connecting) {
      yield this._connecting.promise;
Esempio n. 25
0
  installAndRunProject: function () {
    let project = this.selectedProject;

    if (!project || (project.type != "packaged" && project.type != "hosted")) {
      console.error("Can't install project. Unknown type of project.");
      return promise.reject("Can't install");
    }

    if (!this._listTabsResponse) {
      this.reportError("error_cantInstallNotFullyConnected");
      return promise.reject("Can't install");
    }

    if (!this._appsFront) {
      console.error("Runtime doesn't have a webappsActor");
      return promise.reject("Can't install");
    }

    return Task.spawn(function* () {
      let self = AppManager;

      // Package and validate project
      yield self.packageProject(project);
      yield self.validateAndUpdateProject(project);

      if (project.errorsCount > 0) {
        self.reportError("error_cantInstallValidationErrors");
        return;
      }

      let installPromise;

      if (project.type != "packaged" && project.type != "hosted") {
        return promise.reject("Don't know how to install project");
      }

      let response;
      if (project.type == "packaged") {
        let packageDir = yield ProjectBuilding.getPackageDir(project);
        console.log("Installing app from " + packageDir);

        response = yield self._appsFront.installPackaged(packageDir,
                                                         project.packagedAppOrigin);

        // If the packaged app specified a custom origin override,
        // we need to update the local project origin
        project.packagedAppOrigin = response.appId;
        // And ensure the indexed db on disk is also updated
        AppProjects.update(project);
      }

      if (project.type == "hosted") {
        let manifestURLObject = Services.io.newURI(project.location);
        let origin = Services.io.newURI(manifestURLObject.prePath);
        let appId = origin.host;
        let metadata = {
          origin: origin.spec,
          manifestURL: project.location
        };
        response = yield self._appsFront.installHosted(appId,
                                            metadata,
                                            project.manifest);
      }

      // Addons don't have any document to load (yet?)
      // So that there is no need to run them, installing is enough
      if (project.manifest.manifest_version || project.manifest.role === "addon") {
        return;
      }

      let {app} = response;
      if (!app.running) {
        let deferred = promise.defer();
        self.on("app-manager-update", function onUpdate(event, what) {
          if (what == "project-started") {
            self.off("app-manager-update", onUpdate);
            deferred.resolve();
          }
        });
        yield app.launch();
        yield deferred.promise;
      } else {
        yield app.reload();
      }
    });
  },
Esempio n. 26
0
  search: custom(Task.async(function* (query, options = { }) {
    let nodeList;
    let searchType;
    let searchData = this.searchData = this.searchData || { };
    let selectorOnly = !!options.selectorOnly;

    // Backwards compat.  Use selector only search if the new
    // search functionality isn't implemented, or if the caller (tests)
    // want it.
    if (selectorOnly || !this.traits.textSearch) {
      searchType = "selector";
      if (this.traits.multiFrameQuerySelectorAll) {
        nodeList = yield this.multiFrameQuerySelectorAll(query);
      } else {
        nodeList = yield this.querySelectorAll(this.rootNode, query);
      }
    } else {
      searchType = "search";
      let result = yield this._search(query, options);
      nodeList = result.list;
    }

    // If this is a new search, start at the beginning.
    if (searchData.query !== query ||
        searchData.selectorOnly !== selectorOnly) {
      searchData.selectorOnly = selectorOnly;
      searchData.query = query;
      searchData.index = -1;
    }

    if (!nodeList.length) {
      return null;
    }

    // Move search result cursor and cycle if necessary.
    searchData.index = options.reverse ? searchData.index - 1 :
                                         searchData.index + 1;
    if (searchData.index >= nodeList.length) {
      searchData.index = 0;
    }
    if (searchData.index < 0) {
      searchData.index = nodeList.length - 1;
    }

    // Send back the single node, along with any relevant search data
    let node = yield nodeList.item(searchData.index);
    return {
      type: searchType,
      node: node,
      resultsLength: nodeList.length,
      resultsIndex: searchData.index,
    };
  }), {
Esempio n. 27
0
  this._target.on("will-navigate", this._onBeforeNavigate);

  EventEmitter.decorate(this);
}

exports.InspectorPanel = InspectorPanel;

InspectorPanel.prototype = {
  /**
   * open is effectively an asynchronous constructor
   */
  open: Task.async(function* () {
    this._cssPropertiesLoaded = initCssProperties(this.toolbox);
    yield this._cssPropertiesLoaded;
    yield this.target.makeRemote();
    yield this._getPageStyle();
    let defaultSelection = yield this._getDefaultNodeForSelection();
    return yield this._deferredOpen(defaultSelection);
  }),

  get toolbox() {
    return this._toolbox;
  },

  get inspector() {
    return this._toolbox.inspector;
  },

  get walker() {
    return this._toolbox.walker;
  },
  copyPostData: Task.async(function* () {
    let selected = this.selectedItem.attachment;

    // Try to extract any form data parameters.
    let formDataSections = yield getFormDataSections(
      selected.requestHeaders,
      selected.requestHeadersFromUploadStream,
      selected.requestPostData,
      gNetwork.getString.bind(gNetwork));

    let params = [];
    formDataSections.forEach(section => {
      let paramsArray = NetworkHelper.parseQueryString(section);
      if (paramsArray) {
        params = [...params, ...paramsArray];
      }
    });

    let string = params
      .map(param => param.name + (param.value ? "=" + param.value : ""))
      .join(Services.appinfo.OS === "WINNT" ? "\r\n" : "\n");

    // Fall back to raw payload.
    if (!string) {
      let postData = selected.requestPostData.postData.text;
      string = yield gNetwork.getString(postData);
      if (Services.appinfo.OS !== "WINNT") {
        string = string.replace(/\r/g, "");
      }
    }

    clipboardHelper.copyString(string);
  }),
Esempio n. 29
0
  },

  getMatchedSelectors: custom(function (node, property, options) {
    return this._getMatchedSelectors(node, property, options).then(ret => {
      return ret.matched;
    });
  }, {
    impl: "_getMatchedSelectors"
  }),

  getApplied: custom(Task.async(function* (node, options = {}) {
    // If the getApplied method doesn't recreate the style cache itself, this
    // means a call to cssLogic.highlight is required before trying to access
    // the applied rules. Issue a request to getLayout if this is the case.
    // See https://bugzilla.mozilla.org/show_bug.cgi?id=1103993#c16.
    if (!this._form.traits || !this._form.traits.getAppliedCreatesStyleCache) {
      yield this.getLayout(node);
    }
    let ret = yield this._getApplied(node, options);
    return ret.entries;
  }), {
    impl: "_getApplied"
  }),

  addNewRule: custom(function (node, pseudoClasses) {
    let addPromise;
    if (this.supportsAuthoredStyles) {
      addPromise = this._addNewRule(node, pseudoClasses, true);
    } else {
      addPromise = this._addNewRule(node, pseudoClasses);
    }
}

const MAXIMUM_FONT_SIZE = 96;
const MINIMUM_FONT_SIZE = 6;
const NORMAL_FONT_SIZE = 12;

var testMaximumFontSize = Task.async(function* (win, sp) {
  let doc = win.document;

  Services.prefs.clearUserPref("devtools.scratchpad.editorFontSize");

  let menu = doc.getElementById("sp-menu-larger-font");

  for (let i = NORMAL_FONT_SIZE; i <= MAXIMUM_FONT_SIZE; i++) {
    menu.doCommand();
  }

  let cmd = doc.getElementById("sp-cmd-larger-font");
  ok(cmd.getAttribute("disabled") === "true", 'Command "sp-cmd-larger-font" is disabled.');

  menu = doc.getElementById("sp-menu-smaller-font");
  menu.doCommand();

  ok(cmd.hasAttribute("disabled") === false, 'Command "sp-cmd-larger-font" is enabled.');
});

var testMinimumFontSize = Task.async(function* (win, sp) {
  let doc = win.document;

  let menu = doc.getElementById("sp-menu-smaller-font");