Commit 89856ed1 authored by Alex Catarineu's avatar Alex Catarineu Committed by Matthew Finkel
Browse files

Bug 28005: Implement .onion alias urlbar rewrites

A custom HTTPS Everywhere update channel is installed,
which provides rules for locally redirecting some memorable
.tor.onion URLs to non-memorable .onion URLs.

When these redirects occur, we also rewrite the URL in the urlbar
to display the human-memorable hostname instead of the actual
.onion.

Bug 34196: Update site info URL with the onion name
parent fae5a676
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -136,6 +136,26 @@ class ClickHandlerChild extends JSWindowActorChild {
      json.originStoragePrincipal = ownerDoc.effectiveStoragePrincipal;
      json.triggeringPrincipal = ownerDoc.nodePrincipal;

      // Check if the link needs to be opened with .tor.onion urlbar rewrites
      // allowed. Only when the owner doc has onionUrlbarRewritesAllowed = true
      // and the same origin we should allow this.
      json.onionUrlbarRewritesAllowed = false;
      if (this.docShell.onionUrlbarRewritesAllowed) {
        const sm = Services.scriptSecurityManager;
        try {
          let targetURI = Services.io.newURI(href);
          let isPrivateWin =
            ownerDoc.nodePrincipal.originAttributes.privateBrowsingId > 0;
          sm.checkSameOriginURI(
            docshell.currentDocumentChannel.URI,
            targetURI,
            false,
            isPrivateWin
          );
          json.onionUrlbarRewritesAllowed = true;
        } catch (e) {}
      }

      // If a link element is clicked with middle button, user wants to open
      // the link somewhere rather than pasting clipboard content.  Therefore,
      // when it's clicked with middle button, we should prevent multiple
+1 −0
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ class ClickHandlerParent extends JSWindowActorParent {
      charset: browser.characterSet,
      referrerInfo: E10SUtils.deserializeReferrerInfo(data.referrerInfo),
      allowMixedContent: data.allowMixedContent,
      onionUrlbarRewritesAllowed: data.onionUrlbarRewritesAllowed,
      isContentWindowPrivate: data.isContentWindowPrivate,
      originPrincipal: data.originPrincipal,
      originStoragePrincipal: data.originStoragePrincipal,
+4 −0
Original line number Diff line number Diff line
@@ -576,6 +576,9 @@ class ContextMenuChild extends JSWindowActorChild {
    // The same-origin check will be done in nsContextMenu.openLinkInTab.
    let parentAllowsMixedContent = !!this.docShell.mixedContentChannel;

    let parentAllowsOnionUrlbarRewrites = this.docShell
      .onionUrlbarRewritesAllowed;

    let disableSetDesktopBackground = null;

    // Media related cache info parent needs for saving
@@ -688,6 +691,7 @@ class ContextMenuChild extends JSWindowActorChild {
      frameBrowsingContextID,
      disableSetDesktopBackground,
      parentAllowsMixedContent,
      parentAllowsOnionUrlbarRewrites,
    };

    if (context.inFrame && !context.inSrcdocFrame) {
+8 −4
Original line number Diff line number Diff line
@@ -486,7 +486,8 @@ var PlacesCommandHook = {
   */
  async bookmarkPage() {
    let browser = gBrowser.selectedBrowser;
    let url = new URL(browser.currentURI.spec);
    const uri = browser.currentOnionAliasURI || browser.currentURI;
    let url = new URL(uri.spec);
    let info = await PlacesUtils.bookmarks.fetch({ url });
    let isNewBookmark = !info;
    let showEditUI = !isNewBookmark || StarUI.showForNewBookmarks;
@@ -594,7 +595,7 @@ var PlacesCommandHook = {

    tabs.forEach(tab => {
      let browser = tab.linkedBrowser;
      let uri = browser.currentURI;
      let uri = browser.currentOnionAliasURI || browser.currentURI;
      let title = browser.contentTitle || tab.label;
      let spec = uri.spec;
      if (!(spec in uniquePages)) {
@@ -1917,14 +1918,17 @@ var BookmarkingUI = {
  },

  onLocationChange: function BUI_onLocationChange() {
    if (this._uri && gBrowser.currentURI.equals(this._uri)) {
    const uri =
      gBrowser.selectedBrowser.currentOnionAliasURI || gBrowser.currentURI;
    if (this._uri && uri.equals(this._uri)) {
      return;
    }
    this.updateStarState();
  },

  updateStarState: function BUI_updateStarState() {
    this._uri = gBrowser.currentURI;
    this._uri =
      gBrowser.selectedBrowser.currentOnionAliasURI || gBrowser.currentURI;
    this._itemGuids.clear();
    let guids = new Set();

+7 −5
Original line number Diff line number Diff line
@@ -689,13 +689,13 @@ var gIdentityHandler = {
   *        nsIURI for which the identity UI should be displayed, already
   *        processed by createExposableURI.
   */
  updateIdentity(state, uri) {
  updateIdentity(state, uri, onionAliasURI) {
    let shouldHidePopup = this._uri && this._uri.spec != uri.spec;
    this._state = state;

    // Firstly, populate the state properties required to display the UI. See
    // the documentation of the individual properties for details.
    this.setURI(uri);
    this.setURI(uri, onionAliasURI);
    this._secInfo = gBrowser.securityUI.secInfo;
    this._isSecureContext = gBrowser.securityUI.isSecureContext;

@@ -781,17 +781,18 @@ var gIdentityHandler = {
   * Attempt to provide proper IDN treatment for host names
   */
  getEffectiveHost() {
    let uri = this._onionAliasURI || this._uri;
    if (!this._IDNService) {
      this._IDNService = Cc["@mozilla.org/network/idn-service;1"].getService(
        Ci.nsIIDNService
      );
    }
    try {
      return this._IDNService.convertToDisplayIDN(this._uri.host, {});
      return this._IDNService.convertToDisplayIDN(uri.host, {});
    } catch (e) {
      // If something goes wrong (e.g. host is an IP address) just fail back
      // to the full domain.
      return this._uri.host;
      return uri.host;
    }
  },

@@ -1268,11 +1269,12 @@ var gIdentityHandler = {
    this.updateSitePermissions();
  },

  setURI(uri) {
  setURI(uri, onionAliasURI) {
    if (uri.schemeIs("view-source")) {
      uri = Services.io.newURI(uri.spec.replace(/^view-source:/i, ""));
    }
    this._uri = uri;
    this._onionAliasURI = onionAliasURI;

    try {
      // Account for file: urls and catch when "" is the value
Loading