Skip to content

Commit

Permalink
Bug 21952: Onion-location UI
Browse files Browse the repository at this point in the history
  • Loading branch information
acatarineu committed Nov 29, 2019
1 parent 3a9929a commit 0721f13
Show file tree
Hide file tree
Showing 17 changed files with 396 additions and 0 deletions.
3 changes: 3 additions & 0 deletions browser/base/content/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
NetUtil: "resource://gre/modules/NetUtil.jsm",
NewTabUtils: "resource://gre/modules/NewTabUtils.jsm",
OpenInTabsUtils: "resource:///modules/OpenInTabsUtils.jsm",
OnionLocationParent: "resource:///modules/OnionLocationParent.jsm",
PageActions: "resource:///modules/PageActions.jsm",
PageThumbs: "resource://gre/modules/PageThumbs.jsm",
PanelMultiView: "resource:///modules/PanelMultiView.jsm",
Expand Down Expand Up @@ -5771,6 +5772,7 @@ var XULBrowserWindow = {
if (aRequest && aWebProgress.isTopLevel) {
// clear out search-engine data
browser.engines = null;
OnionLocationParent.onStateChange(browser);
}

this.isBusy = true;
Expand Down Expand Up @@ -5920,6 +5922,7 @@ var XULBrowserWindow = {
Services.obs.notifyObservers(null, "touchbar-location-change", location);
UpdateBackForwardCommands(gBrowser.webNavigation);
ReaderParent.updateReaderButton(gBrowser.selectedBrowser);
OnionLocationParent.updateOnionLocationBadge(gBrowser.selectedBrowser);

if (!gMultiProcessBrowser) {
// Bug 1108553 - Cannot rotate images with e10s
Expand Down
3 changes: 3 additions & 0 deletions browser/base/content/browser.xul
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,9 @@
onclick="FullZoom.reset();"
tooltip="dynamic-shortcut-tooltip"
hidden="true"/>

#include ../../components/onionlocation/content/onionlocation-urlbar.inc.xul

<box id="pageActionSeparator" class="urlbar-page-action"/>
<image id="pageActionButton"
class="urlbar-icon urlbar-page-action"
Expand Down
9 changes: 9 additions & 0 deletions browser/components/BrowserGlue.jsm
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ let LEGACY_ACTORS = {
},
},

OnionLocation: {
child: {
module: "resource:///modules/OnionLocationChild.jsm",
events: { pageshow: {} },
},
},

PageInfo: {
child: {
module: "resource:///actors/PageInfoChild.jsm",
Expand Down Expand Up @@ -507,6 +514,7 @@ XPCOMUtils.defineLazyModuleGetters(this, {
ContentClick: "resource:///modules/ContentClick.jsm",
FormValidationHandler: "resource:///modules/FormValidationHandler.jsm",
LoginManagerParent: "resource://gre/modules/LoginManagerParent.jsm",
OnionLocationParent: "resource:///modules/OnionLocationParent.jsm",
PictureInPicture: "resource://gre/modules/PictureInPicture.jsm",
ReaderParent: "resource:///modules/ReaderParent.jsm",
RemotePrompt: "resource:///modules/RemotePrompt.jsm",
Expand Down Expand Up @@ -605,6 +613,7 @@ const listeners = {
ContentSearch: ["ContentSearch"],
"FormValidation:ShowPopup": ["FormValidationHandler"],
"FormValidation:HidePopup": ["FormValidationHandler"],
"OnionLocation:Set": ["OnionLocationParent"],
"PictureInPicture:Request": ["PictureInPicture"],
"PictureInPicture:Close": ["PictureInPicture"],
"PictureInPicture:Playing": ["PictureInPicture"],
Expand Down
1 change: 1 addition & 0 deletions browser/components/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ DIRS += [
'library',
'migration',
'newtab',
'onionlocation',
'originattributes',
'places',
'pocket',
Expand Down
52 changes: 52 additions & 0 deletions browser/components/onionlocation/OnionLocationChild.jsm
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use strict";

var EXPORTED_SYMBOLS = ["OnionLocationChild"];

const { ActorChild } = ChromeUtils.import(
"resource://gre/modules/ActorChild.jsm"
);

const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");

function isValidOnionLocation(onionLocation) {
if (typeof onionLocation === "string" && onionLocation) {
try {
let URI = Services.io.newURI(onionLocation);
if (
(URI.scheme === "https" || URI.scheme === "http") &&
URI.host.endsWith(".onion")
) {
return true;
}
} catch (e) {}
}
return false;
}

function isSecureChannel(channel) {
try {
return channel.URI.scheme === "https";
} catch (e) {}
return false;
}

class OnionLocationChild extends ActorChild {
handleEvent(event) {
this.onPageShow(event);
}

onPageShow(event) {
if (event.target != this.content.document) {
return;
}

let channel = this.mm.docShell.currentDocumentChannel;
try {
let httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
let onionLocation = httpChannel.getResponseHeader("Onion-Location");
if (isSecureChannel(httpChannel) && isValidOnionLocation(onionLocation)) {
this.mm.sendAsyncMessage("OnionLocation:Set", onionLocation);
}
} catch (e) {}
}
}
164 changes: 164 additions & 0 deletions browser/components/onionlocation/OnionLocationParent.jsm
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
"use strict";

var EXPORTED_SYMBOLS = ["OnionLocationParent"];

const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { TorStrings } = ChromeUtils.import("resource:///modules/TorStrings.jsm");

// Prefs
const ONIONLOCATION_PREF = "privacy.prioritizeonions.enabled";
const NOTIFICATION_PREF = "privacy.prioritizeonions.notification";

// Element IDs
const ONIONLOCATION_BOX_ID = "onion-location-box";
const ONIONLOCATION_BUTTON_ID = "onion-location-button";
const ONIONLOCATION_LABEL_ID = "onion-label";

// Notification IDs
const NOTIFICATION_ID = "onion-location";
const NOTIFICATION_ANCHOR_ID = "onionlocation";

// Strings
const STRING_ONION_AVAILABLE = TorStrings.onionLocation.onionAvailable;
const NOTIFICATION_CANCEL_LABEL = TorStrings.onionLocation.notNow;
const NOTIFICATION_CANCEL_ACCESSKEY = TorStrings.onionLocation.notNowAccessKey;
const NOTIFICATION_OK_LABEL = TorStrings.onionLocation.alwaysPrioritize;
const NOTIFICATION_OK_ACCESSKEY =
TorStrings.onionLocation.alwaysPrioritizeAccessKey;
const NOTIFICATION_TITLE = TorStrings.onionLocation.tryThis;
const NOTIFICATION_DESCRIPTION = TorStrings.onionLocation.description;
const NOTIFICATION_LEARN_MORE_URL = TorStrings.onionLocation.learnMoreURL;

var OnionLocationParent = {
// Listeners are added in BrowserGlue.jsm
receiveMessage(aMsg) {
switch (aMsg.name) {
case "OnionLocation:Set":
this.setOnionLocation(aMsg.target, aMsg.data);
break;
}
},

buttonClick(event) {
if (event.button != 0) {
return;
}
let win = event.target.ownerGlobal;
let browser = win.gBrowser.selectedBrowser;
this.redirect(browser);
},

redirect(browser) {
let win = browser.ownerGlobal;
this.hideNotification(browser);
win.BrowserReloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_ONION_REDIRECT);
this.setDisabled(browser);
},

onStateChange(browser) {
delete browser._onionLocation;
this.hideNotification(browser);
},

setOnionLocation(browser, aURL) {
let win = browser.ownerGlobal;
if (browser != win.gBrowser.selectedBrowser) {
return;
}
browser._onionLocation = aURL;
this.updateOnionLocationBadge(browser);
},

hideNotification(browser) {
let win = browser.ownerGlobal;
if (browser._onionLocationPrompt) {
win.PopupNotifications.remove(browser._onionLocationPrompt);
}
},

showNotification(browser) {
let win = browser.ownerGlobal;
let seen = Services.prefs.getBoolPref(NOTIFICATION_PREF, false);

if (seen) {
return;
}

Services.prefs.setBoolPref(NOTIFICATION_PREF, true);

let mainAction = {
label: NOTIFICATION_OK_LABEL,
accessKey: NOTIFICATION_OK_ACCESSKEY,
callback() {
Services.prefs.setBoolPref(ONIONLOCATION_PREF, true);
OnionLocationParent.redirect(browser);
},
};

let cancelAction = {
label: NOTIFICATION_CANCEL_LABEL,
accessKey: NOTIFICATION_CANCEL_ACCESSKEY,
callback: () => {},
};

let options = {
autofocus: true,
persistent: true,
removeOnDismissal: false,
eventCallback(aTopic) {
if (aTopic === "removed") {
delete browser._onionLocationPrompt;
delete browser.onionpopupnotificationanchor;
}
},
learnMoreURL: NOTIFICATION_LEARN_MORE_URL,
displayURI: {
hostPort: NOTIFICATION_TITLE, // This is hacky, but allows us to have a title without extra markup/css.
},
};

// A hacky way of setting the popup anchor outside the usual url bar icon box
// onionlocationpopupnotificationanchor comes from `${ANCHOR_ID}popupnotificationanchor`
// From https://searchfox.org/mozilla-esr68/rev/080f9ed47742644d2ff84f7aa0b10aea5c44301a/browser/components/newtab/lib/CFRPageActions.jsm#488
browser.onionlocationpopupnotificationanchor = win.document.getElementById(
ONIONLOCATION_BUTTON_ID
);

browser._onionLocationPrompt = win.PopupNotifications.show(
browser,
NOTIFICATION_ID,
NOTIFICATION_DESCRIPTION,
NOTIFICATION_ANCHOR_ID,
mainAction,
[cancelAction],
options
);
},

setEnabled(browser) {
let win = browser.ownerGlobal;
let label = win.document.getElementById(ONIONLOCATION_LABEL_ID);
label.textContent = STRING_ONION_AVAILABLE;
let elem = win.document.getElementById(ONIONLOCATION_BOX_ID);
elem.removeAttribute("hidden");
},

setDisabled(browser) {
let win = browser.ownerGlobal;
let elem = win.document.getElementById(ONIONLOCATION_BOX_ID);
elem.setAttribute("hidden", true);
},

updateOnionLocationBadge(browser) {
let win = browser.ownerGlobal;
if (browser != win.gBrowser.selectedBrowser) {
return;
}
if (browser._onionLocation) {
this.setEnabled(browser);
this.showNotification(browser);
} else {
this.setDisabled(browser);
}
},
};
25 changes: 25 additions & 0 deletions browser/components/onionlocation/content/onionlocation-urlbar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#onion-location-button {
list-style-image: url(chrome://browser/content/onionlocation/onionlocation.svg);
}

#onion-location-box {
border-radius: 3px;
background-color: #6200A4;
padding-left: 5px;
padding-right: 5px;
color: white;
-moz-context-properties: fill;
fill: white;
}

#onion-location-box:hover {
background-color: #0060DF!important;
}

toolbar[brighttext] #onion-location-box {
background-color: #9400ff;
}

toolbar[brighttext] #onion-location-box:hover {
background-color: #0060DF!important;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<hbox id="onion-location-box"
class="urlbar-icon-wrapper urlbar-page-action"
role="button"
hidden="true"
onclick="OnionLocationParent.buttonClick(event);">
<image id="onion-location-button" role="presentation"/>
<hbox id="onion-label-container"><label id="onion-label"/></hbox>
</hbox>
8 changes: 8 additions & 0 deletions browser/components/onionlocation/content/onionlocation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<groupbox id="onionServicesGroup" data-category="panePrivacy" data-subcategory="onionservices">
<label><html:h2 id="onionServicesTitle"></html:h2></label>
<label><label class="tail-with-learn-more" id="prioritizeOnionsDesc"></label><label
class="learnMore" is="text-link" id="onionServicesLearnMore"></label></label>
<radiogroup id="prioritizeOnionsRadioGroup" aria-labelledby="prioritizeOnionsDesc" preference="privacy.prioritizeonions.enabled">
<radio id="onionServicesRadioAlways" value="true"/>
<radio id="onionServicesRadioAsk" value="false"/>
</radiogroup>
</groupbox>
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"use strict";

ChromeUtils.defineModuleGetter(
this,
"TorStrings",
"resource:///modules/TorStrings.jsm"
);

const OnionLocationPreferences = {
init() {
document.getElementById("onionServicesTitle").textContent =
TorStrings.onionLocation.onionServicesTitle;
document.getElementById("prioritizeOnionsDesc").textContent =
TorStrings.onionLocation.prioritizeOnionsDescription;
let learnMore = document.getElementById("onionServicesLearnMore");
learnMore.textContent = TorStrings.onionLocation.learnMore;
learnMore.href = TorStrings.onionLocation.learnMoreURL;
document.getElementById("onionServicesRadioAlways").label =
TorStrings.onionLocation.always;
document.getElementById("onionServicesRadioAsk").label =
TorStrings.onionLocation.askEverytime;
},
};

Object.defineProperty(this, "OnionLocationPreferences", {
value: OnionLocationPreferences,
enumerable: true,
writable: false,
});
3 changes: 3 additions & 0 deletions browser/components/onionlocation/jar.mn
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
browser.jar:
content/browser/onionlocation/onionlocationPreferences.js (content/onionlocationPreferences.js)
content/browser/onionlocation/onionlocation.svg (content/onionlocation.svg)
6 changes: 6 additions & 0 deletions browser/components/onionlocation/moz.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
JAR_MANIFESTS += ['jar.mn']

EXTRA_JS_MODULES += [
'OnionLocationChild.jsm',
'OnionLocationParent.jsm',
]
Loading

0 comments on commit 0721f13

Please sign in to comment.