Bug 754608 - Part 1 - don't capture thumbnails for privacy-sensitive pages; r=dao
authorTim Taubert <tim.taubert@gmx.de>
Tue, 15 May 2012 08:10:55 +0200
changeset 93890 a9e0c4e24451
parent 93889 ab8c08dfe9c4
child 93891 fa73740859cf
push id764
push usertim.taubert@gmx.de
push date2012-05-15 06:44 +0000
treeherderfx-team@b1292af5ecd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdao
bugs754608
milestone15.0a1
Bug 754608 - Part 1 - don't capture thumbnails for privacy-sensitive pages; r=dao
browser/base/content/browser-thumbnails.js
--- a/browser/base/content/browser-thumbnails.js
+++ b/browser/base/content/browser-thumbnails.js
@@ -3,19 +3,29 @@
  * 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/. */
 #endif
 
 /**
  * Keeps thumbnails of open web pages up-to-date.
  */
 let gBrowserThumbnails = {
+  /**
+   * Pref that controls whether we can store SSL content on disk
+   */
+  PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl",
+
   _captureDelayMS: 1000,
 
   /**
+   * Used to keep track of disk_cache_ssl preference
+   */
+  _sslDiskCacheEnabled: null,
+
+  /**
    * Map of capture() timeouts assigned to their browsers.
    */
   _timeouts: null,
 
   /**
    * Cache for the PageThumbs module.
    */
   _pageThumbs: null,
@@ -27,29 +37,34 @@ let gBrowserThumbnails = {
 
   init: function Thumbnails_init() {
     try {
       if (Services.prefs.getBoolPref("browser.pagethumbnails.capturing_disabled"))
         return;
     } catch (e) {}
 
     gBrowser.addTabsProgressListener(this);
+    Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
+
+    this._sslDiskCacheEnabled =
+      Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
 
     this._tabEvents.forEach(function (aEvent) {
       gBrowser.tabContainer.addEventListener(aEvent, this, false);
     }, this);
 
     this._timeouts = new WeakMap();
 
     XPCOMUtils.defineLazyModuleGetter(this, "_pageThumbs",
       "resource:///modules/PageThumbs.jsm", "PageThumbs");
   },
 
   uninit: function Thumbnails_uninit() {
     gBrowser.removeTabsProgressListener(this);
+    Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
 
     this._tabEvents.forEach(function (aEvent) {
       gBrowser.tabContainer.removeEventListener(aEvent, this, false);
     }, this);
   },
 
   handleEvent: function Thumbnails_handleEvent(aEvent) {
     switch (aEvent.type) {
@@ -63,16 +78,21 @@ let gBrowserThumbnails = {
         break;
       case "TabClose": {
         this._clearTimeout(aEvent.target.linkedBrowser);
         break;
       }
     }
   },
 
+  observe: function Thumbnails_observe() {
+    this._sslDiskCacheEnabled =
+      Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
+  },
+
   /**
    * State change progress listener for all tabs.
    */
   onStateChange: function Thumbnails_onStateChange(aBrowser, aWebProgress,
                                                    aRequest, aStateFlags, aStatus) {
     if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
         aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK)
       this._delayedCapture(aBrowser);
@@ -124,29 +144,40 @@ let gBrowserThumbnails = {
     let channel = aBrowser.docShell.currentDocumentChannel;
 
     // No valid document channel. We shouldn't take a screenshot.
     if (!channel)
       return false;
 
     // Don't take screenshots of internally redirecting about: pages.
     // This includes error pages.
-    if (channel.originalURI.schemeIs("about"))
+    let uri = channel.originalURI;
+    if (uri.schemeIs("about"))
       return false;
 
+    let httpChannel;
     try {
-      // If the channel is a nsIHttpChannel get its http status code.
-      let httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
+      httpChannel = channel.QueryInterface(Ci.nsIHttpChannel);
+    } catch (e) { /* Not an HTTP channel. */ }
 
+    if (httpChannel) {
       // Continue only if we have a 2xx status code.
-      return Math.floor(httpChannel.responseStatus / 100) == 2;
-    } catch (e) {
-      // Not a http channel, we just assume a success status code.
-      return true;
+      if (Math.floor(httpChannel.responseStatus / 100) != 2)
+        return false;
+
+      // Cache-Control: no-store.
+      if (httpChannel.isNoStoreResponse())
+        return false;
+
+      // Don't capture HTTPS pages unless the user explicitly enabled it.
+      if (uri.schemeIs("https") && !this._sslDiskCacheEnabled)
+        return false;
     }
+
+    return true;
   },
 
   _clearTimeout: function Thumbnails_clearTimeout(aBrowser) {
     if (this._timeouts.has(aBrowser)) {
       aBrowser.removeEventListener("scroll", this, false);
       clearTimeout(this._timeouts.get(aBrowser));
       this._timeouts.delete(aBrowser);
     }