Bug 967895 - Prompt (w/ Site Permission) before allowing content to extract canvas data (Tor 6253).
MozReview-Commit-ID: 91eeagGmUXv
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1459,16 +1459,17 @@ var gBrowserInit = {
Services.obs.addObserver(gXPInstallObserver, "addon-install-origin-blocked");
Services.obs.addObserver(gXPInstallObserver, "addon-install-failed");
Services.obs.addObserver(gXPInstallObserver, "addon-install-confirmation");
Services.obs.addObserver(gXPInstallObserver, "addon-install-complete");
window.messageManager.addMessageListener("Browser:URIFixup", gKeywordURIFixup);
BrowserOffline.init();
IndexedDBPromptHelper.init();
+ CanvasPermissionPromptHelper.init();
if (AppConstants.E10S_TESTING_ONLY)
gRemoteTabsUI.init();
// Initialize the full zoom setting.
// We do this before the session restore service gets initialized so we can
// apply full zoom settings to tabs restored by the session restore service.
FullZoom.init();
@@ -1892,16 +1893,17 @@ var gBrowserInit = {
Cu.reportError(ex);
}
if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
MenuTouchModeObserver.uninit();
}
BrowserOffline.uninit();
IndexedDBPromptHelper.uninit();
+ CanvasPermissionPromptHelper.uninit();
PanelUI.uninit();
AutoShowBookmarksToolbar.uninit();
}
// Final window teardown, do this last.
window.XULBrowserWindow = null;
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
@@ -6664,16 +6666,92 @@ var IndexedDBPromptHelper = {
browser, topic, message, this._notificationIcon, mainAction, secondaryActions,
{
persistent: true,
hideClose: !Services.prefs.getBoolPref("privacy.permissionPrompts.showCloseButton"),
});
}
};
+var CanvasPermissionPromptHelper = {
+ _permissionsPrompt: "canvas-permissions-prompt",
+ _notificationIcon: "canvas-notification-icon",
+
+ init() {
+ Services.obs.addObserver(this, this._permissionsPrompt);
+ },
+
+ uninit() {
+ Services.obs.removeObserver(this, this._permissionsPrompt);
+ },
+
+ // aSubject is an nsIBrowser (e10s) or an nsIDOMWindow (non-e10s).
+ // aData is an URL string.
+ observe(aSubject, aTopic, aData) {
+ if (aTopic != this._permissionsPrompt) {
+ return;
+ }
+
+ let browser;
+ if (aSubject instanceof Ci.nsIDOMWindow) {
+ let contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
+ browser = gBrowser.getBrowserForContentWindow(contentWindow);
+ } else {
+ browser = aSubject.QueryInterface(Ci.nsIBrowser);
+ }
+
+ let uri = Services.io.newURI(aData);
+ if (gBrowser.selectedBrowser !== browser) {
+ // Must belong to some other window.
+ return;
+ }
+
+ let message = gNavigatorBundle.getFormattedString("canvas.siteprompt", [ uri.asciiHost ]);
+
+ function setCanvasPermission(aURI, aPerm, aPersistent) {
+ Services.perms.add(aURI, "canvas/extractData", aPerm,
+ aPersistent ? Ci.nsIPermissionManager.EXPIRE_NEVER
+ : Ci.nsIPermissionManager.EXPIRE_SESSION);
+ }
+
+ let mainAction = {
+ label: gNavigatorBundle.getString("canvas.allow"),
+ accessKey: gNavigatorBundle.getString("canvas.allow.accesskey"),
+ callback(state) {
+ setCanvasPermission(uri, Ci.nsIPermissionManager.ALLOW_ACTION,
+ state && state.checkboxChecked);
+ }
+ };
+
+ let secondaryActions = [{
+ label: gNavigatorBundle.getString("canvas.notAllow"),
+ accessKey: gNavigatorBundle.getString("canvas.notAllow.accesskey"),
+ callback(state) {
+ setCanvasPermission(uri, Ci.nsIPermissionManager.DENY_ACTION,
+ state && state.checkboxChecked);
+ }
+ }];
+
+ let checkbox = {
+ // In PB mode, we don't want the "always remember" checkbox
+ show: !PrivateBrowsingUtils.isWindowPrivate(window)
+ };
+ if (checkbox.show) {
+ checkbox.checked = true;
+ checkbox.label = gBrowserBundle.GetStringFromName("canvas.remember");
+ }
+
+ let options = {
+ checkbox
+ };
+ PopupNotifications.show(browser, aTopic, message, this._notificationIcon,
+ mainAction, secondaryActions, options);
+ }
+};
+
function CanCloseWindow() {
// Avoid redundant calls to canClose from showing multiple
// PermitUnload dialogs.
if (Services.startup.shuttingDown || window.skipNextCanClose) {
return true;
}
let timedOutProcesses = new WeakSet();
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -818,16 +818,18 @@
onmouseout="document.getElementById('identity-box').classList.remove('no-hover');"
align="center">
<image id="default-notification-icon" class="notification-anchor-icon" role="button"
tooltiptext="&urlbar.defaultNotificationAnchor.tooltip;"/>
<image id="geo-notification-icon" class="notification-anchor-icon geo-icon" role="button"
tooltiptext="&urlbar.geolocationNotificationAnchor.tooltip;"/>
<image id="addons-notification-icon" class="notification-anchor-icon install-icon" role="button"
tooltiptext="&urlbar.addonsNotificationAnchor.tooltip;"/>
+ <image id="canvas-notification-icon" class="notification-anchor-icon" role="button"
+ tooltiptext="&urlbar.canvasNotificationAnchor.tooltip;"/>
<image id="indexedDB-notification-icon" class="notification-anchor-icon indexedDB-icon" role="button"
tooltiptext="&urlbar.indexedDBNotificationAnchor.tooltip;"/>
<image id="password-notification-icon" class="notification-anchor-icon login-icon" role="button"
tooltiptext="&urlbar.passwordNotificationAnchor.tooltip;"/>
<stack id="plugins-notification-icon" class="notification-anchor-icon" role="button" align="center"
tooltiptext="&urlbar.pluginsNotificationAnchor.tooltip;">
<image class="plugin-icon" />
<image id="plugin-icon-badge" />
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -200,16 +200,17 @@ These should match what Safari and other
<!ENTITY printButton.label "Print">
<!ENTITY printButton.tooltip "Print this page">
<!ENTITY urlbar.viewSiteInfo.label "View site information">
<!ENTITY urlbar.defaultNotificationAnchor.tooltip "Open message panel">
<!ENTITY urlbar.geolocationNotificationAnchor.tooltip "Open location request panel">
<!ENTITY urlbar.addonsNotificationAnchor.tooltip "Open add-on installation message panel">
+<!ENTITY urlbar.canvasNotificationAnchor.tooltip "Manage canvas extraction permission">
<!ENTITY urlbar.indexedDBNotificationAnchor.tooltip "Open offline storage message panel">
<!ENTITY urlbar.passwordNotificationAnchor.tooltip "Open save password message panel">
<!ENTITY urlbar.pluginsNotificationAnchor.tooltip "Manage plug-in use">
<!ENTITY urlbar.webNotificationAnchor.tooltip "Change whether you can receive notifications from the site">
<!ENTITY urlbar.persistentStorageNotificationAnchor.tooltip "Store data in Persistent Storage">
<!ENTITY urlbar.remoteControlNotificationAnchor.tooltip "Browser is under remote control">
<!ENTITY urlbar.webRTCShareDevicesNotificationAnchor.tooltip "Manage sharing your camera and/or microphone with the site">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -462,16 +462,25 @@ offlineApps.allowStoring.label=Allow Sto
offlineApps.allowStoring.accesskey=A
offlineApps.dontAllow.label=Don’t Allow
offlineApps.dontAllow.accesskey=n
offlineApps.usage=This website (%S) is now storing more than %SMB of data on your computer for offline use.
offlineApps.manageUsage=Show settings
offlineApps.manageUsageAccessKey=S
+# Canvas permission prompt
+# LOCALIZATION NOTE (canvas.siteprompt): %S is hostname
+canvas.siteprompt=Will you allow %S to use your HTML5 canvas image data? This may be used to uniquely identify your computer.
+canvas.notAllow=Don’t Allow
+canvas.notAllow.accesskey=n
+canvas.allow=Allow Data Access
+canvas.allow.accesskey=A
+canvas.remember=Always remember my decision
+
identity.identified.verifier=Verified by: %S
identity.identified.verified_by_you=You have added a security exception for this site.
identity.identified.state_and_country=%S, %S
identity.icon.tooltip=Show site information
identity.extension.label=Extension (%S)
identity.extension.tooltip=Loaded by extension: %S
identity.showDetails.tooltip=Show connection details
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -56,16 +56,17 @@
skin/classic/browser/identity-icon-notice.svg (../shared/identity-block/identity-icon-notice.svg)
skin/classic/browser/info.svg (../shared/info.svg)
skin/classic/browser/searchReset.css (../shared/searchReset.css)
skin/classic/browser/illustrations/error-session-restore.svg (../shared/illustrations/error-session-restore.svg)
skin/classic/browser/notification-icons/camera-blocked.svg (../shared/notification-icons/camera-blocked.svg)
skin/classic/browser/notification-icons/camera.svg (../shared/notification-icons/camera.svg)
+ skin/classic/browser/notification-icons/canvas.svg (../shared/notification-icons/canvas.svg)
skin/classic/browser/notification-icons/default-info.svg (../shared/notification-icons/default-info.svg)
skin/classic/browser/notification-icons/desktop-notification-blocked.svg (../shared/notification-icons/desktop-notification-blocked.svg)
skin/classic/browser/notification-icons/desktop-notification.svg (../shared/notification-icons/desktop-notification.svg)
skin/classic/browser/notification-icons/focus-tab-by-prompt.svg (../shared/notification-icons/focus-tab-by-prompt.svg)
skin/classic/browser/notification-icons/indexedDB-blocked.svg (../shared/notification-icons/indexedDB-blocked.svg)
skin/classic/browser/notification-icons/indexedDB.svg (../shared/notification-icons/indexedDB.svg)
skin/classic/browser/notification-icons/login-detailed.svg (../shared/notification-icons/login-detailed.svg)
skin/classic/browser/notification-icons/login.svg (../shared/notification-icons/login.svg)
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -112,16 +112,21 @@
.screen-icon.in-use {
list-style-image: url(chrome://browser/skin/notification-icons/screen.svg);
}
.screen-icon.blocked-permission-icon {
list-style-image: url(chrome://browser/skin/notification-icons/screen-blocked.svg);
}
+#canvas-notification-icon,
+.popup-notification-icon[popupid="canvas-permissions-prompt"] {
+ list-style-image: url(chrome://browser/skin/notification-icons/canvas.svg);
+}
+
#webRTC-preview:not([hidden]) {
display: -moz-stack;
border-radius: 4px;
border: 1px solid GrayText;
overflow: hidden;
min-width: 300px;
min-height: 10em;
}
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/notification-icons/canvas.svg
@@ -0,0 +1,7 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 481.156 508.687" fill="context-fill" fill-opacity="context-fill-opacity">
+ <path d="M477.656 289.656c-36.133 224.615-220.16 222.188-283 218C22.22 496.163-68.584 254.586 61.98 128.066l105.857 105.872c-7.183 24.6 2.7 54.1 42.418 70.59 42.865 17.8 87.4 9.747 87.4 9.747s-14.08-22.03-15.565-68.266c-1.1-34.2-40.15-55.996-72.513-50.483L108.757 94.69c30.6-12.34 59.033-1.8 69.9 6.966 26.87 21.688 16.616 68.436 53 54 70.87-28.12-40.744-132.32 53-154 79.026-18.278 220.516 116.945 193 288zm-371-14a41 41 0 1 0 41 41 41 41 0 0 0-41-41zm149.5 92a43.5 43.5 0 1 0 43.5 43.5 43.5 43.5 0 0 0-43.5-43.5zm97.5-273a40 40 0 1 0 40 40 40 40 0 0 0-40-40zm24.5 141a45.5 45.5 0 1 0 45.5 45.5 45.5 45.5 0 0 0-45.5-45.5z"/>
+ <path d="M213.656 296.656c-36.083-15.022-42.678-42.92-33.52-64.423L35.847 87.925a17.732 17.732 0 0 1 25.076-25.078L205.45 207.393c28.076-10.037 67.206 8.853 68.206 40.263 1.24 38.716 13 58 13 58s-37.2 5.905-73-9z"/>
+</svg>