Bug 520165 - Part7: Provide a new preference to toggle history, r=mano ui-r=faaborg
authorMarco Bonardo <mbonardo@mozilla.com>
Fri, 15 Jan 2010 17:40:14 +0100
changeset 37225 6070563dee67be37a4f45cf829cea2ad2ea3c119
parent 37224 f85c8c1c111e365a0f3dc16823e91e7c9e2a9182
child 37226 1a6355f9da5a6f7e43b906f49e487523f59c322e
push idunknown
push userunknown
push dateunknown
reviewersmano, faaborg
bugs520165
milestone1.9.3a1pre
Bug 520165 - Part7: Provide a new preference to toggle history, r=mano ui-r=faaborg
browser/app/profile/firefox.js
browser/components/preferences/privacy.js
browser/components/preferences/privacy.xul
browser/components/preferences/tests/browser_privacypane_3.js
browser/components/preferences/tests/privacypane_tests.js
browser/locales/en-US/chrome/browser/preferences/privacy.dtd
toolkit/components/places/public/nsINavHistoryService.idl
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/places/src/nsNavHistory.h
toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
toolkit/components/places/tests/unit/test_download_history.js
toolkit/components/places/tests/unit/test_history.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -779,16 +779,19 @@ pref("browser.sessionstore.max_tabs_undo
 pref("browser.sessionstore.max_windows_undo", 3);
 // number of crashes that can occur before the about:sessionrestore page is displayed
 // (this pref has no effect if more than 6 hours have passed since the last crash)
 pref("browser.sessionstore.max_resumed_crashes", 1);
 
 // allow META refresh by default
 pref("accessibility.blockautorefresh", false);
 
+// Whether history is enabled or not.
+pref("places.history.enabled", true);
+
 // The percentage of system memory that the Places database can use.  Out of the
 // allowed cache size it will at most use the size of the database file.
 // Changes to this value are effective after an application restart.
 // Acceptable values are between 0 and 50.
 pref("places.database.cache_to_memory_percentage", 6);
 
 // the (maximum) number of the recent visits to sample
 // when calculating frecency
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -51,17 +51,16 @@ var gPrivacyPane = {
   _autoStartPrivateBrowsing: false,
 
   /**
    * Sets up the UI for the number of days of history to keep, and updates the
    * label of the "Clear Now..." button.
    */
   init: function ()
   {
-    this._updateHistoryDaysUI();
     this._updateSanitizeSettingsButton();
     this.initializeHistoryMode();
     this.updateHistoryModePane();
     this.updatePrivacyMicroControls();
     this.initAutoStartPrivateBrowsingObserver();
   },
 
   // HISTORY MODE
@@ -73,35 +72,33 @@ var gPrivacyPane = {
    * If all of these preferences have their default values, and the auto-start
    * private browsing mode is not active, the initial history mode would be
    * set to "Remember everything".
    * Otherwise, the initial history mode would be set to "Custom".
    *
    * Extensions adding their own preferences can append their IDs to this array if needed.
    */
   prefsForDefault: [
-    "browser.history_expire_days",
-    "browser.history_expire_days_min",
+    "places.history.enabled",
     "browser.download.manager.retention",
     "browser.formfill.enable",
     "network.cookie.cookieBehavior",
     "network.cookie.lifetimePolicy",
     "privacy.sanitize.sanitizeOnShutdown"
   ],
 
   /**
    * The list of control IDs which are dependent on the auto-start private
    * browsing setting, such that in "Custom" mode they would be disabled if
    * the auto-start private browsing checkbox is checked, and enabled otherwise.
    *
    * Extensions adding their own controls can append their IDs to this array if needed.
    */
   dependentControls: [
-    "rememberHistoryDays",
-    "rememberAfter",
+    "rememberHistory",
     "rememberDownloads",
     "rememberForms",
     "keepUntil",
     "keepCookiesUntil",
     "alwaysClear",
     "clearDataSettings"
   ],
 
@@ -169,21 +166,19 @@ var gPrivacyPane = {
   updateHistoryModePrefs: function PPP_updateHistoryModePrefs()
   {
     let pref = document.getElementById("browser.privatebrowsing.autostart");
     switch (document.getElementById("historyMode").value) {
     case "remember":
       pref.value = false;
 
       // select the remember history option if needed
-      let rememberHistoryCheckbox = document.getElementById("rememberHistoryDays");
-      if (!rememberHistoryCheckbox.checked) {
+      let rememberHistoryCheckbox = document.getElementById("rememberHistory");
+      if (!rememberHistoryCheckbox.checked)
         rememberHistoryCheckbox.checked = true;
-        this.onchangeHistoryDaysCheck();
-      }
 
       // select the remember downloads option if needed
       if (!document.getElementById("rememberDownloads").checked)
         document.getElementById("browser.download.manager.retention").value = 2;
 
       // select the remember forms history option
       document.getElementById("browser.formfill.enable").value = true;
 
@@ -219,19 +214,18 @@ var gPrivacyPane = {
       document.getElementById("keepCookiesUntil").value = disabled ? 2 :
         document.getElementById("network.cookie.lifetimePolicy").value;
 
       // adjust the checked state of the sanitizeOnShutdown checkbox
       document.getElementById("alwaysClear").checked = disabled ? false :
         document.getElementById("privacy.sanitize.sanitizeOnShutdown").value;
 
       // adjust the checked state of the remember history checkboxes
-      document.getElementById("rememberHistoryDays").checked = disabled ? false :
-        document.getElementById("browser.history_expire_days").value > 0;
-      this.onchangeHistoryDaysCheck();
+      document.getElementById("rememberHistory").checked = disabled ? false :
+        document.getElementById("places.history.enabled").value;
       document.getElementById("rememberDownloads").checked = disabled ? false :
         this.readDownloadRetention();
       document.getElementById("rememberForms").checked = disabled ? false :
         document.getElementById("browser.formfill.enable").value;
 
       if (!disabled) {
         // adjust the Settings button for sanitizeOnShutdown
         this._updateSanitizeSettingsButton();
@@ -314,95 +308,31 @@ var gPrivacyPane = {
 
     // Always update the enabled pref
     return enabled;
   },
 
   /*
    * Preferences:
    *
-   * NOTE: These first two are no longer shown in the UI. They're controlled
-   *       via the checkbox, which uses the zero state of the pref to turn
-   *       history off.
-   * browser.history_expire_days
-   * - the number of days of history to remember
-   * browser.history_expire_days.mirror
-   * - a preference whose value mirrors that of browser.history_expire_days, to
-   *   make the "days of history" checkbox easier to code
-   *
-   * browser.history_expire_days_min
-   * - the mininum number of days of history to remember
-   * browser.history_expire_days_min.mirror
-   * - a preference whose value mirrors that of browser.history_expire_days_min
-   *   to make the "days of history" checkbox easier to code
+   * places.history.enabled
+   * - whether history is enabled or not
    * browser.formfill.enable
    * - true if entries in forms and the search bar should be saved, false
    *   otherwise
    * browser.download.manager.retention
    * - determines when downloads are automatically removed from the download
    *   manager:
    *
    *     0 means remove downloads when they finish downloading
    *     1 means downloads will be removed when the browser quits
    *     2 means never remove downloads
    */
 
   /**
-   * Initializes the days-of-history mirror preference and connects it to the
-   * days-of-history checkbox so that updates to the textbox are transmitted to
-   * the real days-of-history preference.
-   */
-  _updateHistoryDaysUI: function ()
-  {
-    var pref = document.getElementById("browser.history_expire_days");
-    var mirror = document.getElementById("browser.history_expire_days.mirror");
-    var pref_min = document.getElementById("browser.history_expire_days_min");
-    var textbox = document.getElementById("historyDays");
-    var checkbox = document.getElementById("rememberHistoryDays");
-
-    // handle mirror non-existence or mirror/pref unsync
-    if (mirror.value === null || mirror.value != pref.value || 
-        (mirror.value == pref.value && mirror.value == 0) )
-      mirror.value = pref.value ? pref.value : pref.defaultValue;
-
-    checkbox.checked = (pref.value > 0);
-    textbox.disabled = !checkbox.checked;
-  },
-
-  /**
-   * Responds to the checking or unchecking of the days-of-history UI, storing
-   * the appropriate value to the days-of-history preference and enabling or
-   * disabling the number textbox as appropriate.
-   */
-  onchangeHistoryDaysCheck: function ()
-  {
-    var pref = document.getElementById("browser.history_expire_days");
-    var mirror = document.getElementById("browser.history_expire_days.mirror");
-    var textbox = document.getElementById("historyDays");
-    var checkbox = document.getElementById("rememberHistoryDays");
-
-    if (!this._autoStartPrivateBrowsing)
-      pref.value = checkbox.checked ? mirror.value : 0;
-    textbox.disabled = !checkbox.checked;
-  },
-
-  /**
-   * Responds to changes in the days-of-history textbox,
-   * unchecking the history-enabled checkbox if the days
-   * value is zero.
-   */
-  onkeyupHistoryDaysText: function ()
-  {
-    var textbox = document.getElementById("historyDays");
-    var checkbox = document.getElementById("rememberHistoryDays");
-    
-    checkbox.checked = textbox.value != 0;
-  },
-
-  /**
    * Converts the value of the browser.download.manager.retention preference
    * into a Boolean value.  "remove on close" and "don't remember" both map
    * to an unchecked checkbox, while "remember" maps to a checked checkbox.
    */
   readDownloadRetention: function ()
   {
     var pref = document.getElementById("browser.download.manager.retention");
     return (pref.value == 2);
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -71,25 +71,19 @@
                   name="browser.urlbar.autocomplete.enabled"
                   type="bool"/>
       <preference id="browser.urlbar.default.behavior"
                   name="browser.urlbar.default.behavior"
                   type="int"
                   onchange="document.getElementById('browser.urlbar.autocomplete.enabled').updateElements();"/>
 
       <!-- History -->
-      <preference id="browser.history_expire_days"
-                  name="browser.history_expire_days"
-                  type="int"/>
-      <preference id="browser.history_expire_days.mirror"
-                  name="browser.history_expire_days.mirror"
-                  type="int"/>
-      <preference id="browser.history_expire_days_min"
-                  name="browser.history_expire_days_min"
-                  type="int"/>
+      <preference id="places.history.enabled"
+                  name="places.history.enabled"
+                  type="bool"/>
       <preference id="browser.formfill.enable"
                   name="browser.formfill.enable"
                   type="bool"/>
       <preference id="browser.download.manager.retention"
                   name="browser.download.manager.retention"
                   type="int"/>
 
       <!-- Cookies -->
@@ -179,28 +173,20 @@
           <separator class="thin"/>
           <checkbox id="privateBrowsingAutoStart" class="indent"
                     label="&privateBrowsingPermanent.label;"
                     accesskey="&privateBrowsingPermanent.accesskey;"
                     preference="browser.privatebrowsing.autostart"/>
 
           <vbox class="indent">
             <vbox class="indent">
-              <hbox align="center">
-                <checkbox id="rememberHistoryDays"
-                          label="&rememberHistory.pre.label;"
-                          accesskey="&rememberHistory.pre.accesskey;"
-                          oncommand="gPrivacyPane.onchangeHistoryDaysCheck();"
-                          aria-labelledby="rememberHistoryDays historyDays rememberAfter"/>
-                <textbox id="historyDays" type="number" size="3"
-                         aria-labelledby="rememberHistoryDays historyDays rememberAfter"
-                         onkeyup="gPrivacyPane.onkeyupHistoryDaysText();"
-                         preference="browser.history_expire_days_min"/>
-                <label id="rememberAfter"> &rememberHistory.post.label;</label>
-              </hbox>
+              <checkbox id="rememberHistory"
+                        label="&rememberHistory.label;"
+                        accesskey="&rememberHistory.accesskey;"
+                        preference="places.history.enabled"/>
               <checkbox id="rememberDownloads"
                         label="&rememberDownload.label;"
                         accesskey="&rememberDownload.accesskey;"
                         preference="browser.download.manager.retention"
                         onsyncfrompreference="return gPrivacyPane.readDownloadRetention();"
                         onsynctopreference="return gPrivacyPane.writeDownloadRetention();"/>
               <checkbox id="rememberForms"
                         label="&rememberSearchForm.label;"
--- a/browser/components/preferences/tests/browser_privacypane_3.js
+++ b/browser/components/preferences/tests/browser_privacypane_3.js
@@ -36,20 +36,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 function test() {
   let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
                getService(Ci.mozIJSSubScriptLoader);
   loader.loadSubScript("chrome://mochikit/content/browser/browser/components/preferences/tests/privacypane_tests.js", this);
 
   run_test_subset([
-    test_custom_retention("rememberHistoryDays", "remember"),
-    test_custom_retention("rememberHistoryDays", "custom"),
-    test_custom_retention("historyDays", "remember", 1),
-    test_custom_retention("historyDays", "custom", -1),
+    test_custom_retention("rememberHistory", "remember"),
+    test_custom_retention("rememberHistory", "custom"),
     test_custom_retention("rememberDownloads", "remember"),
     test_custom_retention("rememberDownloads", "custom"),
     test_custom_retention("rememberForms", "remember"),
     test_custom_retention("rememberForms", "custom"),
     test_historymode_retention("remember", "remember"),
 
     // reset all preferences to their default values once we're done
     reset_preferences
--- a/browser/components/preferences/tests/privacypane_tests.js
+++ b/browser/components/preferences/tests/privacypane_tests.js
@@ -102,19 +102,17 @@ function test_pane_visibility(win) {
 }
 
 function test_dependent_elements(win) {
   let historymode = win.document.getElementById("historyMode");
   ok(historymode, "history mode menulist should exist");
   let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
   ok(pbautostart, "the private browsing auto-start checkbox should exist");
   let controls = [
-    win.document.getElementById("rememberHistoryDays"),
-    win.document.getElementById("historyDays"),
-    win.document.getElementById("rememberAfter"),
+    win.document.getElementById("rememberHistory"),
     win.document.getElementById("rememberDownloads"),
     win.document.getElementById("rememberForms"),
     win.document.getElementById("keepUntil"),
     win.document.getElementById("keepCookiesUntil"),
     win.document.getElementById("alwaysClear"),
   ];
   controls.forEach(function(control) {
     ok(control, "the dependent controls should exist");
@@ -127,17 +125,17 @@ function test_dependent_elements(win) {
     ok(control, "the independent controls should exist");
   });
   let cookieexceptions = win.document.getElementById("cookieExceptions");
   ok(cookieexceptions, "the cookie exceptions button should exist");
   let keepuntil = win.document.getElementById("keepCookiesUntil");
   ok(keepuntil, "the keep cookies until menulist should exist");
   let alwaysclear = win.document.getElementById("alwaysClear");
   ok(alwaysclear, "the clear data on close checkbox should exist");
-  let rememberhistory = win.document.getElementById("rememberHistoryDays");
+  let rememberhistory = win.document.getElementById("rememberHistory");
   ok(rememberhistory, "the remember history checkbox should exist");
   let rememberdownloads = win.document.getElementById("rememberDownloads");
   ok(rememberdownloads, "the remember downloads checkbox should exist");
   let rememberforms = win.document.getElementById("rememberForms");
   ok(rememberforms, "the remember forms checkbox should exist");
   let alwaysclearsettings = win.document.getElementById("clearDataSettings");
   ok(alwaysclearsettings, "the clear data settings button should exist");
 
@@ -314,17 +312,17 @@ function test_dependent_clearonclose_ele
   controlChanged(alwaysclear);
   expect_disabled(true);
 }
 
 function test_dependent_prefs(win) {
   let historymode = win.document.getElementById("historyMode");
   ok(historymode, "history mode menulist should exist");
   let controls = [
-    win.document.getElementById("rememberHistoryDays"),
+    win.document.getElementById("rememberHistory"),
     win.document.getElementById("rememberDownloads"),
     win.document.getElementById("rememberForms"),
     win.document.getElementById("acceptCookies"),
     win.document.getElementById("acceptThirdParty"),
   ];
   controls.forEach(function(control) {
     ok(control, "the micro-management controls should exist");
   });
--- a/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -55,25 +55,18 @@
 <!-- LOCALIZATION NOTE (dontrememberActions.post.label): include a starting space as needed -->
 <!ENTITY  dontrememberActions.pre.label          "You may also want to ">
 <!ENTITY  dontrememberActions.clearHistory.label "clear all current history">
 <!ENTITY  dontrememberActions.post.label         ".">
 
 <!ENTITY  privateBrowsingPermanent.label "Permanent Private Browsing mode">
 <!ENTITY  privateBrowsingPermanent.accesskey "P">
 
-<!-- LOCALIZATION NOTE:
-  The entities rememberHistory.pre.label and rememberHistory.post.label appear on a single
-  line in preferences as follows:
-
-  &rememberHistory.pre.label  [ textbox for number of days ]  &rememberHistory.post.label;
--->
-<!ENTITY  rememberHistory.pre.label      "Remember my browsing history for at least">
-<!ENTITY  rememberHistory.pre.accesskey  "b">
-<!ENTITY  rememberHistory.post.label     "days">
+<!ENTITY  rememberHistory.label      "Remember my browsing history">
+<!ENTITY  rememberHistory.accesskey  "b">
 
 <!ENTITY  rememberDownload.label         "Remember download history">
 <!ENTITY  rememberDownload.accesskey     "d">
 
 <!ENTITY  rememberSearchForm.label       "Remember search and form history">
 <!ENTITY  rememberSearchForm.accesskey   "f">
 
 <!ENTITY  clearOnClose.label             "Clear history when &brandShortName; closes">
--- a/toolkit/components/places/public/nsINavHistoryService.idl
+++ b/toolkit/components/places/public/nsINavHistoryService.idl
@@ -1454,17 +1454,17 @@ interface nsINavHistoryService : nsISupp
    * @param aUserData
    *        Opaque parameter passed to nsINavBookmarksBatchCallback
    */
   void runInBatchMode(in nsINavHistoryBatchCallback aCallback,
                       in nsISupports aClosure);
 
   /** 
    * True if history is disabled. currently, 
-   * history is disabled if the browser.history_expire_days pref is 0
+   * history is disabled if the places.history.enabled pref is false.
    */
   readonly attribute boolean historyDisabled;
 
   /**
    * Import the given Mork history file.
    *  @param file     The Mork history file to import
    */
   void importHistory(in nsIFile file);
--- a/toolkit/components/places/src/nsNavHistory.cpp
+++ b/toolkit/components/places/src/nsNavHistory.cpp
@@ -99,16 +99,18 @@ using namespace mozilla::places;
 // is very difficult to get that many unconsumed events (for example, typed but
 // never visited) in the RECENT_EVENT_THRESHOLD. Otherwise, we'll start
 // checking each one for every page visit, which will be somewhat slower.
 #define RECENT_EVENT_QUEUE_MAX_LENGTH 128
 
 // preference ID strings
 #define PREF_BRANCH_BASE                        "browser."
 
+#define PREF_HISTORY_ENABLED                    "places.history.enabled"
+
 #define PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN    "history_expire_days_min"
 #define PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX    "history_expire_days"
 #define PREF_BROWSER_HISTORY_EXPIRE_SITES       "history_expire_sites"
 
 #define PREF_FRECENCY_NUM_VISITS                "places.frecency.numVisits"
 #define PREF_FRECENCY_FIRST_BUCKET_CUTOFF       "places.frecency.firstBucketCutoff"
 #define PREF_FRECENCY_SECOND_BUCKET_CUTOFF      "places.frecency.secondBucketCutoff"
 #define PREF_FRECENCY_THIRD_BUCKET_CUTOFF       "places.frecency.thirdBucketCutoff"
@@ -394,16 +396,17 @@ nsNavHistory::nsNavHistory()
 : mBatchLevel(0)
 , mBatchHasTransaction(PR_FALSE)
 , mCachedNow(0)
 , mExpireNowTimer(nsnull)
 , mLastSessionID(0)
 , mExpireDaysMin(0)
 , mExpireDaysMax(0)
 , mExpireSites(0)
+, mHistoryEnabled(PR_TRUE)
 , mNumVisitsForFrecency(10)
 , mTagsFolder(-1)
 , mInPrivateBrowsing(PRIVATEBROWSING_NOTINITED)
 , mDatabaseStatus(DATABASE_STATUS_OK)
 , mCanNotify(true)
 , mCacheObservers("history-observers")
 {
 #ifdef LAZY_ADD
@@ -494,16 +497,21 @@ nsNavHistory::Init()
 
   nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
   if (pbi) {
     pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX, this, PR_FALSE);
     pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN, this, PR_FALSE);
     pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_SITES, this, PR_FALSE);
   }
 
+  nsCOMPtr<nsIPrefBranch2> prefs =
+    do_GetService("@mozilla.org/preferences-service;1");
+  if (prefs)
+    prefs->AddObserver(PREF_HISTORY_ENABLED, this, PR_FALSE);
+
   nsCOMPtr<nsIObserverService> obsSvc =
     do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
   if (obsSvc) {
     (void)obsSvc->AddObserver(this, TOPIC_XPCOM_SHUTDOWN, PR_FALSE);
     (void)obsSvc->AddObserver(this, TOPIC_IDLE_DAILY, PR_FALSE);
     (void)obsSvc->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, PR_FALSE);
 #ifdef MOZ_XUL
     (void)obsSvc->AddObserver(this, TOPIC_AUTOCOMPLETE_FEEDBACK_INCOMING, PR_FALSE);
@@ -2044,16 +2052,18 @@ nsNavHistory::LoadPrefs(PRBool aInitiali
     mExpireDaysMax = mExpireDaysMin;
   if (NS_FAILED(mPrefBranch->GetIntPref(PREF_BROWSER_HISTORY_EXPIRE_SITES,
                                         &mExpireSites)))
     mExpireSites = EXPIRATION_CAP_SITES;
 
   // get the frecency prefs
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
   if (prefs) {
+    prefs->GetBoolPref(PREF_HISTORY_ENABLED, &mHistoryEnabled);
+
     prefs->GetIntPref(PREF_FRECENCY_NUM_VISITS, 
       &mNumVisitsForFrecency);
     prefs->GetIntPref(PREF_FRECENCY_FIRST_BUCKET_CUTOFF, 
       &mFirstBucketCutoffInDays);
     prefs->GetIntPref(PREF_FRECENCY_SECOND_BUCKET_CUTOFF,
       &mSecondBucketCutoffInDays);
     prefs->GetIntPref(PREF_FRECENCY_THIRD_BUCKET_CUTOFF, 
       &mThirdBucketCutoffInDays);
@@ -5529,18 +5539,28 @@ nsNavHistory::Observe(nsISupports *aSubj
         rv = observer->Observe(observer,
                                TOPIC_PLACES_INIT_COMPLETE,
                                nsnull);
       }
     }
 
     nsCOMPtr<nsIPrefService> prefService =
       do_GetService(NS_PREFSERVICE_CONTRACTID);
-    if (prefService)
+    if (prefService) {
       prefService->SavePrefFile(nsnull);
+      nsCOMPtr<nsIPrefBranch2> prefs = do_QueryInterface(prefService);
+      prefs->RemoveObserver(PREF_HISTORY_ENABLED, this);
+    }
+
+    nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
+    if (pbi) {
+      pbi->RemoveObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX, this);
+      pbi->RemoveObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN, this);
+      pbi->RemoveObserver(PREF_BROWSER_HISTORY_EXPIRE_SITES, this);
+    }
 
     // Start shutdown expiration.
     mExpire->OnQuit();
 
 #ifdef LAZY_ADD
     // Commit all pending lazy messages.
     CommitLazyMessages(PR_TRUE);
 
--- a/toolkit/components/places/src/nsNavHistory.h
+++ b/toolkit/components/places/src/nsNavHistory.h
@@ -208,18 +208,20 @@ public:
   nsIStringBundle* GetBundle();
   nsIStringBundle* GetDateFormatBundle();
   nsICollation* GetCollation();
   void GetStringFromName(const PRUnichar* aName, nsACString& aResult);
   void GetAgeInDaysString(PRInt32 aInt, const PRUnichar *aName,
                           nsACString& aResult);
   void GetMonthName(PRInt32 aIndex, nsACString& aResult);
 
-  // returns true if history has been disabled
-  PRBool IsHistoryDisabled() { return mExpireDaysMax == 0 || InPrivateBrowsingMode(); }
+  // Returns whether history is enabled or not.
+  PRBool IsHistoryDisabled() {
+    return mExpireDaysMax == 0 || !mHistoryEnabled || InPrivateBrowsingMode();
+  }
 
   // Constants for the columns returned by the above statement.
   static const PRInt32 kGetInfoIndex_PageID;
   static const PRInt32 kGetInfoIndex_URL;
   static const PRInt32 kGetInfoIndex_Title;
   static const PRInt32 kGetInfoIndex_RevHost;
   static const PRInt32 kGetInfoIndex_VisitCount;
   static const PRInt32 kGetInfoIndex_ItemId;
@@ -655,16 +657,20 @@ protected:
   nsresult AutoCompleteFeedback(PRInt32 aIndex,
                                 nsIAutoCompleteController *aController);
 #endif
 
   PRInt32 mExpireDaysMin;
   PRInt32 mExpireDaysMax;
   PRInt32 mExpireSites;
 
+  // Whether history is enabled or not.
+  // Will mimic value of the places.history.enabled preference.
+  PRBool mHistoryEnabled;
+
   // Frecency preferences.
   PRInt32 mNumVisitsForFrecency;
   PRInt32 mFirstBucketCutoffInDays;
   PRInt32 mSecondBucketCutoffInDays;
   PRInt32 mThirdBucketCutoffInDays;
   PRInt32 mFourthBucketCutoffInDays;
   PRInt32 mFirstBucketWeight;
   PRInt32 mSecondBucketWeight;
--- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
+++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
@@ -86,45 +86,45 @@ var tests = [
 
   // TODO bug 527036: There is no way to know whether setting a favicon failed.
   //{
   //  desc: "test setAndLoadFaviconForPage with history disabled",
   //  pageURI: uri("http://test2.bar/"),
   //  go: function go4() {
   //    // disable history
   //    var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
-  //    prefs.setIntPref("browser.history_expire_days", 0);
+  //    prefs.setBoolPref("places.history.enabled", false);
   //
   //    iconsvc.setAndLoadFaviconForPage(this.pageURI, favicons[0].uri, true);
   //
   //    try {
-  //      prefs.clearUserPref("browser.history_expire_days");
+  //      prefs.clearUserPref("places.history.enabled");
   //    } catch (ex) {}
   //  },
   //  check: function check4() {
   //    checkAddFailed(this.pageURI);
   //  }
   //},
 
   {
     desc: "test setAndLoadFaviconForPage with history disabled for bookmarked URI",
     pageURI: uri("http://test3.bar/"),
     favicon: favicons[0],
     go: function go5() {
       // disable history
       var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
-      prefs.setIntPref("browser.history_expire_days", 0);
+      prefs.setBoolPref("places.history.enabled", false);
 
       // Add as bookmark
       addBookmark(this.pageURI);
 
       iconsvc.setAndLoadFaviconForPage(this.pageURI, this.favicon.uri, true);
 
       try {
-        prefs.clearUserPref("browser.history_expire_days");
+        prefs.clearUserPref("places.history.enabled");
       } catch (ex) {}
     },
     check: function check5() {
       checkAddSucceeded(this.pageURI, this.favicon.mimetype, this.favicon.data);
     }
   },
 
   // TODO bug 527036: There is no way to know whether setting a favicon failed.
--- a/toolkit/components/places/tests/unit/test_download_history.js
+++ b/toolkit/components/places/tests/unit/test_download_history.js
@@ -47,17 +47,17 @@ var os = Cc["@mozilla.org/observer-servi
 var prefs = Cc["@mozilla.org/preferences-service;1"].
             getService(Ci.nsIPrefBranch);
 var dh = Cc["@mozilla.org/browser/download-history;1"].
          getService(Ci.nsIDownloadHistory);
 // Test that this nsIDownloadHistory is the one places implements.
 do_check_true(dh instanceof Ci.nsINavHistoryService);
 
 const NS_LINK_VISITED_EVENT_TOPIC = "link-visited";
-const DISABLE_HISTORY_PREF = "browser.history_expire_days";
+const ENABLE_HISTORY_PREF = "places.history.enabled";
 const PB_KEEP_SESSION_PREF = "browser.privatebrowsing.keep_current_session";
 
 var testURI = uri("http://google.com/");
 var referrerURI = uri("http://yahoo.com");
 
 /**
  * Checks to see that a URI is in the database.
  *
@@ -110,26 +110,26 @@ function test_dh_privateBrowsing() {
   uri_in_db(referrerURI, false);
 
   // Cleanup
   pb.privateBrowsingEnabled = false;
 }
 
 function test_dh_disabledHistory() {
   // Disable history
-  prefs.setIntPref(DISABLE_HISTORY_PREF, 0);
+  prefs.setBoolPref(ENABLE_HISTORY_PREF, false);
 
   dh.addDownload(testURI, referrerURI, Date.now() * 1000);
 
   do_check_false(observer.topicReceived);
   uri_in_db(testURI, false);
   uri_in_db(referrerURI, false);
 
   // Cleanup
-  prefs.setIntPref(DISABLE_HISTORY_PREF, 180);
+  prefs.setBoolPref(ENABLE_HISTORY_PREF, true);
 }
 
 var tests = [
   test_dh,
   test_dh_privateBrowsing,
   test_dh_disabledHistory,
 ];
 
--- a/toolkit/components/places/tests/unit/test_history.js
+++ b/toolkit/components/places/tests/unit/test_history.js
@@ -178,17 +178,17 @@ function run_test() {
 
   // test annotationIsNot
   query.annotationIsNot = true;
   result = histsvc.executeQuery(query, options);
   result.root.containerOpen = true;
   do_check_eq(result.root.childCount, 1);
   do_check_eq(result.root.getChild(0).uri, "http://google.com/");
 
-  // by default, browser.history_expire_days is 9
+  // By default history is enabled.
   do_check_true(!histsvc.historyDisabled);
 
   // test getPageTitle
   var title = histsvc.getPageTitle(uri("http://mozilla.com"));
   do_check_eq(title, null);
 
   // query for the visit
   do_check_true(uri_in_db(testURI));