Back out bug 674926 (changeset 7837b186b10b)
authorTim Taubert <tim.taubert@gmx.de>
Sun, 21 Aug 2011 20:16:13 +0200
changeset 75627 eb8e9468f409c9efeec64e5631f87ae192ab727c
parent 75626 1ea40cc5b3f3677f5ffa60eef3e879302f5253bf
child 75628 9d6e9b1c7807759887c3c2d2d4dc7f2996adbf27
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
bugs674926
milestone9.0a1
Back out bug 674926 (changeset 7837b186b10b)
browser/base/content/tabview/content.js
browser/base/content/tabview/modules/utils.jsm
browser/base/content/tabview/storagePolicy.js
browser/base/content/tabview/tabview.js
browser/base/content/tabview/thumbnailStorage.js
browser/base/content/tabview/ui.js
browser/base/content/test/tabview/Makefile.in
browser/base/content/test/tabview/browser_tabview_bug627239.js
browser/base/content/test/tabview/browser_tabview_storage_policy.js
--- a/browser/base/content/tabview/content.js
+++ b/browser/base/content/tabview/content.js
@@ -29,157 +29,18 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-"use strict";
-
-const Cu = Components.utils;
-
-Cu.import("resource:///modules/tabview/utils.jsm");
-
-let ifaceReq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
-let webProgress = ifaceReq.getInterface(Ci.nsIWebProgress);
-
-// ----------
-// WindowEventHandler
-//
-// Handles events dispatched by the content window.
-let WindowEventHandler = {
-  // ----------
-  // Function: onLoad
-  // Sends an asynchronous message when the "onload" event for the current page
-  // is fired.
-  onLoad: function WEH_onLoad(event) {
-    sendAsyncMessage("Panorama:Load");
-  },
-
-  // ----------
-  // Function: onDOMWillOpenModalDialog
-  // Sends a synchronous message when the "onDOMWillOpenModalDialog" event
-  // is fired right before a modal dialog will be opened by the current page.
-  onDOMWillOpenModalDialog: function WEH_onDOMWillOpenModalDialog(event) {
-    // (event.isTrusted == true) when the event is generated by a user action
-    // and does not originate from a script.
-    if (!event.isTrusted)
-      return;
-
+addEventListener("DOMWillOpenModalDialog", function (event) {
+  // (event.isTrusted == true) when the event is generated by a user action
+  // and does not originate from a script.
+  if (event.isTrusted) {
     // we're intentionally sending a synchronous message to handle this event
     // as quick as possible, switch the selected tab and hide the tabview
     // before the modal dialog is shown
     sendSyncMessage("Panorama:DOMWillOpenModalDialog");
   }
-};
-
-// add event listeners
-addEventListener("load", WindowEventHandler.onLoad);
-addEventListener("DOMWillOpenModalDialog", WindowEventHandler.onDOMWillOpenModalDialog);
-
-// ----------
-// WindowMessageHandler
-//
-// Handles messages sent by the chrome process.
-let WindowMessageHandler = {
-  // ----------
-  // Function: isDocumentLoaded
-  // Checks if the currently active document is loaded.
-  isDocumentLoaded: function WMH_isDocumentLoaded(cx) {
-    let isLoaded = (content.document.readyState == "complete" &&
-                    !webProgress.isLoadingDocument);
-
-    sendAsyncMessage(cx.name, {isLoaded: isLoaded});
-  }
-};
-
-// add message listeners
-addMessageListener("Panorama:isDocumentLoaded", WindowMessageHandler.isDocumentLoaded);
-
-// ----------
-// WebProgressListener
-//
-// Observe the web progress of content pages loaded into this browser. When the
-// state of a page changes we check if we're still allowed to store page
-// information permanently.
-let WebProgressListener = {
-  // ----------
-  // Function: onStateChange
-  // Called by the webProgress when its state changes.
-  onStateChange: function WPL_onStateChange(webProgress, request, flag, status) {
-    // The browser just started loading (again). Explicitly grant storage
-    // because the browser might have been blocked before (e.g. when navigating
-    // from a https-page to a http-page).
-    if (flag & Ci.nsIWebProgressListener.STATE_START) {
-      // ensure the dom window is the top one
-      if (this._isTopWindow(webProgress))
-        sendAsyncMessage("Panorama:StoragePolicy:granted");
-    }
-
-    // The browser finished loading - check the cache control headers. Send
-    // a message if we're not allowed to store information about this page.
-    if (flag & Ci.nsIWebProgressListener.STATE_STOP) {
-      // ensure the dom window is the top one
-      if (this._isTopWindow(webProgress) &&
-          request && request instanceof Ci.nsIHttpChannel) {
-        request.QueryInterface(Ci.nsIHttpChannel);
-
-        let exclude = false;
-        let reason = "";
-
-        // Check if the "Cache-Control" header is "no-store". In this case we're
-        // not allowed to store information about the current page.
-        if (this._isNoStoreResponse(request)) {
-          exclude = true;
-          reason = "no-store";
-        }
-        // Otherwise we'll deny storage if we're currently viewing a https
-        // page without a "Cache-Control: public" header.
-        else if (request.URI.schemeIs("https")) {
-          let cacheControlHeader = this._getCacheControlHeader(request);
-          if (cacheControlHeader && !(/public/i).test(cacheControlHeader)) {
-            exclude = true;
-            reason = "https";
-          }
-        }
-
-        if (exclude)
-          sendAsyncMessage("Panorama:StoragePolicy:denied", {reason: reason});
-      }
-    }
-  },
-
-  // ----------
-  // Function: _isTopWindow
-  // Returns whether the DOMWindow associated with the webProgress is the
-  // top content window (and not an iframe or similar).
-  _isTopWindow: function WPL__isTopWindow(webProgress) {
-    // can throw if there's no associated DOMWindow
-    return !!Utils.attempt(function () webProgress.DOMWindow == content);
-  },
-
-  // ----------
-  // Function: _isNoStoreResponse
-  // Checks if the "Cache-Control" header is "no-store".
-  _isNoStoreResponse: function WPL__isNoStoreResponse(req) {
-    // can throw if called before the response has been received
-    return !!Utils.attempt(function () req.isNoStoreResponse());
-  },
-
-  // ----------
-  // Function: _getCacheControlHeader
-  // Returns the value of the "Cache-Control" header.
-  _getCacheControlHeader: function WPL__getCacheControlHeader(req) {
-    // can throw when the "Cache-Control" header doesn't exist
-    return Utils.attempt(function () req.getResponseHeader("Cache-Control"));
-  },
-
-  // ----------
-  // Implements progress listener interface.
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
-                                         Ci.nsISupportsWeakReference,
-                                         Ci.nsISupports])
-};
-
-// add web progress listener
-webProgress.addProgressListener(WebProgressListener, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
+}, true);
--- a/browser/base/content/tabview/modules/utils.jsm
+++ b/browser/base/content/tabview/modules/utils.jsm
@@ -771,27 +771,10 @@ let Utils = {
           if (copy !== undefined)
             target[name] = copy;
         }
       }
     }
 
     // Return the modified object
     return target;
-  },
-
-  // ----------
-  // Function: attempt
-  // Tries to execute a number of functions. Returns immediately the return
-  // value of the first non-failed function without executing successive
-  // functions, or null.
-  attempt: function () {
-    let args = arguments;
-
-    for (let i = 0; i < args.length; i++) {
-      try {
-        return args[i]();
-      } catch (e) {}
-    }
-
-    return null;
   }
 };
deleted file mode 100644
--- a/browser/base/content/tabview/storagePolicy.js
+++ /dev/null
@@ -1,201 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is storagePolicy.js.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Tim Taubert <ttaubert@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-// **********
-// Title: storagePolicy.js
-
-// ##########
-// Class: StoragePolicy
-// Singleton for implementing a storage policy for sensitive data.
-let StoragePolicy = {
-  // Pref that controls whether we can store SSL content on disk
-  PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl",
-
-  // Used to keep track of disk_cache_ssl preference
-  _enablePersistentHttpsCaching: null,
-
-  // Used to keep track of browsers whose data we shouldn't store permanently
-  _deniedBrowsers: [],
-
-  // ----------
-  // Function: toString
-  // Prints [StoragePolicy] for debug use.
-  toString: function StoragePolicy_toString() {
-    return "[StoragePolicy]";
-  },
-
-  // ----------
-  // Function: init
-  // Initializes the StoragePolicy object.
-  init: function StoragePolicy_init() {
-    // store the preference value
-    this._enablePersistentHttpsCaching =
-      Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
-
-    Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
-
-    // tabs are already loaded before UI is initialized so cache-control
-    // values are unknown. We add browsers with https to the list for now.
-    if (!this._enablePersistentHttpsCaching)
-      Array.forEach(gBrowser.browsers, this._initializeBrowser.bind(this));
-
-    // make sure to remove tab browsers when tabs get closed
-    this._onTabClose = this._onTabClose.bind(this);
-    gBrowser.tabContainer.addEventListener("TabClose", this._onTabClose, false);
-
-    let mm = gWindow.messageManager;
-
-    // add message listeners for storage granted
-    this._onGranted = this._onGranted.bind(this);
-    mm.addMessageListener("Panorama:StoragePolicy:granted", this._onGranted);
-
-    // add message listeners for storage denied
-    this._onDenied = this._onDenied.bind(this);
-    mm.addMessageListener("Panorama:StoragePolicy:denied", this._onDenied);
-  },
-
-  // ----------
-  // Function: _initializeBrowser
-  // Initializes the given browser and checks if we need to add it to our
-  // internal exclusion list.
-  _initializeBrowser: function StoragePolicy__initializeBrowser(browser) {
-    let self = this;
-
-    function checkExclusion() {
-      if (browser.currentURI.schemeIs("https"))
-        self._deniedBrowsers.push(browser);
-    }
-
-    function waitForDocumentLoad() {
-      mm.addMessageListener("Panorama:Load", function onLoad(cx) {
-        mm.removeMessageListener(cx.name, onLoad);
-        checkExclusion(browser);
-      });
-    }
-
-    this._isDocumentLoaded(browser, function (isLoaded) {
-      if (isLoaded)
-        checkExclusion();
-      else
-        waitForDocumentLoad();
-    });
-  },
-
-  // ----------
-  // Function: _isDocumentLoaded
-  // Check if the given browser's document is loaded.
-  _isDocumentLoaded: function StoragePolicy__isDocumentLoaded(browser, callback) {
-    let mm = browser.messageManager;
-    let message = "Panorama:isDocumentLoaded";
-
-    mm.addMessageListener(message, function onMessage(cx) {
-      mm.removeMessageListener(cx.name, onMessage);
-      callback(cx.json.isLoaded);
-    });
-
-    mm.sendAsyncMessage(message);
-  },
-
-  // ----------
-  // Function: uninit
-  // Is called by UI.init() when the browser windows is closed.
-  uninit: function StoragePolicy_uninit() {
-    Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
-    gBrowser.removeTabsProgressListener(this);
-    gBrowser.tabContainer.removeEventListener("TabClose", this._onTabClose, false);
-
-    let mm = gWindow.messageManager;
-
-    // remove message listeners
-    mm.removeMessageListener("Panorama:StoragePolicy:granted", this._onGranted);
-    mm.removeMessageListener("Panorama:StoragePolicy:denied", this._onDenied);
-  },
-
-  // ----------
-  // Function: _onGranted
-  // Handle the 'granted' message and remove the given browser from the list
-  // of denied browsers.
-  _onGranted: function StoragePolicy__onGranted(cx) {
-    let index = this._deniedBrowsers.indexOf(cx.target);
-
-    if (index > -1)
-      this._deniedBrowsers.splice(index, 1);
-  },
-
-  // ----------
-  // Function: _onDenied
-  // Handle the 'denied' message and add the given browser to the list of denied
-  // browsers.
-  _onDenied: function StoragePolicy__onDenied(cx) {
-    // exclusion is optional because cache-control is not no-store or public and
-    // the protocol is https. don't exclude when persistent https caching is
-    // enabled.
-    if ("https" == cx.json.reason && this._enablePersistentHttpsCaching)
-      return;
-
-    let browser = cx.target;
-
-    if (this._deniedBrowsers.indexOf(browser) == -1)
-      this._deniedBrowsers.push(browser);
-  },
-
-  // ----------
-  // Function: _onTabClose
-  // Remove the browser from our internal exclusion list when a tab gets closed.
-  _onTabClose: function StoragePolicy__onTabClose(event) {
-    let browser = event.target.linkedBrowser;
-    let index = this._deniedBrowsers.indexOf(browser);
-
-    if (index > -1)
-      this._deniedBrowsers.splice(index, 1);
-  },
-
-  // ----------
-  // Function: canStoreThumbnailForTab
-  // Returns whether we're allowed to store the thumbnail of the given tab.
-  canStoreThumbnailForTab: function StoragePolicy_canStoreThumbnailForTab(tab) {
-    return (this._deniedBrowsers.indexOf(tab.linkedBrowser) == -1);
-  },
-
-  // ----------
-  // Function: observe
-  // Observe pref changes.
-  observe: function StoragePolicy_observe(subject, topic, data) {
-    this._enablePersistentHttpsCaching =
-      Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
-  }
-};
--- a/browser/base/content/tabview/tabview.js
+++ b/browser/base/content/tabview/tabview.js
@@ -66,17 +66,16 @@ let AllTabs = {
     gBrowser.tabContainer.removeEventListener(this._events[eventName], callback, false);
   }
 };
 
 # NB: Certain files need to evaluate before others
 
 #include iq.js
 #include storage.js
-#include storagePolicy.js
 #include items.js
 #include groupitems.js
 #include tabitems.js
 #include drag.js
 #include trench.js
 #include thumbnailStorage.js
 #include ui.js
 #include search.js
--- a/browser/base/content/tabview/thumbnailStorage.js
+++ b/browser/base/content/tabview/thumbnailStorage.js
@@ -39,26 +39,36 @@
 // Title: thumbnailStorage.js
 
 // ##########
 // Class: ThumbnailStorage
 // Singleton for persistent storage of thumbnail data.
 let ThumbnailStorage = {
   CACHE_CLIENT_IDENTIFIER: "tabview-cache",
   CACHE_PREFIX: "moz-panorama:",
+  PREF_DISK_CACHE_SSL: "browser.cache.disk_cache_ssl",
 
   // Holds the cache session reference
   _cacheSession: null,
 
   // Holds the string input stream reference
   _stringInputStream: null,
 
   // Holds the storage stream reference
   _storageStream: null,
 
+  // Holds the progress listener reference
+  _progressListener: null,
+
+  // Used to keep track of disk_cache_ssl preference
+  enablePersistentHttpsCaching: null,
+
+  // Used to keep track of browsers whose thumbs we shouldn't save
+  excludedBrowsers: [],
+
   // ----------
   // Function: toString
   // Prints [ThumbnailStorage] for debug use.
   toString: function ThumbnailStorage_toString() {
     return "[ThumbnailStorage]";
   },
 
   // ----------
@@ -72,16 +82,50 @@ let ThumbnailStorage = {
     this._cacheSession = cacheService.createSession(
       this.CACHE_CLIENT_IDENTIFIER, Ci.nsICache.STORE_ON_DISK, true);
     this._stringInputStream = Components.Constructor(
       "@mozilla.org/io/string-input-stream;1", "nsIStringInputStream",
       "setData");
     this._storageStream = Components.Constructor(
       "@mozilla.org/storagestream;1", "nsIStorageStream", 
       "init");
+
+    // store the preference value
+    this.enablePersistentHttpsCaching =
+      Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
+
+    Services.prefs.addObserver(this.PREF_DISK_CACHE_SSL, this, false);
+
+    let self = this;
+    // tabs are already loaded before UI is initialized so cache-control
+    // values are unknown.  We add browsers with https to the list for now.
+    gBrowser.browsers.forEach(function(browser) {
+      let checkAndAddToList = function(browserObj) {
+        if (!self.enablePersistentHttpsCaching &&
+            browserObj.currentURI.schemeIs("https"))
+          self.excludedBrowsers.push(browserObj);
+      };
+      if (browser.contentDocument.readyState != "complete" ||
+          browser.webProgress.isLoadingDocument) {
+        browser.addEventListener("load", function onLoad() {
+          browser.removeEventListener("load", onLoad, true);
+          checkAndAddToList(browser);
+        }, true);
+      } else {
+        checkAndAddToList(browser);
+      }
+    });
+    gBrowser.addTabsProgressListener(this);
+  },
+
+  // Function: uninit
+  // Should be called when window is unloaded.
+  uninit: function ThumbnailStorage_uninit() {
+    gBrowser.removeTabsProgressListener(this);
+    Services.prefs.removeObserver(this.PREF_DISK_CACHE_SSL, this);
   },
 
   // ----------
   // Function: _openCacheEntry
   // Opens a cache entry for the given <url> and requests access <access>.
   // Calls <successCallback>(entry) when the entry was successfully opened with
   // requested access rights. Otherwise calls <errorCallback>().
   _openCacheEntry: function ThumbnailStorage__openCacheEntry(url, access, successCallback, errorCallback) {
@@ -102,26 +146,32 @@ let ThumbnailStorage = {
       let status = Cr.NS_OK;
       onCacheEntryAvailable(entry, entry.accessGranted, status);
     } else {
       let listener = new CacheListener(onCacheEntryAvailable);
       this._cacheSession.asyncOpenCacheEntry(key, access, listener);
     }
   },
 
+  // Function: _shouldSaveThumbnail
+  // Checks whether to save tab's thumbnail or not.
+  _shouldSaveThumbnail : function ThumbnailStorage__shouldSaveThumbnail(tab) {
+    return (this.excludedBrowsers.indexOf(tab.linkedBrowser) == -1);
+  },
+
   // ----------
   // Function: saveThumbnail
   // Saves the <imageData> to the cache using the given <url> as key.
   // Calls <callback>(status, data) when finished, passing true or false
   // (indicating whether the operation succeeded).
   saveThumbnail: function ThumbnailStorage_saveThumbnail(tab, imageData, callback) {
     Utils.assert(tab, "tab");
     Utils.assert(imageData, "imageData");
-
-    if (!StoragePolicy.canStoreThumbnailForTab(tab)) {
+    
+    if (!this._shouldSaveThumbnail(tab)) {
       tab._tabViewTabItem._sendToSubscribers("deniedToCacheImageData");
       if (callback)
         callback(false);
       return;
     }
 
     let self = this;
 
@@ -233,16 +283,71 @@ let ThumbnailStorage = {
     }
 
     let onCacheEntryUnavailable = function() {
       completed(false);
     }
 
     this._openCacheEntry(url, Ci.nsICache.ACCESS_READ,
         onCacheEntryAvailable, onCacheEntryUnavailable);
+  },
+
+  // ----------
+  // Function: observe
+  // Implements the observer interface.
+  observe: function ThumbnailStorage_observe(subject, topic, data) {
+    this.enablePersistentHttpsCaching =
+      Services.prefs.getBoolPref(this.PREF_DISK_CACHE_SSL);
+  },
+
+  // ----------
+  // Implements progress listener interface.
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+                                         Ci.nsISupportsWeakReference,
+                                         Ci.nsISupports]),
+
+  onStateChange: function ThumbnailStorage_onStateChange(
+    browser, webProgress, request, flag, status) {
+    if (flag & Ci.nsIWebProgressListener.STATE_START &&
+        flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
+      // ensure the dom window is the top one
+      if (webProgress.DOMWindow.parent == webProgress.DOMWindow) {
+        let index = this.excludedBrowsers.indexOf(browser);
+        if (index != -1)
+          this.excludedBrowsers.splice(index, 1);
+      }
+    }
+    if (flag & Ci.nsIWebProgressListener.STATE_STOP &&
+        flag & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
+      // ensure the dom window is the top one
+      if (webProgress.DOMWindow.parent == webProgress.DOMWindow &&
+          request && request instanceof Ci.nsIHttpChannel) {
+        request.QueryInterface(Ci.nsIHttpChannel);
+
+        let inhibitPersistentThumb = false;
+        if (request.isNoStoreResponse()) {
+           inhibitPersistentThumb = true;
+        } else if (!this.enablePersistentHttpsCaching &&
+                   request.URI.schemeIs("https")) {
+          let cacheControlHeader;
+          try {
+            cacheControlHeader = request.getResponseHeader("Cache-Control");
+          } catch(e) {
+            // this error would occur when "Cache-Control" doesn't exist in
+            // the eaders
+          }
+          if (cacheControlHeader && !(/public/i).test(cacheControlHeader))
+            inhibitPersistentThumb = true;
+        }
+
+        if (inhibitPersistentThumb &&
+            this.excludedBrowsers.indexOf(browser) == -1)
+          this.excludedBrowsers.push(browser);
+      }
+    }
   }
 }
 
 // ##########
 // Class: CacheListener
 // Generic CacheListener for feeding to asynchronous cache calls.
 // Calls <callback>(entry, access, status) when the requested cache entry
 // is available.
--- a/browser/base/content/tabview/ui.js
+++ b/browser/base/content/tabview/ui.js
@@ -170,19 +170,16 @@ let UI = {
       this._initPageDirection();
 
       // ___ thumbnail storage
       ThumbnailStorage.init();
 
       // ___ storage
       Storage.init();
 
-      // ___ storage policy
-      StoragePolicy.init();
-
       if (Storage.readWindowBusyState(gWindow))
         this.storageBusy();
 
       let data = Storage.readUIData(gWindow);
       this._storageSanity(data);
       this._pageBounds = data.pageBounds;
 
       // ___ currentTab
@@ -321,17 +318,17 @@ let UI = {
       func();
     });
     this._cleanupFunctions = [];
 
     // additional clean up
     TabItems.uninit();
     GroupItems.uninit();
     Storage.uninit();
-    StoragePolicy.uninit();
+    ThumbnailStorage.uninit();
 
     this._removeTabActionHandlers();
     this._currentTab = null;
     this._pageBounds = null;
     this._reorderTabItemsOnShow = null;
     this._reorderTabsOnHide = null;
     this._frameInitialized = false;
   },
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -109,16 +109,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug624953.js \
                  browser_tabview_bug625195.js \
                  browser_tabview_bug625269.js \
                  browser_tabview_bug625424.js \
                  browser_tabview_bug626368.js \
                  browser_tabview_bug626455.js \
                  browser_tabview_bug626525.js \
                  browser_tabview_bug626791.js \
+                 browser_tabview_bug627239.js \
                  browser_tabview_bug627288.js \
                  browser_tabview_bug627736.js \
                  browser_tabview_bug628061.js \
                  browser_tabview_bug628165.js \
                  browser_tabview_bug628270.js \
                  browser_tabview_bug629189.js \
                  browser_tabview_bug629195.js \
                  browser_tabview_bug630102.js \
@@ -161,17 +162,16 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_group.js \
                  browser_tabview_launch.js \
                  browser_tabview_multiwindow_search.js \
                  browser_tabview_privatebrowsing.js \
                  browser_tabview_rtl.js \
                  browser_tabview_search.js \
                  browser_tabview_snapping.js \
                  browser_tabview_startup_transitions.js \
-                 browser_tabview_storage_policy.js \
                  browser_tabview_undo_group.js \
                  dummy_page.html \
                  head.js \
                  search1.html \
                  search2.html \
                  test_bug600645.html \
                  test_bug644097.html \
                  $(NULL)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug627239.js
@@ -0,0 +1,154 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+let contentWindow;
+let enablePersistentHttpsCaching;
+let newTab;
+
+function test() {
+  waitForExplicitFinish();
+
+  newTab = gBrowser.addTab();
+
+  HttpRequestObserver.register();
+
+  registerCleanupFunction(function () {
+    HttpRequestObserver.unregister();
+    if (gBrowser.tabs[1])
+      gBrowser.removeTab(gBrowser.tabs[1]);
+    hideTabView();
+
+    contentWindow.ThumbnailStorage.enablePersistentHttpsCaching =
+        enablePersistentHttpsCaching;
+  });
+
+  showTabView(function() {
+    contentWindow = TabView.getContentWindow();
+    test1();
+  });
+}
+
+
+function test1() {
+  // page with cache-control: no-store, should not save thumbnail
+  HttpRequestObserver.cacheControlValue = "no-store";
+  newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/base/content/test/tabview/dummy_page.html");
+
+  afterAllTabsLoaded(function() {
+    let tabItem = newTab._tabViewTabItem;
+
+    ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab), 
+       "Should not save the thumbnail for tab");
+
+    whenDeniedToCacheImageData(tabItem, test2);
+    tabItem.save(true);
+    HttpRequestObserver.cacheControlValue = null;
+  });
+}
+
+function test2() {
+  // page with cache-control: private, should save thumbnail
+  HttpRequestObserver.cacheControlValue = "private";
+
+  newTab.linkedBrowser.loadURI("http://www.example.com/");
+  afterAllTabsLoaded(function() {
+    let tabItem = newTab._tabViewTabItem;
+
+    ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab), 
+       "Should save the thumbnail for tab");
+
+    whenSavedCachedImageData(tabItem, test3);
+    tabItem.save(true);
+  });
+}
+
+function test3() {
+  // page with cache-control: private with https caching enabled, should save thumbnail
+  HttpRequestObserver.cacheControlValue = "private";
+
+  enablePersistentHttpsCaching =
+    contentWindow.ThumbnailStorage.enablePersistentHttpsCaching;
+  contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = true;
+
+  newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/dummy_page.html");
+  afterAllTabsLoaded(function() {
+    let tabItem = newTab._tabViewTabItem;
+
+    ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
+       "Should save the thumbnail for tab");
+
+    whenSavedCachedImageData(tabItem, test4);
+    tabItem.save(true);
+  });
+}
+
+function test4() {
+  // page with cache-control: public with https caching disabled, should save thumbnail
+  HttpRequestObserver.cacheControlValue = "public";
+
+  contentWindow.ThumbnailStorage.enablePersistentHttpsCaching = false;
+
+  newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/");
+  afterAllTabsLoaded(function() {
+    let tabItem = newTab._tabViewTabItem;
+
+    ok(contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
+       "Should save the thumbnail for tab");
+
+    whenSavedCachedImageData(tabItem, test5);
+    tabItem.save(true);
+  });
+}
+
+function test5() {
+  // page with cache-control: private with https caching disabled, should not save thumbnail
+  HttpRequestObserver.cacheControlValue = "private";
+ 
+  newTab.linkedBrowser.loadURI("https://example.com/");
+  afterAllTabsLoaded(function() {
+    let tabItem = newTab._tabViewTabItem;
+
+    ok(!contentWindow.ThumbnailStorage._shouldSaveThumbnail(newTab),
+       "Should not the thumbnail for tab");
+
+    whenDeniedToCacheImageData(tabItem, function () {
+      hideTabView(function () {
+        gBrowser.removeTab(gBrowser.tabs[1]);
+        finish();
+      });
+    });
+    tabItem.save(true);
+  });
+}
+
+let HttpRequestObserver = {
+  cacheControlValue: null,
+
+  observe: function(subject, topic, data) {
+    if (topic == "http-on-examine-response" && this.cacheControlValue) {
+      let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
+      httpChannel.setResponseHeader("Cache-Control", this.cacheControlValue, false);
+    }
+  },
+
+  register: function() {
+    Services.obs.addObserver(this, "http-on-examine-response", false);
+  },
+
+  unregister: function() {
+    Services.obs.removeObserver(this, "http-on-examine-response");
+  }
+};
+
+function whenSavedCachedImageData(tabItem, callback) {
+  tabItem.addSubscriber("savedCachedImageData", function onSaved() {
+    tabItem.removeSubscriber("savedCachedImageData", onSaved);
+    callback();
+  });
+}
+
+function whenDeniedToCacheImageData(tabItem, callback) {
+  tabItem.addSubscriber("deniedToCacheImageData", function onDenied() {
+    tabItem.removeSubscriber("deniedToCacheImageData", onDenied);
+    callback();
+  });
+}
deleted file mode 100644
--- a/browser/base/content/test/tabview/browser_tabview_storage_policy.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const PREF_DISK_CACHE_SSL = "browser.cache.disk_cache_ssl";
-
-let contentWindow;
-let newTab;
-
-function test() {
-  waitForExplicitFinish();
-
-  newTab = gBrowser.addTab();
-
-  HttpRequestObserver.register();
-
-  registerCleanupFunction(function () {
-    HttpRequestObserver.unregister();
-    if (gBrowser.tabs[1])
-      gBrowser.removeTab(gBrowser.tabs[1]);
-    hideTabView();
-
-    Services.prefs.clearUserPref(PREF_DISK_CACHE_SSL);
-  });
-
-  showTabView(function() {
-    contentWindow = TabView.getContentWindow();
-    test1();
-  });
-}
-
-
-function test1() {
-  // page with cache-control: no-store, should not save thumbnail
-  HttpRequestObserver.cacheControlValue = "no-store";
-
-  whenStorageDenied(newTab, function () {
-    let tabItem = newTab._tabViewTabItem;
-
-    ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab), 
-       "Should not save the thumbnail for tab");
-
-    whenDeniedToCacheImageData(tabItem, test2);
-    tabItem.save(true);
-    HttpRequestObserver.cacheControlValue = null;
-  });
-
-  newTab.linkedBrowser.loadURI("http://www.example.com/browser/browser/base/content/test/tabview/dummy_page.html");
-}
-
-function test2() {
-  // page with cache-control: private, should save thumbnail
-  HttpRequestObserver.cacheControlValue = "private";
-
-  newTab.linkedBrowser.loadURI("http://www.example.com/");
-  afterAllTabsLoaded(function() {
-    let tabItem = newTab._tabViewTabItem;
-
-    ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab), 
-       "Should save the thumbnail for tab");
-
-    whenSavedCachedImageData(tabItem, test3);
-    tabItem.save(true);
-  });
-}
-
-function test3() {
-  // page with cache-control: private with https caching enabled, should save thumbnail
-  HttpRequestObserver.cacheControlValue = "private";
-
-  Services.prefs.setBoolPref(PREF_DISK_CACHE_SSL, true);
-
-  newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/dummy_page.html");
-  afterAllTabsLoaded(function() {
-    let tabItem = newTab._tabViewTabItem;
-
-    ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
-       "Should save the thumbnail for tab");
-
-    whenSavedCachedImageData(tabItem, test4);
-    tabItem.save(true);
-  });
-}
-
-function test4() {
-  // page with cache-control: public with https caching disabled, should save thumbnail
-  HttpRequestObserver.cacheControlValue = "public";
-
-  Services.prefs.setBoolPref(PREF_DISK_CACHE_SSL, false);
-
-  newTab.linkedBrowser.loadURI("https://example.com/browser/browser/base/content/test/tabview/");
-  afterAllTabsLoaded(function() {
-    let tabItem = newTab._tabViewTabItem;
-
-    ok(contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
-       "Should save the thumbnail for tab");
-
-    whenSavedCachedImageData(tabItem, test5);
-    tabItem.save(true);
-  });
-}
-
-function test5() {
-  // page with cache-control: private with https caching disabled, should not save thumbnail
-  HttpRequestObserver.cacheControlValue = "private";
-
-  whenStorageDenied(newTab, function () {
-    let tabItem = newTab._tabViewTabItem;
-
-    ok(!contentWindow.StoragePolicy.canStoreThumbnailForTab(newTab),
-       "Should not save the thumbnail for tab");
-
-    whenDeniedToCacheImageData(tabItem, function () {
-      hideTabView(function () {
-        gBrowser.removeTab(gBrowser.tabs[1]);
-        finish();
-      });
-    });
-    tabItem.save(true);
-  });
-
-  newTab.linkedBrowser.loadURI("https://example.com/");
-}
-
-let HttpRequestObserver = {
-  cacheControlValue: null,
-
-  observe: function(subject, topic, data) {
-    if (topic == "http-on-examine-response" && this.cacheControlValue) {
-      let httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
-      httpChannel.setResponseHeader("Cache-Control", this.cacheControlValue, false);
-    }
-  },
-
-  register: function() {
-    Services.obs.addObserver(this, "http-on-examine-response", false);
-  },
-
-  unregister: function() {
-    Services.obs.removeObserver(this, "http-on-examine-response");
-  }
-};
-
-function whenSavedCachedImageData(tabItem, callback) {
-  tabItem.addSubscriber("savedCachedImageData", function onSaved() {
-    tabItem.removeSubscriber("savedCachedImageData", onSaved);
-    callback();
-  });
-}
-
-function whenDeniedToCacheImageData(tabItem, callback) {
-  tabItem.addSubscriber("deniedToCacheImageData", function onDenied() {
-    tabItem.removeSubscriber("deniedToCacheImageData", onDenied);
-    callback();
-  });
-}
-
-function whenStorageDenied(tab, callback) {
-  let mm = tab.linkedBrowser.messageManager;
-
-  mm.addMessageListener("Panorama:StoragePolicy:denied", function onDenied() {
-    mm.removeMessageListener("Panorama:StoragePolicy:denied", onDenied);
-    executeSoon(callback);
-  });
-}