Bug 1275878 - Part 1: move back clear history operations to History.clear(). r=adw
authorMarco Bonardo <mbonardo@mozilla.com>
Tue, 17 May 2016 09:35:45 +0200
changeset 419247 a4ae03c61b155067d5c815a4bc09ddc98b6ee86f
parent 419246 cab53621bfee5fc6f3b41b69f3ec73b40ab35b0d
child 419248 b217b97a74781c5d8d2f981651467331f04f6078
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersadw
bugs1275878
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1275878 - Part 1: move back clear history operations to History.clear(). r=adw MozReview-Commit-ID: DbEJgKbTxd7
browser/components/downloads/test/browser/browser_indicatorDrop.js
browser/components/downloads/test/browser/browser_libraryDrop.js
browser/components/downloads/test/browser/head.js
toolkit/components/places/History.jsm
toolkit/components/places/nsPlacesExpiration.js
toolkit/components/places/tests/PlacesTestUtils.jsm
toolkit/components/places/tests/expiration/test_clearHistory.js
toolkit/components/places/tests/expiration/test_notifications.js
toolkit/components/places/tests/expiration/test_pref_interval.js
toolkit/components/places/tests/unit/test_history_clear.js
--- a/browser/components/downloads/test/browser/browser_indicatorDrop.js
+++ b/browser/components/downloads/test/browser/browser_indicatorDrop.js
@@ -3,17 +3,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
   "resource://testing-common/httpd.js");
 
 registerCleanupFunction(async function() {
   await task_resetState();
-  await task_clearHistory();
+  await PlacesUtils.history.clear();
 });
 
 add_task(async function test_indicatorDrop() {
   let downloadButton = document.getElementById("downloads-button");
   ok(downloadButton, "download button present");
 
   let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
       getService(Ci.mozIJSSubScriptLoader);
--- a/browser/components/downloads/test/browser/browser_libraryDrop.js
+++ b/browser/components/downloads/test/browser/browser_libraryDrop.js
@@ -3,17 +3,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 XPCOMUtils.defineLazyModuleGetter(this, "HttpServer",
   "resource://testing-common/httpd.js");
 
 registerCleanupFunction(async function() {
   await task_resetState();
-  await task_clearHistory();
+  await PlacesUtils.history.clear();
 });
 
 add_task(async function test_indicatorDrop() {
   let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
       getService(Ci.mozIJSSubScriptLoader);
   let EventUtils = {};
   scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
 
--- a/browser/components/downloads/test/browser/head.js
+++ b/browser/components/downloads/test/browser/head.js
@@ -158,26 +158,16 @@ function startServer() {
   });
 }
 
 function httpUrl(aFileName) {
   return "http://localhost:" + gHttpServer.identity.primaryPort + "/" +
     aFileName;
 }
 
-function task_clearHistory() {
-  return new Promise(function(resolve) {
-    Services.obs.addObserver(function observeCH(aSubject, aTopic, aData) {
-      Services.obs.removeObserver(observeCH, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
-      resolve();
-    }, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
-    PlacesUtils.history.clear();
-  });
-}
-
 function openLibrary(aLeftPaneRoot) {
   let library = window.openDialog("chrome://browser/content/places/places.xul",
                                   "", "chrome,toolbar=yes,dialog=no,resizable",
                                   aLeftPaneRoot);
 
   return new Promise(resolve => {
     waitForFocus(resolve, library);
   });
--- a/toolkit/components/places/History.jsm
+++ b/toolkit/components/places/History.jsm
@@ -745,38 +745,66 @@ var invalidateFrecencies = async functio
      SET hidden = 0
      WHERE id in (${ ids })
      AND frecency <> 0`
   );
 };
 
 // Inner implementation of History.clear().
 var clear = async function(db) {
-  // Remove all history.
-  await db.execute("DELETE FROM moz_historyvisits");
+  await db.executeTransaction(async function() {
+    // Remove all non-bookmarked places entries first, this will speed up the
+    // triggers work.
+    await db.execute(`DELETE FROM moz_places WHERE foreign_count = 0`);
+    await db.execute(`DELETE FROM moz_updatehosts_temp`);
+
+    // Expire orphan icons.
+    await db.executeCached(`DELETE FROM moz_pages_w_icons
+                            WHERE page_url_hash NOT IN (SELECT url_hash FROM moz_places)`);
+    await db.executeCached(`DELETE FROM moz_icons
+                            WHERE root = 0 AND id NOT IN (SELECT icon_id FROM moz_icons_to_pages)`);
+
+    // Expire annotations.
+    await db.execute(`DELETE FROM moz_items_annos WHERE expiration = :expire_session`,
+                     { expire_session: Ci.nsIAnnotationService.EXPIRE_SESSION });
+    await db.execute(`DELETE FROM moz_annos WHERE id in (
+                        SELECT a.id FROM moz_annos a
+                        LEFT JOIN moz_places h ON a.place_id = h.id
+                        WHERE h.id IS NULL
+                           OR expiration = :expire_session
+                           OR (expiration = :expire_with_history
+                               AND h.last_visit_date ISNULL)
+                      )`, { expire_session: Ci.nsIAnnotationService.EXPIRE_SESSION,
+                            expire_with_history: Ci.nsIAnnotationService.EXPIRE_WITH_HISTORY });
+
+    // Expire inputhistory.
+    await db.execute(`DELETE FROM moz_inputhistory WHERE place_id IN (
+                        SELECT i.place_id FROM moz_inputhistory i
+                        LEFT JOIN moz_places h ON h.id = i.place_id
+                        WHERE h.id IS NULL)`);
+
+    // Remove all history.
+    await db.execute("DELETE FROM moz_historyvisits");
+
+    // Invalidate frecencies for the remaining places.
+    await db.execute(`UPDATE moz_places SET frecency =
+                        (CASE
+                          WHEN url_hash BETWEEN hash("place", "prefix_lo") AND
+                                                hash("place", "prefix_hi")
+                          THEN 0
+                          ELSE -1
+                          END)
+                        WHERE frecency > 0`);
+  });
 
   // Clear the registered embed visits.
   PlacesUtils.history.clearEmbedVisits();
 
-  // Expiration will take care of orphans.
   let observers = PlacesUtils.history.getObservers();
   notify(observers, "onClearHistory");
-
-  // Invalidate frecencies for the remaining places. This must happen
-  // after the notification to ensure it runs enqueued to expiration.
-  await db.execute(
-    `UPDATE moz_places SET frecency =
-     (CASE
-      WHEN url_hash BETWEEN hash("place", "prefix_lo") AND
-                            hash("place", "prefix_hi")
-      THEN 0
-      ELSE -1
-      END)
-     WHERE frecency > 0`);
-
   // Notify frecency change observers.
   notify(observers, "onManyFrecenciesChanged");
 };
 
 /**
  * Clean up pages whose history has been modified, by either
  * removing them entirely (if they are marked for removal,
  * typically because all visits have been removed and there
--- a/toolkit/components/places/nsPlacesExpiration.js
+++ b/toolkit/components/places/nsPlacesExpiration.js
@@ -7,17 +7,16 @@
 /**
  * This component handles history and orphans expiration through asynchronous
  * Storage statements.
  * Expiration runs:
  * - At idle, but just once, we stop any other kind of expiration during idle
  *   to preserve batteries in portable devices.
  * - At shutdown, only if the database is dirty, we should still avoid to
  *   expire too heavily on shutdown.
- * - On ClearHistory we run a full expiration for privacy reasons.
  * - On a repeating timer we expire in small chunks.
  *
  * Expiration algorithm will adapt itself based on:
  * - Memory size of the device.
  * - Status of the database (clean or dirty).
  */
 
 const Cc = Components.classes;
@@ -104,21 +103,16 @@ const EXPIRE_AGGRESSIVITY_MULTIPLIER = 3
 // Used as a fall back value when it's not possible to calculate the real value.
 const URIENTRY_AVG_SIZE = 600;
 
 // Seconds of idle time before starting a larger expiration step.
 // Notice during idle we stop the expiration timer since we don't want to hurt
 // stand-by or mobile devices batteries.
 const IDLE_TIMEOUT_SECONDS = 5 * 60;
 
-// If a clear history ran just before we shutdown, we will skip most of the
-// expiration at shutdown.  This is maximum number of seconds from last
-// clearHistory to decide to skip expiration at shutdown.
-const SHUTDOWN_WITH_RECENT_CLEARHISTORY_TIMEOUT_SECONDS = 10;
-
 // If the number of pages over history limit is greater than this threshold,
 // expiration will be more aggressive, to bring back history to a saner size.
 const OVERLIMIT_PAGES_THRESHOLD = 1000;
 
 const MSECS_PER_DAY = 86400000;
 const ANNOS_EXPIRE_POLICIES = [
   { bind: "expire_days",
     type: Ci.nsIAnnotationService.EXPIRE_DAYS,
@@ -129,17 +123,17 @@ const ANNOS_EXPIRE_POLICIES = [
   { bind: "expire_months",
     type: Ci.nsIAnnotationService.EXPIRE_MONTHS,
     time: 180 * 1000 * MSECS_PER_DAY },
 ];
 
 // When we expire we can use these limits:
 // - SMALL for usual partial expirations, will expire a small chunk.
 // - LARGE for idle or shutdown expirations, will expire a large chunk.
-// - UNLIMITED for clearHistory, will expire everything.
+// - UNLIMITED will expire all the orphans.
 // - DEBUG will use a known limit, passed along with the debug notification.
 const LIMIT = {
   SMALL: 0,
   LARGE: 1,
   UNLIMITED: 2,
   DEBUG: 3,
 };
 
@@ -149,21 +143,20 @@ const STATUS = {
   DIRTY: 1,
   UNKNOWN: 2,
 };
 
 // Represents actions on which a query will run.
 const ACTION = {
   TIMED:           1 << 0, // happens every this._interval
   TIMED_OVERLIMIT: 1 << 1, // like TIMED but only when history is over limits
-  CLEAR_HISTORY:   1 << 2, // happens when history is cleared
-  SHUTDOWN_DIRTY:  1 << 3, // happens at shutdown for DIRTY state
-  IDLE_DIRTY:      1 << 4, // happens on idle for DIRTY state
-  IDLE_DAILY:      1 << 5, // happens once a day on idle
-  DEBUG:           1 << 6, // happens on TOPIC_DEBUG_START_EXPIRATION
+  SHUTDOWN_DIRTY:  1 << 2, // happens at shutdown for DIRTY state
+  IDLE_DIRTY:      1 << 3, // happens on idle for DIRTY state
+  IDLE_DAILY:      1 << 4, // happens once a day on idle
+  DEBUG:           1 << 5, // happens on TOPIC_DEBUG_START_EXPIRATION
 };
 
 // The queries we use to expire.
 const EXPIRATION_QUERIES = {
 
   // Some visits can be expired more often than others, cause they are less
   // useful to the user and can pollute awesomebar results:
   // 1. urls over 255 chars
@@ -235,161 +228,127 @@ const EXPIRATION_QUERIES = {
   QUERY_EXPIRE_URIS: {
     sql: `DELETE FROM moz_places WHERE id IN (
             SELECT p_id FROM expiration_notify WHERE p_id NOTNULL
           ) AND foreign_count = 0 AND last_visit_date ISNULL`,
     actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
              ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
-  // Expire orphan URIs from the database.
-  QUERY_SILENT_EXPIRE_ORPHAN_URIS: {
-    sql: `DELETE FROM moz_places WHERE id IN (
-            SELECT h.id
-            FROM moz_places h
-            LEFT JOIN moz_historyvisits v ON h.id = v.place_id
-            WHERE h.last_visit_date IS NULL
-              AND h.foreign_count = 0
-              AND v.id IS NULL
-            LIMIT :limit_uris
-          )`,
-    actions: ACTION.CLEAR_HISTORY
-  },
-
   // Hosts accumulated during the places delete are updated through a trigger
   // (see nsPlacesTriggers.h).
   QUERY_UPDATE_HOSTS: {
     sql: `DELETE FROM moz_updatehosts_temp`,
-    actions: ACTION.CLEAR_HISTORY | ACTION.TIMED | ACTION.TIMED_OVERLIMIT |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
+    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire orphan pages from the icons database.
   QUERY_EXPIRE_FAVICONS_PAGES: {
     sql: `DELETE FROM moz_pages_w_icons
           WHERE page_url_hash NOT IN (
             SELECT url_hash FROM moz_places
           )`,
-    actions: ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
+    actions: ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire orphan icons from the database.
   QUERY_EXPIRE_FAVICONS: {
     sql: `DELETE FROM moz_icons
           WHERE root = 0 AND id NOT IN (
             SELECT icon_id FROM moz_icons_to_pages
           )`,
-    actions: ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
+    actions: ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire orphan page annotations from the database.
   QUERY_EXPIRE_ANNOS: {
     sql: `DELETE FROM moz_annos WHERE id in (
             SELECT a.id FROM moz_annos a
             LEFT JOIN moz_places h ON a.place_id = h.id
             WHERE h.id IS NULL
             LIMIT :limit_annos
           )`,
-    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
+    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire page annotations based on expiration policy.
   QUERY_EXPIRE_ANNOS_WITH_POLICY: {
     sql: `DELETE FROM moz_annos
           WHERE (expiration = :expire_days
             AND :expire_days_time > MAX(lastModified, dateAdded))
              OR (expiration = :expire_weeks
             AND :expire_weeks_time > MAX(lastModified, dateAdded))
              OR (expiration = :expire_months
             AND :expire_months_time > MAX(lastModified, dateAdded))`,
-    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
+    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire items annotations based on expiration policy.
   QUERY_EXPIRE_ITEMS_ANNOS_WITH_POLICY: {
     sql: `DELETE FROM moz_items_annos
           WHERE (expiration = :expire_days
             AND :expire_days_time > MAX(lastModified, dateAdded))
              OR (expiration = :expire_weeks
             AND :expire_weeks_time > MAX(lastModified, dateAdded))
              OR (expiration = :expire_months
             AND :expire_months_time > MAX(lastModified, dateAdded))`,
-    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
+    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire page annotations based on expiration policy.
   QUERY_EXPIRE_ANNOS_WITH_HISTORY: {
     sql: `DELETE FROM moz_annos
           WHERE expiration = :expire_with_history
             AND NOT EXISTS (SELECT id FROM moz_historyvisits
                             WHERE place_id = moz_annos.place_id LIMIT 1)`,
-    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
+    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire item annos without a corresponding item id.
   QUERY_EXPIRE_ITEMS_ANNOS: {
     sql: `DELETE FROM moz_items_annos WHERE id IN (
             SELECT a.id FROM moz_items_annos a
             LEFT JOIN moz_bookmarks b ON a.item_id = b.id
             WHERE b.id IS NULL
             LIMIT :limit_annos
           )`,
-    actions: ACTION.CLEAR_HISTORY | ACTION.IDLE_DAILY | ACTION.DEBUG
+    actions: ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire all annotation names without a corresponding annotation.
   QUERY_EXPIRE_ANNO_ATTRIBUTES: {
     sql: `DELETE FROM moz_anno_attributes WHERE id IN (
             SELECT n.id FROM moz_anno_attributes n
             LEFT JOIN moz_annos a ON n.id = a.anno_attribute_id
             LEFT JOIN moz_items_annos t ON n.id = t.anno_attribute_id
             WHERE a.anno_attribute_id IS NULL
               AND t.anno_attribute_id IS NULL
             LIMIT :limit_annos
           )`,
-    actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY |
+    actions: ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY |
              ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Expire orphan inputhistory.
   QUERY_EXPIRE_INPUTHISTORY: {
     sql: `DELETE FROM moz_inputhistory WHERE place_id IN (
             SELECT i.place_id FROM moz_inputhistory i
             LEFT JOIN moz_places h ON h.id = i.place_id
             WHERE h.id IS NULL
             LIMIT :limit_inputhistory
           )`,
-    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
-             ACTION.SHUTDOWN_DIRTY | ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY |
-             ACTION.DEBUG
-  },
-
-  // Expire all session annotations.  Should only be called at shutdown.
-  QUERY_EXPIRE_ANNOS_SESSION: {
-    sql: "DELETE FROM moz_annos WHERE expiration = :expire_session",
-    actions: ACTION.CLEAR_HISTORY | ACTION.DEBUG
-  },
-
-  // Expire all session item annotations.  Should only be called at shutdown.
-  QUERY_EXPIRE_ITEMS_ANNOS_SESSION: {
-    sql: "DELETE FROM moz_items_annos WHERE expiration = :expire_session",
-    actions: ACTION.CLEAR_HISTORY | ACTION.DEBUG
+    actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN_DIRTY |
+             ACTION.IDLE_DIRTY | ACTION.IDLE_DAILY | ACTION.DEBUG
   },
 
   // Select entries for notifications.
   // If p_id is set whole_entry = 1, then we have expired the full page.
   // Either p_id or v_id are always set.
   QUERY_SELECT_NOTIFICATIONS: {
     sql: `SELECT url, guid, MAX(visit_date) AS visit_date,
                  MAX(IFNULL(MIN(p_id, 1), MIN(v_id, 0))) AS whole_entry,
@@ -492,22 +451,19 @@ nsPlacesExpiration.prototype = {
       this._shuttingDown = true;
       this.expireOnIdle = false;
 
       if (this._timer) {
         this._timer.cancel();
         this._timer = null;
       }
 
-      // If we didn't ran a clearHistory recently and database is dirty, we
-      // want to expire some entries, to speed up the expiration process.
-      let hasRecentClearHistory =
-        Date.now() - this._lastClearHistoryTime <
-          SHUTDOWN_WITH_RECENT_CLEARHISTORY_TIMEOUT_SECONDS * 1000;
-      if (!hasRecentClearHistory && this.status == STATUS.DIRTY) {
+      // If the database is dirty, we want to expire some entries, to speed up
+      // the expiration process.
+      if (this.status == STATUS.DIRTY) {
         this._expireWithActionAndLimit(ACTION.SHUTDOWN_DIRTY, LIMIT.LARGE);
       }
 
       this._finalizeInternalStatements();
     } else if (aTopic == TOPIC_PREF_CHANGED) {
       this._loadPrefsPromise = this._loadPrefs().then(() => {
         if (aData == PREF_INTERVAL_SECONDS) {
           // Renew the timer with the new interval value.
@@ -572,22 +528,19 @@ nsPlacesExpiration.prototype = {
   onEndUpdateBatch: function PEX_onEndUpdateBatch() {
     this._inBatchMode = false;
 
     // Restore timer.
     if (!this._timer)
       this._newTimer();
   },
 
-  _lastClearHistoryTime: 0,
   onClearHistory: function PEX_onClearHistory() {
-    this._lastClearHistoryTime = Date.now();
-    // Expire orphans.  History status is clean after a clear history.
+    // History status is clean after a clear history.
     this.status = STATUS.CLEAN;
-    this._expireWithActionAndLimit(ACTION.CLEAR_HISTORY, LIMIT.UNLIMITED);
   },
 
   onVisit() {},
   onTitleChanged() {},
   onDeleteURI() {},
   onPageChanged() {},
   onDeleteVisits() {},
 
@@ -977,19 +930,16 @@ nsPlacesExpiration.prototype = {
         // Avoid expiring all visits in case of an unlimited debug expiration,
         // just remove orphans instead.
         params.limit_visits =
           aLimit == LIMIT.DEBUG && baseLimit == -1 ? 0 : baseLimit;
         break;
       case "QUERY_FIND_URIS_TO_EXPIRE":
         params.limit_uris = baseLimit;
         break;
-      case "QUERY_SILENT_EXPIRE_ORPHAN_URIS":
-        params.limit_uris = baseLimit;
-        break;
       case "QUERY_EXPIRE_ANNOS":
         // Each page may have multiple annos.
         params.limit_annos = baseLimit * EXPIRE_AGGRESSIVITY_MULTIPLIER;
         break;
       case "QUERY_EXPIRE_ANNOS_WITH_POLICY":
       case "QUERY_EXPIRE_ITEMS_ANNOS_WITH_POLICY":
         let microNow = Date.now() * 1000;
         ANNOS_EXPIRE_POLICIES.forEach(function(policy) {
@@ -1004,20 +954,16 @@ nsPlacesExpiration.prototype = {
         params.limit_annos = baseLimit;
         break;
       case "QUERY_EXPIRE_ANNO_ATTRIBUTES":
         params.limit_annos = baseLimit;
         break;
       case "QUERY_EXPIRE_INPUTHISTORY":
         params.limit_inputhistory = baseLimit;
         break;
-      case "QUERY_EXPIRE_ANNOS_SESSION":
-      case "QUERY_EXPIRE_ITEMS_ANNOS_SESSION":
-        params.expire_session = Ci.nsIAnnotationService.EXPIRE_SESSION;
-        break;
     }
 
     return stmt;
   },
 
   /**
    * Creates a new timer based on this._interval.
    *
--- a/toolkit/components/places/tests/PlacesTestUtils.jsm
+++ b/toolkit/components/places/tests/PlacesTestUtils.jsm
@@ -123,26 +123,21 @@ this.PlacesTestUtils = Object.freeze({
   },
 
   /**
    * Clear all history.
    *
    * @return {Promise}
    * @resolves When history was cleared successfully.
    * @rejects JavaScript exception.
+   *
+   * @deprecated New consumers should directly use PlacesUtils.history.clear().
    */
   clearHistory() {
-    let expirationFinished = new Promise(resolve => {
-      Services.obs.addObserver(function observe(subj, topic, data) {
-        Services.obs.removeObserver(observe, topic);
-        resolve();
-      }, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
-    });
-
-    return Promise.all([expirationFinished, PlacesUtils.history.clear()]);
+    return PlacesUtils.history.clear();
   },
 
   /**
    * Waits for all pending async statements on the default connection.
    *
    * @return {Promise}
    * @resolves When all pending async statements finished.
    * @rejects Never.
--- a/toolkit/components/places/tests/expiration/test_clearHistory.js
+++ b/toolkit/components/places/tests/expiration/test_clearHistory.js
@@ -6,79 +6,18 @@
 
 /**
  * What this is aimed to test:
  *
  * History.clear() should expire everything but bookmarked pages and valid
  * annos.
  */
 
-var as = PlacesUtils.annotations;
-
-/**
- * Creates an aged annotation.
- *
- * @param aIdentifier Either a page url or an item id.
- * @param aIdentifier Name of the annotation.
- * @param aValue Value for the annotation.
- * @param aExpirePolicy Expiration policy of the annotation.
- * @param aAgeInDays Age in days of the annotation.
- * @param [optional] aLastModifiedAgeInDays Age in days of the annotation, for lastModified.
- */
-var now = Date.now();
-function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy,
-                      aAgeInDays, aLastModifiedAgeInDays) {
-  let expireDate = (now - (aAgeInDays * 86400 * 1000)) * 1000;
-  let lastModifiedDate = 0;
-  if (aLastModifiedAgeInDays)
-    lastModifiedDate = (now - (aLastModifiedAgeInDays * 86400 * 1000)) * 1000;
-
-  let sql;
-  if (typeof(aIdentifier) == "number") {
-    // Item annotation.
-    as.setItemAnnotation(aIdentifier, aName, aValue, 0, aExpirePolicy);
-    // Update dateAdded for the last added annotation.
-    sql = "UPDATE moz_items_annos SET dateAdded = :expire_date, lastModified = :last_modified " +
-          "WHERE id = ( " +
-            "SELECT a.id FROM moz_items_annos a " +
-            "JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id " +
-            "WHERE a.item_id = :id " +
-              "AND n.name = :anno_name " +
-            "ORDER BY a.dateAdded DESC LIMIT 1 " +
-          ")";
-  } else if (aIdentifier instanceof Ci.nsIURI) {
-    // Page annotation.
-    as.setPageAnnotation(aIdentifier, aName, aValue, 0, aExpirePolicy);
-    // Update dateAdded for the last added annotation.
-    sql = "UPDATE moz_annos SET dateAdded = :expire_date, lastModified = :last_modified " +
-          "WHERE id = ( " +
-            "SELECT a.id FROM moz_annos a " +
-            "JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id " +
-            "JOIN moz_places h on h.id = a.place_id " +
-            "WHERE h.url_hash = hash(:id) AND h.url = :id " +
-            "AND n.name = :anno_name " +
-            "ORDER BY a.dateAdded DESC LIMIT 1 " +
-          ")";
-  } else
-    do_throw("Wrong identifier type");
-
-  let stmt = DBConn().createStatement(sql);
-  stmt.params.id = (typeof(aIdentifier) == "number") ? aIdentifier
-                                                     : aIdentifier.spec;
-  stmt.params.expire_date = expireDate;
-  stmt.params.last_modified = lastModifiedDate;
-  stmt.params.anno_name = aName;
-  try {
-    stmt.executeStep();
-  } finally {
-    stmt.finalize();
-  }
-}
-
 add_task(async function test_historyClear() {
+  let as = PlacesUtils.annotations;
   // Set interval to a large value so we don't expire on it.
   setInterval(3600); // 1h
 
   // Expire all expirable pages.
   setMaxPages(0);
 
   // Add some bookmarked page with visit and annotations.
   for (let i = 0; i < 5; i++) {
@@ -94,48 +33,38 @@ add_task(async function test_historyClea
     // Will persist because it's an EXPIRE_NEVER item anno.
     as.setItemAnnotation(id, "persist", "test", 0, as.EXPIRE_NEVER);
     // Will persist because the page is bookmarked.
     as.setPageAnnotation(pageURI, "persist", "test", 0, as.EXPIRE_NEVER);
     // All EXPIRE_SESSION annotations are expected to expire on clear history.
     as.setItemAnnotation(id, "expire_session", "test", 0, as.EXPIRE_SESSION);
     as.setPageAnnotation(pageURI, "expire_session", "test", 0, as.EXPIRE_SESSION);
     // Annotations with timed policy will expire regardless bookmarked status.
-    add_old_anno(id, "expire_days", "test", as.EXPIRE_DAYS, 8);
-    add_old_anno(id, "expire_weeks", "test", as.EXPIRE_WEEKS, 31);
-    add_old_anno(id, "expire_months", "test", as.EXPIRE_MONTHS, 181);
-    add_old_anno(pageURI, "expire_days", "test", as.EXPIRE_DAYS, 8);
-    add_old_anno(pageURI, "expire_weeks", "test", as.EXPIRE_WEEKS, 31);
-    add_old_anno(pageURI, "expire_months", "test", as.EXPIRE_MONTHS, 181);
   }
 
   // Add some visited page and annotations for each.
   for (let i = 0; i < 5; i++) {
     // All page annotations related to these expired pages are expected to
     // expire as well.
     let pageURI = uri("http://page_anno." + i + ".mozilla.org/");
     await PlacesTestUtils.addVisits({ uri: pageURI });
     as.setPageAnnotation(pageURI, "expire", "test", 0, as.EXPIRE_NEVER);
     as.setPageAnnotation(pageURI, "expire_session", "test", 0, as.EXPIRE_SESSION);
-    add_old_anno(pageURI, "expire_days", "test", as.EXPIRE_DAYS, 8);
-    add_old_anno(pageURI, "expire_weeks", "test", as.EXPIRE_WEEKS, 31);
-    add_old_anno(pageURI, "expire_months", "test", as.EXPIRE_MONTHS, 181);
   }
 
   // Expire all visits for the bookmarks
   await PlacesTestUtils.clearHistory();
 
-  ["expire_days", "expire_weeks", "expire_months", "expire_session",
+  ["expire_session",
    "expire"].forEach(function(aAnno) {
     let pages = as.getPagesWithAnnotation(aAnno);
     do_check_eq(pages.length, 0);
   });
 
-  ["expire_days", "expire_weeks", "expire_months", "expire_session",
-   "expire"].forEach(function(aAnno) {
+  ["expire_session", "expire"].forEach(function(aAnno) {
     let items = as.getItemsWithAnnotation(aAnno);
     do_check_eq(items.length, 0);
   });
 
   let pages = as.getPagesWithAnnotation("persist");
   do_check_eq(pages.length, 5);
 
   let items = as.getItemsWithAnnotation("persist");
--- a/toolkit/components/places/tests/expiration/test_notifications.js
+++ b/toolkit/components/places/tests/expiration/test_notifications.js
@@ -20,17 +20,17 @@ var gObserver = {
   }
 };
 os.addObserver(gObserver, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
 
 function run_test() {
   // Set interval to a large value so we don't expire on it.
   setInterval(3600); // 1h
 
-  PlacesTestUtils.clearHistory();
+  promiseForceExpirationStep(1);
 
   do_timeout(2000, check_result);
   do_test_pending();
 }
 
 function check_result() {
   os.removeObserver(gObserver, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
   do_check_eq(gObserver.notifications, 1);
--- a/toolkit/components/places/tests/expiration/test_pref_interval.js
+++ b/toolkit/components/places/tests/expiration/test_pref_interval.js
@@ -12,50 +12,47 @@
 // PREF_INTERVAL_SECONDS_NOTSET in nsPlacesExpiration.
 const DEFAULT_TIMER_DELAY_SECONDS = 3 * 60;
 
 // Sync this with the const value in the component.
 const EXPIRE_AGGRESSIVITY_MULTIPLIER = 3;
 
 var tests = [
 
-  // This test should be the first, so the interval won't be influenced by
-  // status of history.
   { desc: "Set interval to 1s.",
     interval: 1,
-    expectedTimerDelay: 1
+    expectedTimerDelay: 1 * EXPIRE_AGGRESSIVITY_MULTIPLIER
   },
 
   { desc: "Set interval to a negative value.",
     interval: -1,
-    expectedTimerDelay: DEFAULT_TIMER_DELAY_SECONDS
+    expectedTimerDelay: DEFAULT_TIMER_DELAY_SECONDS * EXPIRE_AGGRESSIVITY_MULTIPLIER
   },
 
   { desc: "Set interval to 0.",
     interval: 0,
-    expectedTimerDelay: DEFAULT_TIMER_DELAY_SECONDS
+    expectedTimerDelay: DEFAULT_TIMER_DELAY_SECONDS * EXPIRE_AGGRESSIVITY_MULTIPLIER
   },
 
   { desc: "Set interval to a large value.",
     interval: 100,
-    expectedTimerDelay: 100
+    expectedTimerDelay: 100 * EXPIRE_AGGRESSIVITY_MULTIPLIER
   },
 
 ];
 
 add_task(async function test() {
   // The pref should not exist by default.
   Assert.throws(() => getInterval());
 
   // Force the component, so it will start observing preferences.
   force_expiration_start();
 
   for (let currentTest of tests) {
+    currentTest = tests.shift();
     print(currentTest.desc);
     let promise = promiseTopicObserved("test-interval-changed");
     setInterval(currentTest.interval);
     let [, data] = await promise;
-    Assert.equal(data, currentTest.expectedTimerDelay * EXPIRE_AGGRESSIVITY_MULTIPLIER);
+    Assert.equal(data, currentTest.expectedTimerDelay);
   }
-
   clearInterval();
 });
-
--- a/toolkit/components/places/tests/unit/test_history_clear.js
+++ b/toolkit/components/places/tests/unit/test_history_clear.js
@@ -1,41 +1,16 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 var mDBConn = DBConn();
 
-function promiseOnClearHistoryObserved() {
-  return new Promise(resolve => {
-
-    let historyObserver = {
-      onBeginUpdateBatch() {},
-      onEndUpdateBatch() {},
-      onVisit() {},
-      onTitleChanged() {},
-      onDeleteURI(aURI) {},
-      onPageChanged() {},
-      onDeleteVisits() {},
-
-      onClearHistory() {
-        PlacesUtils.history.removeObserver(this, false);
-        resolve();
-      },
-
-      QueryInterface: XPCOMUtils.generateQI([
-        Ci.nsINavHistoryObserver,
-      ])
-    }
-    PlacesUtils.history.addObserver(historyObserver);
-  });
-}
-
 add_task(async function test_history_clear() {
   await PlacesTestUtils.addVisits([
     { uri: uri("http://typed.mozilla.org/"),
       transition: TRANSITION_TYPED },
     { uri: uri("http://link.mozilla.org/"),
       transition: TRANSITION_LINK },
     { uri: uri("http://download.mozilla.org/"),
       transition: TRANSITION_DOWNLOAD },
@@ -73,24 +48,24 @@ add_task(async function test_history_cle
     { uri: uri("http://typed.mozilla.org/"),
       transition: TRANSITION_BOOKMARK },
     { uri: uri("http://frecency.mozilla.org/"),
       transition: TRANSITION_LINK },
   ]);
   await PlacesTestUtils.promiseAsyncUpdates();
 
   // Clear history and wait for the onClearHistory notification.
-  let promiseWaitClearHistory = promiseOnClearHistoryObserved();
+  let promiseClearHistory =
+    PlacesTestUtils.waitForNotification("onClearHistory", () => true, "history");
   PlacesUtils.history.clear();
-  await promiseWaitClearHistory;
+  await promiseClearHistory;
 
   // check browserHistory returns no entries
   do_check_eq(0, PlacesUtils.history.hasHistoryEntries);
 
-  await promiseTopicObserved(PlacesUtils.TOPIC_EXPIRATION_FINISHED);
   await PlacesTestUtils.promiseAsyncUpdates();
 
   // Check that frecency for not cleared items (bookmarks) has been converted
   // to -1.
   let stmt = mDBConn.createStatement(
     "SELECT h.id FROM moz_places h WHERE h.frecency > 0 ");
   do_check_false(stmt.executeStep());
   stmt.finalize();