Example #1
0
/**
 * Opens a channel for given URL. Tries a bit harder than NetUtil.newChannel.
 *
 * @param {String} url - The URL to open a channel for.
 * @param {Object} options - The options object passed to @method fetch.
 * @return {nsIChannel} - The newly created channel. Throws on failure.
 */
function newChannelForURL(url, { policy, window, principal }, recursing = false) {
  const securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;

  let uri;
  try {
    uri = Services.io.newURI(url);
  } catch (e) {
    // In the xpcshell tests, the script url is the absolute path of the test
    // file, which will make a malformed URI error be thrown. Add the file
    // scheme to see if it helps.
    uri = Services.io.newURI("file://" + url);
  }
  const channelOptions = {
    contentPolicyType: policy,
    securityFlags: securityFlags,
    uri: uri,
  };

  // Ensure that we have some contentPolicyType type set if one was
  // not provided.
  if (!channelOptions.contentPolicyType) {
    channelOptions.contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
  }

  // If a window is provided, always use it's document as the loadingNode.
  // This will provide the correct principal, origin attributes, service
  // worker controller, etc.
  if (window) {
    channelOptions.loadingNode = window.document;
  } else {
    // If a window is not provided, then we must set a loading principal.

    // If the caller did not provide a principal, then we use the URI
    // to create one.  Note, it's not clear what use cases require this
    // and it may not be correct.
    let prin = principal;
    if (!prin) {
      prin = Services.scriptSecurityManager
                     .createCodebasePrincipal(uri, {});
    }

    channelOptions.loadingPrincipal = prin;
  }

  try {
    return NetUtil.newChannel(channelOptions);
  } catch (e) {
    // Don't infinitely recurse if newChannel keeps throwing.
    if (recursing) {
      throw e;
    }

    // In xpcshell tests on Windows, nsExternalProtocolHandler::NewChannel()
    // can throw NS_ERROR_UNKNOWN_PROTOCOL if the external protocol isn't
    // supported by Windows, so we also need to handle the exception here if
    // parsing the URL above doesn't throw.
    return newChannelForURL("file://" + url, { policy, window, principal },
                            /* recursing */ true);
  }
}
/**
 * Normalize multiple relative paths towards the base paths on the right.
 */
function normalize(...aURLs) {
  let base = Services.io.newURI(aURLs.pop());
  let url;
  while ((url = aURLs.pop())) {
    base = Services.io.newURI(url, null, base);
  }
  return base.spec;
}
Example #3
0
AppValidator.prototype._getOriginURL = function () {
  if (this.type == "packaged") {
    let manifestURL = Services.io.newURI(this.manifestURL);
    return Services.io.newURI(".", null, manifestURL).spec;
  } else if (this.type == "hosted") {
    return Services.io.newURI(this.location).prePath;
  }
};
Example #4
0
 isMixedHTTPSRequest: function (request, location) {
   try {
     let requestURI = Services.io.newURI(request);
     let contentURI = Services.io.newURI(location);
     return (contentURI.scheme == "https" && requestURI.scheme != "https");
   } catch (ex) {
     return false;
   }
 },
Example #5
0
 isMixedHTTPSRequest: function WCU_isMixedHTTPSRequest(aRequest, aLocation)
 {
   try {
     let requestURI = Services.io.newURI(aRequest, null, null);
     let contentURI = Services.io.newURI(aLocation, null, null);
     return (contentURI.scheme == "https" && requestURI.scheme != "https");
   }
   catch (ex) {
     return false;
   }
 },
Example #6
0
  resolveRelativeURL: function(url, node) {
    const document = InspectorActorUtils.isNodeDead(node)
                   ? this.window.document
                   : InspectorActorUtils.nodeDocument(node.rawNode);

    if (!document) {
      return url;
    }

    const baseURI = Services.io.newURI(document.location.href);
    return Services.io.newURI(url, null, baseURI).spec;
  },
Example #7
0
  _mapSourceToAddon: function () {
    try {
      var nsuri = Services.io.newURI(this.url.split(" -> ").pop(), null, null);
    }
    catch (e) {
      // We can't do anything with an invalid URI
      return;
    }

    let localURI = resolveURIToLocalPath(nsuri);
    if (!localURI) {
      return;
    }

    let id = mapURIToAddonID(localURI);
    if (!id) {
      return;
    }
    this._addonID = id;

    if (localURI instanceof Ci.nsIJARURI) {
      // The path in the add-on is easy for jar: uris
      this._addonPath = localURI.JAREntry;
    }
    else if (localURI instanceof Ci.nsIFileURL) {
      // For file: uris walk up to find the last directory that is part of the
      // add-on
      let target = localURI.file;
      let path = target.leafName;

      // We can assume that the directory containing the source file is part
      // of the add-on
      let root = target.parent;
      let file = root.parent;
      while (file && mapURIToAddonID(Services.io.newFileURI(file))) {
        path = root.leafName + "/" + path;
        root = file;
        file = file.parent;
      }

      if (!file) {
        const error = new Error("Could not find the root of the add-on for " + this.url);
        DevToolsUtils.reportException("SourceActor.prototype._mapSourceToAddon", error);
        return;
      }

      this._addonPath = path;
    }
  },
Example #8
0
AppValidator.prototype._getPackagedManifestURL = function () {
  let manifestFile = this._getPackagedManifestFile();
  if (!manifestFile) {
    return null;
  }
  return Services.io.newFileURI(manifestFile).spec;
};
Example #9
0
function getSupportsFile(path) {
  let cr = Cc["@mozilla.org/chrome/chrome-registry;1"]
    .getService(Ci.nsIChromeRegistry);
  let uri = Services.io.newURI(CHROME_ROOT + path, null, null);
  let fileurl = cr.convertChromeURL(uri);
  return fileurl.QueryInterface(Ci.nsIFileURL);
}
Example #10
0
  return new Promise((resolve, reject) => {
    try {
      uri = Services.io.newURI(uri, null, null);
    } catch (e) {
      reject(e);
    }

    if (uri.scheme != "resource") {
      reject(new Error(
        "Can only register actors whose URI scheme is 'resource'."));
    }

    NetUtil.asyncFetch(uri, (stream, status, req) => {
      if (!components.isSuccessCode(status)) {
        reject(new Error("Request failed with status code = "
                         + status
                         + " after NetUtil.asyncFetch for url = "
                         + uri));
        return;
      }

      let source = NetUtil.readInputStreamToString(stream, stream.available());
      stream.close();
      resolve(source);
    });
  });
Example #11
0
    exec: function* (args, context) {
      let document = context.environment.document;
      let library = args.library;
      let name = (library.type === "selection") ?
          library.selection.name : library.url;
      let src = (library.type === "selection") ?
          library.selection.src : library.url;

      if (context.environment.window.location.protocol == "https:") {
        src = src.replace(/^http:/, "https:");
      }

      try {
        // Check if URI is valid
        Services.io.newURI(src, null, null);
      } catch (e) {
        return l10n.lookupFormat("injectFailed", [name]);
      }

      let newSource = document.createElement("script");
      newSource.setAttribute("src", src);

      let loadPromise = listenOnce(newSource, "load");
      document.head.appendChild(newSource);

      yield loadPromise;

      return l10n.lookupFormat("injectLoaded", [name]);
    }
Example #12
0
  return new Promise(resolve => {
    // The launch_path field has to start with a `/`
    if (manifest.launch_path && manifest.launch_path[0] !== "/") {
      this.error(strings.formatStringFromName("validator.nonAbsoluteLaunchPath", [manifest.launch_path], 1));
      resolve();
    }
    let origin = this._getOriginURL();
    let path;
    if (this.type == "packaged") {
      path = "." + (manifest.launch_path || "/index.html");
    } else if (this.type == "hosted") {
      path = manifest.launch_path || "/";
    }
    let indexURL;
    try {
      indexURL = Services.io.newURI(path, null, Services.io.newURI(origin)).spec;
    } catch (e) {
      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [origin + path], 1));
      return resolve();
    }

    let req = new XMLHttpRequest();
    req.overrideMimeType("text/plain");
    try {
      req.open("HEAD", indexURL, true);
      req.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIRequest.INHIBIT_CACHING;
    } catch (e) {
      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
      return resolve();
    }
    req.onload = () => {
      if (req.status >= 400)
        this.error(strings.formatStringFromName("validator.accessFailedLaunchPathBadHttpCode", [indexURL, req.status], 2));
      resolve();
    };
    req.onerror = () => {
      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
      resolve();
    };

    try {
      req.send(null);
    } catch (e) {
      this.error(strings.formatStringFromName("validator.accessFailedLaunchPath", [indexURL], 1));
      resolve();
    }
  });
Example #13
0
exports.joinURI = (initialPath, ...paths) => {
  let uri;

  try {
    uri = Services.io.newURI(initialPath, null, null);
  }
  catch(e) {
    return;
  }

  for(let path of paths) {
    if (path) {
      uri = Services.io.newURI(path, null, uri);
    }
  }

  return uri.spec;
}
Example #14
0
  nsIURL: function (url, store = gNSURLStore) {
    if (store.has(url)) {
      return store.get(url);
    }

    let uri = Services.io.newURI(url).QueryInterface(Ci.nsIURL);
    store.set(url, uri);
    return uri;
  }
Example #15
0
/**
 * Returns the full path of the file with the specified name in a
 * platform-independent and URL-like form.
 */
function getFilePath(aName, aAllowMissing=false) {
  let file = do_get_file(aName, aAllowMissing);
  let path = Services.io.newFileURI(file).spec;
  let filePrePath = "file://";
  if ("nsILocalFileWin" in Ci &&
      file instanceof Ci.nsILocalFileWin) {
    filePrePath += "/";
  }
  return path.slice(filePrePath.length);
}
Example #16
0
/**
 * Opens a channel for given URL. Tries a bit harder than NetUtil.newChannel.
 *
 * @param {String} url - The URL to open a channel for.
 * @param {Object} options - The options object passed to @method fetch.
 * @return {nsIChannel} - The newly created channel. Throws on failure.
 */
function newChannelForURL(url, { policy, window, principal }) {
  let securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;

  let uri;
  try {
    uri = Services.io.newURI(url);
  } catch (e) {
    // In the xpcshell tests, the script url is the absolute path of the test
    // file, which will make a malformed URI error be thrown. Add the file
    // scheme to see if it helps.
    uri = Services.io.newURI("file://" + url);
  }
  let channelOptions = {
    contentPolicyType: policy,
    securityFlags: securityFlags,
    uri: uri
  };
  let prin = principal;
  if (!prin) {
    let oa = {};
    if (window) {
      oa = window.document.nodePrincipal.originAttributes;
    }
    prin = Services.scriptSecurityManager
                   .createCodebasePrincipal(uri, oa);
  }
  // contentPolicyType is required when specifying a principal
  if (!channelOptions.contentPolicyType) {
    channelOptions.contentPolicyType = Ci.nsIContentPolicy.TYPE_OTHER;
  }
  channelOptions.loadingPrincipal = prin;

  try {
    return NetUtil.newChannel(channelOptions);
  } catch (e) {
    // In xpcshell tests on Windows, nsExternalProtocolHandler::NewChannel()
    // can throw NS_ERROR_UNKNOWN_PROTOCOL if the external protocol isn't
    // supported by Windows, so we also need to handle the exception here if
    // parsing the URL above doesn't throw.
    return newChannelForURL("file://" + url, { policy, window, principal });
  }
}
// Show a warning message in the webconsole when an extension
// eval request has been denied, so that the user knows about it
// even if the extension doesn't report the error itself.
function logAccessDeniedWarning(window, callerInfo, extensionPolicy) {
  // Do not log the same warning multiple times for the same document.
  if (deniedWarningDocuments.has(window.document)) {
    return;
  }

  deniedWarningDocuments.add(window.document);

  const {name} = extensionPolicy;

  // System principals have a null nodePrincipal.URI and so we use
  // the url from window.location.href.
  const reportedURI = isSystemPrincipalWindow(window) ?
    Services.io.newURI(window.location.href) : window.document.nodePrincipal.URI;

  const error = Cc["@mozilla.org/scripterror;1"].createInstance(Ci.nsIScriptError);

  const msg = `The extension "${name}" is not allowed to access ${reportedURI.spec}`;

  const innerWindowId = window.windowUtils.currentInnerWindowID;

  const errorFlag = 0;

  let {url, lineNumber} = callerInfo;

  const callerURI = callerInfo.url && Services.io.newURI(callerInfo.url);

  // callerInfo.url is not the full path to the file that called the WebExtensions
  // API yet (Bug 1448878), and so we associate the error to the url of the extension
  // manifest.json file as a fallback.
  if (callerURI.filePath === "/") {
    url = extensionPolicy.getURL("/manifest.json");
    lineNumber = null;
  }

  error.initWithWindowID(msg, url, lineNumber, 0, 0, errorFlag, "webExtensions",
                         innerWindowId);
  Services.console.logMessage(error);
}
function createFakeAddonWindow({addonId} = {}) {
  let baseURI = Services.io.newURI("about:blank", null, null);
  let originAttributes = {addonId};
  let principal = Services.scriptSecurityManager
        .createCodebasePrincipal(baseURI, originAttributes);
  let chromeWebNav = Services.appShell.createWindowlessBrowser(true);
  let docShell = chromeWebNav.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDocShell);
  docShell.createAboutBlankContentViewer(principal);
  let addonWindow = docShell.contentViewer.DOMDocument.defaultView;

  return {addonWindow, chromeWebNav};
}
Example #19
0
/**
 * Returns the full path of the file with the specified name in a
 * platform-independent and URL-like form.
 */
function getFilePath(name, allowMissing = false, usePlatformPathSeparator = false) {
  const file = do_get_file(name, allowMissing);
  let path = Services.io.newFileURI(file).spec;
  let filePrePath = "file://";
  if ("nsILocalFileWin" in Ci &&
      file instanceof Ci.nsILocalFileWin) {
    filePrePath += "/";
  }

  path = path.slice(filePrePath.length);

  if (usePlatformPathSeparator && path.match(/^\w:/)) {
    path = path.replace(/\//g, "\\");
  }

  return path;
}
Example #20
0
webExtensionTargetPrototype._allowSource = function(source) {
  // Use the source.element to detect the allowed source, if any.
  if (source.element) {
    const domEl = unwrapDebuggerObjectGlobal(source.element);
    return (this.isExtensionWindow(domEl.ownerGlobal) ||
            this.isExtensionWindowDescendent(domEl.ownerGlobal));
  }

  // Fallback to check the uri if there is no source.element associated to the source.

  // Retrieve the first component of source.url in the form "url1 -> url2 -> ...".
  const url = source.url.split(" -> ").pop();

  // Filter out the code introduced by evaluating code in the webconsole.
  if (url === "debugger eval code") {
    return false;
  }

  let uri;

  // Try to decode the url.
  try {
    uri = Services.io.newURI(url);
  } catch (err) {
    Cu.reportError(`Unexpected invalid url: ${url}`);
    return false;
  }

  // Filter out resource and chrome sources (which are related to the loaded internals).
  if (["resource", "chrome", "file"].includes(uri.scheme)) {
    return false;
  }

  try {
    const addonID = this.aps.extensionURIToAddonId(uri);

    return addonID == this.addonId;
  } catch (err) {
    // extensionURIToAddonId raises an exception on non-extension URLs.
    return false;
  }
};
Example #21
0
  _shouldAddNewGlobalAsDebuggee: function (aGlobal) {
    const global = unwrapDebuggerObjectGlobal(aGlobal);
    try {
      // This will fail for non-Sandbox objects, hence the try-catch block.
      let metadata = Cu.getSandboxMetadata(global);
      if (metadata) {
        return metadata.addonID === this.id;
      }
    } catch (e) {}

    if (global instanceof Ci.nsIDOMWindow) {
      let id = {};
      if (mapURIToAddonID(global.document.documentURIObject, id)) {
        return id.value === this.id;
      }
      return false;
    }

    // Check the global for a __URI__ property and then try to map that to an
    // add-on
    let uridescriptor = aGlobal.getOwnPropertyDescriptor("__URI__");
    if (uridescriptor && "value" in uridescriptor && uridescriptor.value) {
      let uri;
      try {
        uri = Services.io.newURI(uridescriptor.value, null, null);
      }
      catch (e) {
        DevToolsUtils.reportException(
          "BrowserAddonActor.prototype._shouldAddNewGlobalAsDebuggee",
          new Error("Invalid URI: " + uridescriptor.value)
        );
        return false;
      }

      let id = {};
      if (mapURIToAddonID(uri, id)) {
        return id.value === this.id;
      }
    }

    return false;
  },
Example #22
0
AppValidator.prototype._getManifest = function () {
  let manifestURL;
  if (this.type == "packaged") {
    manifestURL = this._getPackagedManifestURL();
    if (!manifestURL)
      return Promise.resolve(null);
  } else if (this.type == "hosted") {
    manifestURL = this.location;
    try {
      Services.io.newURI(manifestURL);
    } catch (e) {
      this.error(strings.formatStringFromName("validator.invalidHostedManifestURL", [manifestURL, e.message], 2));
      return Promise.resolve(null);
    }
  } else {
    this.error(strings.formatStringFromName("validator.invalidProjectType", [this.type], 1));
    return Promise.resolve(null);
  }
  return this._fetchManifest(manifestURL);
};
Example #23
0
/**
 * Resolve a URI back to physical file.
 *
 * Of course, this works only for URIs pointing to local resources.
 *
 * @param  uri
 *         URI to resolve
 * @return
 *         resolved nsIURI
 */
function resolveURIToLocalPath(uri) {
  let resolved;
  switch (uri.scheme) {
    case "jar":
    case "file":
      return uri;

    case "chrome":
      resolved = Cc["@mozilla.org/chrome/chrome-registry;1"]
                  .getService(Ci.nsIChromeRegistry).convertChromeURL(uri);
      return resolveURIToLocalPath(resolved);

    case "resource":
      resolved = Cc["@mozilla.org/network/protocol;1?name=resource"]
                  .getService(Ci.nsIResProtocolHandler).resolveURI(uri);
      uri = Services.io.newURI(resolved);
      return resolveURIToLocalPath(uri);

    default:
      return null;
  }
}
/**
 * Restore the default bookmarks for the current profile
 */
function restoreDefaultBookmarks() {
  const TOPIC_BOOKMARKS_RESTORE_SUCCESS = "bookmarks-restore-success";
  const BOOKMARKS_RESOURCE = "resource:///defaults/profile/bookmarks.html";

  // In theory, could take a long time to finish. In practice never seems to.
  const BOOKMARKS_TIMEOUT = 10000;

  // Set up the observer -- we're only checking for success here, so we'll simply
  // time out and throw on failure. It makes the code much clearer than handling
  // finished state and success state separately.
  var importObserver = {
    observe: function (aSubject, aTopic, aData) {
      if (aTopic === TOPIC_BOOKMARKS_RESTORE_SUCCESS)
        this.success = true;
    },
    success: false
  }

  services.obs.addObserver(importObserver, TOPIC_BOOKMARKS_RESTORE_SUCCESS, false);
  try {
    // newURI requires all params to be supplied, even if undefined.
    var bookmarksURI = services.io.newURI(BOOKMARKS_RESOURCE, undefined, undefined);

    // Fire off the import
    services.placesImportExport.importHTMLFromURI(bookmarksURI, true);

    // Wait for it to be finished--the observer above will flip this flag
    driver.waitFor(function () {
      return importObserver.success;
    }, "Default bookmarks have finished importing", BOOKMARKS_TIMEOUT);
  }
  finally {
    // Whatever happens, remove the observer afterwards
    services.obs.removeObserver(importObserver, TOPIC_BOOKMARKS_RESTORE_SUCCESS);
  }
}
Example #25
0
  return new Promise((resolve, reject) => {
    try {
      uri = Services.io.newURI(uri, null, null);
    } catch (e) {
      reject(e);
    }

    NetUtil.asyncFetch({
      uri,
      loadUsingSystemPrincipal: true,
     }, (stream, status, req) => {
      if (!components.isSuccessCode(status)) {
        reject(new Error("Request failed with status code = "
                         + status
                         + " after NetUtil.asyncFetch for url = "
                         + uri));
        return;
      }

      let source = NetUtil.readInputStreamToString(stream, stream.available());
      stream.close();
      resolve(source);
    });
  });
Example #26
0
/**
 * Save the screenshot data to disk, returning a promise which is resolved on
 * completion.
 *
 * @param object image
 *        The image object that was sent from the server.
 *
 * @return string
 *         Response message from processing the screenshot.
 */
async function saveToFile(image) {
  let filename = image.filename;

  // Check there is a .png extension to filename
  if (!filename.match(/.png$/i)) {
    filename += ".png";
  }

  const downloadsDir = await Downloads.getPreferredDownloadsDirectory();
  const downloadsDirExists = await OS.File.exists(downloadsDir);
  if (downloadsDirExists) {
    // If filename is absolute, it will override the downloads directory and
    // still be applied as expected.
    filename = OS.Path.join(downloadsDir, filename);
  }

  const sourceURI = Services.io.newURI(image.data);
  const targetFile = new FileUtils.File(filename);

  // Create download and track its progress.
  try {
    const download = await Downloads.createDownload({
      source: sourceURI,
      target: targetFile
    });
    const list = await Downloads.getList(Downloads.ALL);
    // add the download to the download list in the Downloads list in the Browser UI
    list.add(download);
    // Await successful completion of the save via the download manager
    await download.start();
    return L10N.getFormatStr("screenshotSavedToFile", filename);
  } catch (ex) {
    console.error(ex);
    return L10N.getFormatStr("screenshotErrorSavingToFile", filename);
  }
}
Example #27
0
function getHostedURL(window, location) {
  const ret = { value: null };

  if (!location) {
    Services.prompt.prompt(window,
        Strings.GetStringFromName("importHostedApp_title"),
        Strings.GetStringFromName("importHostedApp_header"),
        ret, null, {});
    location = ret.value;
  }

  if (!location) {
    return null;
  }

  // Clean location string and add "http://" if missing
  location = location.trim();
  try { // Will fail if no scheme
    Services.io.extractScheme(location);
  } catch (e) {
    location = "http://" + location;
  }
  return location;
}
 newChannel: function(aURI, aLoadInfo) {
   let chan = Services.io.newChannelFromURIWithLoadInfo(this.uri, aLoadInfo);
   chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
   return chan;
 },
"use strict";

// Register about:devtools-toolbox which allows to open a devtools toolbox
// in a Firefox tab or a custom html iframe in browser.html

const { Ci, Cu, Cm, components } = require("chrome");
const registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
const Services = require("Services");
const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
const { nsIAboutModule } = Ci;

function AboutURL() {}

AboutURL.prototype = {
  uri: Services.io.newURI("chrome://devtools/content/framework/toolbox.xul",
                          null, null),
  classDescription: "about:devtools-toolbox",
  classID: components.ID("11342911-3135-45a8-8d71-737a2b0ad469"),
  contractID: "@mozilla.org/network/protocol/about;1?what=devtools-toolbox",

  QueryInterface: XPCOMUtils.generateQI([nsIAboutModule]),

  newChannel: function(aURI, aLoadInfo) {
    let chan = Services.io.newChannelFromURIWithLoadInfo(this.uri, aLoadInfo);
    chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
    return chan;
  },

  getURIFlags: function(aURI) {
    return nsIAboutModule.ALLOW_SCRIPT || nsIAboutModule.ENABLE_INDEXED_DB;
  }
function dirname(aPath) {
  return Services.io.newURI(
    ".", null, Services.io.newURI(aPath)).spec;
}