Commit b8067345 authored by Kathleen Brade's avatar Kathleen Brade Committed by Mike Perry
Browse files

Add canvas image extraction prompt.

Also fixes bug #12684: Make "Not now" default for HTML5 canvas permission
dialogue, update the notification icon, and logs script URLs to the browser
console.

The notification only appears for first party urls, but all extraction
attempts are logged.

NOTE: Applying this patch requires an additional patch to TorButton, to
store the additional UI strings before localisation. [3]
parent 784c1007
Loading
Loading
Loading
Loading
+115 −0
Original line number Diff line number Diff line
@@ -1027,6 +1027,7 @@ var gBrowserInit = {
    BrowserOffline.init();
    OfflineApps.init();
    IndexedDBPromptHelper.init();
    CanvasPermissionPromptHelper.init();
    gFormSubmitObserver.init();
    SocialUI.init();
    AddonManager.addAddonListener(AddonsMgrListener);
@@ -1389,6 +1390,7 @@ var gBrowserInit = {
      BrowserOffline.uninit();
      OfflineApps.uninit();
      IndexedDBPromptHelper.uninit();
      CanvasPermissionPromptHelper.uninit();
      AddonManager.removeAddonListener(AddonsMgrListener);
      SocialUI.uninit();
    }
@@ -6026,6 +6028,119 @@ var IndexedDBPromptHelper = {
  }
};

var CanvasPermissionPromptHelper = {
  _permissionsPrompt: "canvas-permissions-prompt",
  _notificationIcon: "canvas-notification-icon",

  init:
  function CanvasPermissionPromptHelper_init() {
    if (document.styleSheets && (document.styleSheets.length > 0)) try {
      let ruleText = "panel[popupid=canvas-permissions-prompt] description { white-space: pre-wrap; }";
      let sheet = document.styleSheets[0];
      sheet.insertRule(ruleText, sheet.cssRules.length);
    } catch (e) {};

    Services.obs.addObserver(this, this._permissionsPrompt, false);
  },

  uninit:
  function CanvasPermissionPromptHelper_uninit() {
    Services.obs.removeObserver(this, this._permissionsPrompt, false);
  },

  // aSubject is an nsIDOMWindow.
  // aData is an URL string.
  observe:
  function CanvasPermissionPromptHelper_observe(aSubject, aTopic, aData) {
    if ((aTopic != this._permissionsPrompt) || !aData)
      throw new Error("Unexpected topic or missing URL");

    var uri = makeURI(aData);
    var contentWindow = aSubject.QueryInterface(Ci.nsIDOMWindow);
    var contentDocument = contentWindow.document;
    var browserWindow =
      OfflineApps._getBrowserWindowForContentWindow(contentWindow);

    if (browserWindow != window) {
      // Must belong to some other window.
      return;
    }

    // If canvas prompt is already displayed, just return.  This is OK (and
    // more efficient) since this permission is associated with the top
    // browser's URL.
    if (PopupNotifications.getNotification(aTopic, browser))
      return;

    var bundleSvc = Cc["@mozilla.org/intl/stringbundle;1"].
                        getService(Ci.nsIStringBundleService);
    var torBtnBundle;
    try {
      torBtnBundle = bundleSvc.createBundle(
                             "chrome://torbutton/locale/torbutton.properties");
    } catch (e) {}

    var message = getLocalizedString("canvas.siteprompt", [ uri.asciiHost ]);

    var mainAction = {
      label: getLocalizedString("canvas.notNow"),
      accessKey: getLocalizedString("canvas.notNowAccessKey"),
      callback: function() {
        return null;
      }
    };

    var secondaryActions = [
      {
        label: getLocalizedString("canvas.never"),
        accessKey: getLocalizedString("canvas.neverAccessKey"),
        callback: function() {
          setCanvasPermission(uri, Ci.nsIPermissionManager.DENY_ACTION);
        }
      },
      {
        label: getLocalizedString("canvas.allow"),
        accessKey: getLocalizedString("canvas.allowAccessKey"),
        callback: function() {
            setCanvasPermission(uri, Ci.nsIPermissionManager.ALLOW_ACTION);
        }
      }
    ];

    // Since we have a process in place to perform localization for the
    // Torbutton extension, get our strings from the extension if possible.
    function getLocalizedString(aID, aParams) {
      var s;
      if (torBtnBundle) try {
        if (aParams)
          s = torBtnBundle.formatStringFromName(aID, aParams, aParams.length);
        else
          s = torBtnBundle.GetStringFromName(aID);
      } catch (e) {}

      if (!s) {
        if (aParams)
          s = gNavigatorBundle.getFormattedString(aID, aParams);
        else
          s = gNavigatorBundle.getString(aID);
      }

      return s;
    }

    function setCanvasPermission(aURI, aPerm) {
      Services.perms.add(aURI, "canvas/extractData", aPerm,
                         Ci.nsIPermissionManager.EXPIRE_NEVER);
    }

    var browser = OfflineApps._getBrowserForContentWindow(browserWindow,
                                                          contentWindow);
    notification = PopupNotifications.show(browser, aTopic, message,
                                           this._notificationIcon, mainAction,
                                           secondaryActions, null);
  }
};

function WindowIsClosing()
{
  if (TabView.isVisible()) {
+1 −0
Original line number Diff line number Diff line
@@ -442,6 +442,7 @@
            <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
            <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
            <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
            <image id="canvas-notification-icon" class="notification-anchor-icon" role="button"/>
            <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
            <image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
            <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
+7 −0
Original line number Diff line number Diff line
@@ -249,6 +249,13 @@ offlineApps.usage=This website (%S) is now storing more than %SMB of data on you
offlineApps.manageUsage=Show settings
offlineApps.manageUsageAccessKey=S

# Canvas permission prompt
canvas.siteprompt=This website (%S) attempted to access image data on a canvas. Since canvas image data can be used to discover information about your computer, blank image data was returned this time.
canvas.allow=Allow in the Future
canvas.allowAccessKey=A
canvas.never=Never for This Site
canvas.neverAccessKey=e

# LOCALIZATION NOTE (indexedDB.usage): %1$S is the website host name
# %2$S a number of megabytes.
indexedDB.usage=This website (%1$S) is attempting to store more than %2$S MB of data on your computer for offline use.
+8 −0
Original line number Diff line number Diff line
@@ -1207,6 +1207,10 @@ toolbar[iconsize="small"] #webrtc-status-button {
  list-style-image: url("moz-icon://stock/gtk-cancel?size=menu");
}

.popup-notification-icon[popupid="canvas-permissions-prompt"] {
  list-style-image: url(chrome://browser/skin/canvas-popup.svg);
}

.popup-notification-icon[popupid="indexedDB-permissions-prompt"],
.popup-notification-icon[popupid="indexedDB-quota-prompt"],
.popup-notification-icon[popupid*="offline-app-requested"],
@@ -1290,6 +1294,10 @@ toolbar[iconsize="small"] #webrtc-status-button {
  list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric-16.png);
}

#canvas-notification-icon {
  list-style-image: url(chrome://browser/skin/canvas-popup.svg);
}

.indexedDB-notification-icon,
#indexedDB-notification-icon {
  list-style-image: url(chrome://global/skin/icons/question-16.png);
+19 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="UTF-8"?>
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">

 <metadata>image/svg+xmlOpen Clip Art Librarypalette2009-02-17T21:15:25http://openclipart.org/detail/21620/palette-by-benbenclip artclipartcolorcoloriconiconimagemediapaintpaintpalettepalettepngpublic domainsvg</metadata>
 <g>
  <title>Layer 1</title>
  <g id="layer1">
   <rect fill="#000000" stroke-width="2" stroke-miterlimit="4" stroke-dashoffset="0" ry="23.587006" rx="26.785715" y="0" x="0" height="200" width="200" id="rect6786"/>
   <g transform="matrix(4.65116, 0, 0, 4.65116, -1717.85, -314.201)" id="g6820">
    <path fill="#ffffff" stroke-width="1.924773" stroke-miterlimit="4" stroke-dasharray="3.84954572, 3.84954572" stroke-dashoffset="3.657068" d="m388.618042,70.128563c-4.746887,0 -18.367279,0.849472 -18.34375,12.3125c0.001312,0.644249 1.226776,2.886879 2.25,3.125c7.5755,1.762962 7.986664,7.834511 7.53125,12.625c-0.03479,0.362747 0.589233,2.891006 1.125,3.53125c4.344635,5.191872 5.822723,7.468742 11.6875,7.46875c11.729614,0 18.3125,-5.93206 18.3125,-17.8125c0,-11.880463 -10.832916,-21.25 -22.5625,-21.25zm-11.875,8.1875c0.986481,0.058029 2.139893,0.464394 3.21875,1.1875c2.157715,1.44622 3.225708,3.668251 2.375,4.9375c-0.850739,1.269257 -3.311005,1.10247 -5.46875,-0.34375c-2.157745,-1.446228 -3.194458,-3.637001 -2.34375,-4.90625c0.425354,-0.634628 1.232269,-0.933029 2.21875,-0.875z" id="path6822"/>
    <path fill="#ff7a00" stroke-width="1.924773" stroke-miterlimit="4" stroke-dasharray="3.84954572, 3.84954572" stroke-dashoffset="3.657068" id="path6824" d="m392.586761,76.615746a3.5,3.5 0 1 1 -7,0a3.5,3.5 0 1 1 7,0z"/>
    <path fill="#95d300" stroke-width="1.924773" stroke-miterlimit="4" stroke-dasharray="3.84954572, 3.84954572" stroke-dashoffset="3.657068" id="path6826" d="m402.524292,81.553246a3.5,3.5 0 1 1 -7,0a3.5,3.5 0 1 1 7,0z"/>
    <path fill="#00a6e4" stroke-width="1.924773" stroke-miterlimit="4" stroke-dasharray="3.84954572, 3.84954572" stroke-dashoffset="3.657068" id="path6828" d="m408.461792,90.615746a3.5,3.5 0 1 1 -7,0a3.5,3.5 0 1 1 7,0z"/>
    <path fill="#f9de00" stroke-width="1.924773" stroke-miterlimit="4" stroke-dasharray="3.84954572, 3.84954572" stroke-dashoffset="3.657068" id="path6830" d="m403.643463,99.60791a3.5,3.5 0 1 1 -7,0a3.5,3.5 0 1 1 7,0z"/>
    <path fill="#e600ad" stroke-width="1.924773" stroke-miterlimit="4" stroke-dasharray="3.84954572, 3.84954572" stroke-dashoffset="3.657068" id="path6832" d="m393.518463,100.60791a3.5,3.5 0 1 1 -7,0a3.5,3.5 0 1 1 7,0z"/>
   </g>
  </g>
 </g>
</svg>
 No newline at end of file
Loading