Bug 722273 - [New Tab Page] clear internal links cache on 'browser:purge-session-history'; r=dietrich
authorTim Taubert <tim.taubert@gmx.de>
Mon, 05 Mar 2012 20:59:56 +0100
changeset 91401 151a006fd5d113bf99eee94141bc046fb7553961
parent 91394 75b24396b0ce85ad88afa8048662515c978bdd02
child 91402 cef96693077797edc58e2f2a46f78d16f1f91f70
push idunknown
push userunknown
push dateunknown
reviewersdietrich
bugs722273
milestone13.0a1
Bug 722273 - [New Tab Page] clear internal links cache on 'browser:purge-session-history'; r=dietrich
browser/base/content/test/newtab/Makefile.in
browser/base/content/test/newtab/browser_newtab_bug722273.js
browser/base/content/test/newtab/head.js
browser/modules/NewTabUtils.jsm
--- a/browser/base/content/test/newtab/Makefile.in
+++ b/browser/base/content/test/newtab/Makefile.in
@@ -15,15 +15,16 @@ include $(topsrcdir)/config/rules.mk
 	browser_newtab_block.js \
 	browser_newtab_disable.js \
 	browser_newtab_drag_drop.js \
 	browser_newtab_drop_preview.js \
 	browser_newtab_private_browsing.js \
 	browser_newtab_reset.js \
 	browser_newtab_tabsync.js \
 	browser_newtab_unpin.js \
+	browser_newtab_bug722273.js \
 	browser_newtab_bug723102.js \
 	browser_newtab_bug723121.js \
 	head.js \
 	$(NULL)
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/newtab/browser_newtab_bug722273.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const NOW = Date.now() * 1000;
+const URL = "http://fake-site.com/";
+
+let tmp = {};
+Cu.import("resource:///modules/NewTabUtils.jsm", tmp);
+Cc["@mozilla.org/moz/jssubscript-loader;1"]
+  .getService(Ci.mozIJSSubScriptLoader)
+  .loadSubScript("chrome://browser/content/sanitize.js", tmp);
+
+let {NewTabUtils, Sanitizer} = tmp;
+
+let bhist = Cc["@mozilla.org/browser/global-history;2"]
+  .getService(Ci.nsIBrowserHistory);
+
+function runTests() {
+  clearHistory();
+  fillHistory();
+  yield addNewTabPageTab();
+
+  is(cells[0].site.url, URL, "first site is our fake site");
+
+  let page = {
+    update: function () {
+      executeSoon(TestRunner.next);
+    },
+
+    observe: function () {}
+  };
+
+  NewTabUtils.allPages.register(page);
+  yield clearHistory();
+
+  NewTabUtils.allPages.unregister(page);
+  ok(!cells[0].site, "the fake site is gone");
+}
+
+function fillHistory() {
+  let uri = makeURI(URL);
+  for (let i = 59; i > 0; i--)
+    bhist.addPageWithDetails(uri, "fake site", NOW - i * 60 * 1000000);
+}
+
+function clearHistory() {
+  let s = new Sanitizer();
+  s.prefDomain = "privacy.cpd.";
+
+  let prefs = gPrefService.getBranch(s.prefDomain);
+  prefs.setBoolPref("history", true);
+  prefs.setBoolPref("downloads", false);
+  prefs.setBoolPref("cache", false);
+  prefs.setBoolPref("cookies", false);
+  prefs.setBoolPref("formdata", false);
+  prefs.setBoolPref("offlineApps", false);
+  prefs.setBoolPref("passwords", false);
+  prefs.setBoolPref("sessions", false);
+  prefs.setBoolPref("siteSettings", false);
+
+  s.sanitize();
+}
--- a/browser/base/content/test/newtab/head.js
+++ b/browser/base/content/test/newtab/head.js
@@ -124,20 +124,21 @@ function addNewTabPageTab() {
 
   // Wait for the new tab page to be loaded.
   browser.addEventListener("load", function onLoad() {
     browser.removeEventListener("load", onLoad, true);
 
     cw = browser.contentWindow;
 
     if (NewTabUtils.allPages.enabled) {
-      cells = cw.gGrid.cells;
-
       // Continue when the link cache has been populated.
-      NewTabUtils.links.populateCache(TestRunner.next);
+      NewTabUtils.links.populateCache(function () {
+        cells = cw.gGrid.cells;
+        executeSoon(TestRunner.next);
+      });
     } else {
       TestRunner.next();
     }
 
   }, true);
 }
 
 /**
@@ -241,16 +242,18 @@ function unpinCell(aCell) {
 
 /**
  * Simulates a drop and drop operation.
  * @param aDropTarget the cell that is the drop target
  * @param aDragSource the cell that contains the dragged site (optional)
  */
 function simulateDrop(aDropTarget, aDragSource) {
   let event = {
+    clientX: 0,
+    clientY: 0,
     dataTransfer: {
       mozUserCancelled: false,
       setData: function () null,
       setDragImage: function () null,
       getData: function () "about:blank#99\nblank"
     }
   };
 
--- a/browser/modules/NewTabUtils.jsm
+++ b/browser/modules/NewTabUtils.jsm
@@ -116,18 +116,16 @@ let Storage = {
       // Reset to normal DOM storage.
       this.currentStorage = this.domStorage;
 
       // When switching back from private browsing we need to reset the
       // grid and re-read its values from the underlying storage. We don't
       // want any data from private browsing to show up.
       PinnedLinks.resetCache();
       BlockedLinks.resetCache();
-
-      Pages.update();
     }
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference])
 };
 
 /**
@@ -183,37 +181,27 @@ PrivateBrowsingStorage.prototype = {
  */
 let AllPages = {
   /**
    * The array containing all active pages.
    */
   _pages: [],
 
   /**
-   * Tells whether we already added a preference observer.
-   */
-  _observing: false,
-
-  /**
    * Cached value that tells whether the New Tab Page feature is enabled.
    */
   _enabled: null,
 
   /**
    * Adds a page to the internal list of pages.
    * @param aPage The page to register.
    */
   register: function AllPages_register(aPage) {
     this._pages.push(aPage);
-
-    // Add the preference observer if we haven't already.
-    if (!this._observing) {
-      this._observing = true;
-      Services.prefs.addObserver(PREF_NEWTAB_ENABLED, this, true);
-    }
+    this._addObserver();
   },
 
   /**
    * Removes a page from the internal list of pages.
    * @param aPage The page to unregister.
    */
   unregister: function AllPages_unregister(aPage) {
     let index = this._pages.indexOf(aPage);
@@ -234,16 +222,24 @@ let AllPages = {
    * Enables or disables the 'New Tab Page' feature.
    */
   set enabled(aEnabled) {
     if (this.enabled != aEnabled)
       Services.prefs.setBoolPref(PREF_NEWTAB_ENABLED, !!aEnabled);
   },
 
   /**
+   * Returns the number of registered New Tab Pages (i.e. the number of open
+   * about:newtab instances).
+   */
+  get length() {
+    return this._pages.length;
+  },
+
+  /**
    * Updates all currently active pages but the given one.
    * @param aExceptPage The page to exclude from updating.
    */
   update: function AllPages_update(aExceptPage) {
     this._pages.forEach(function (aPage) {
       if (aExceptPage != aPage)
         aPage.update();
     });
@@ -259,16 +255,25 @@ let AllPages = {
 
     let args = Array.slice(arguments);
 
     this._pages.forEach(function (aPage) {
       aPage.observe.apply(aPage, args);
     }, this);
   },
 
+  /**
+   * Adds a preference observer and turns itself into a no-op after the first
+   * invokation.
+   */
+  _addObserver: function AllPages_addObserver() {
+    Services.prefs.addObserver(PREF_NEWTAB_ENABLED, this, true);
+    this._addObserver = function () {};
+  },
+
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference])
 };
 
 /**
  * Singleton that keeps track of all pinned links and their positions in the
  * grid.
  */
@@ -507,16 +512,18 @@ let Links = {
 
     if (this._links && !aForce) {
       executeCallbacks();
     } else {
       this._provider.getLinks(function (aLinks) {
         this._links = aLinks;
         executeCallbacks();
       }.bind(this));
+
+      this._addObserver();
     }
   },
 
   /**
    * Gets the current set of links contained in the grid.
    * @return The links in the grid.
    */
   getLinks: function Links_getLinks() {
@@ -539,17 +546,42 @@ let Links = {
     return pinnedLinks;
   },
 
   /**
    * Resets the links cache.
    */
   resetCache: function Links_resetCache() {
     this._links = [];
-  }
+  },
+
+  /**
+   * Implements the nsIObserver interface to get notified about browser history
+   * sanitization.
+   */
+  observe: function Links_observe(aSubject, aTopic, aData) {
+    // Make sure to update open about:newtab instances. If there are no opened
+    // pages we can just wait for the next new tab to populate the cache again.
+    if (AllPages.length && AllPages.enabled)
+      this.populateCache(function () { AllPages.update() }, true);
+    else
+      this._links = null;
+  },
+
+  /**
+   * Adds a sanitization observer and turns itself into a no-op after the first
+   * invokation.
+   */
+  _addObserver: function Links_addObserver() {
+    Services.obs.addObserver(this, "browser:purge-session-history", true);
+    this._addObserver = function () {};
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                         Ci.nsISupportsWeakReference])
 };
 
 /**
  * Singleton that provides the public API of this JSM.
  */
 let NewTabUtils = {
   /**
    * Resets the NewTabUtils module, its links and its storage.