Backed out 2 changesets (bug 911307) for frequent timeouts in browser_newtab_perwindow_private_browsing.js
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 29 Mar 2014 12:13:11 -0700
changeset 194593 0e19655e93df46ca1b69ecd31f8a50147d366c98
parent 194592 95130f72756e4ae9465e578b3518afb66a23084a
child 194597 c18345da71b97122ee912daf5a15910f20561ed7
child 194622 8b031a695888ecaa807e7de26e651986d2e5ee1d
child 194641 aab401903b48ca1739ebaab08a67032be5068d46
push idunknown
push userunknown
push dateunknown
bugs911307
milestone31.0a1
backs out70638b7c97f1136a9b7c5f6abe9225ee5f65ace6
3951f7e82b4ca65b88016620ee6ebbd3fc5da6d7
Backed out 2 changesets (bug 911307) for frequent timeouts in browser_newtab_perwindow_private_browsing.js Backed out changeset 70638b7c97f1 (bug 911307) Backed out changeset 3951f7e82b4c (bug 911307)
browser/base/content/newtab/page.js
browser/base/content/test/newtab/browser.ini
browser/base/content/test/newtab/browser_newtab_update.js
browser/base/content/test/newtab/head.js
toolkit/components/downloads/nsDownloadManager.cpp
toolkit/components/places/Database.cpp
toolkit/components/places/History.cpp
toolkit/components/places/SQLFunctions.cpp
toolkit/components/places/SQLFunctions.h
toolkit/components/places/nsINavHistoryService.idl
toolkit/components/places/nsNavBookmarks.cpp
toolkit/components/places/nsNavHistory.cpp
toolkit/components/places/nsNavHistory.h
toolkit/components/places/nsNavHistoryResult.cpp
toolkit/components/places/nsNavHistoryResult.h
toolkit/components/places/tests/unit/test_frecency_observers.js
toolkit/components/places/tests/unit/xpcshell.ini
toolkit/modules/BinarySearch.jsm
toolkit/modules/NewTabUtils.jsm
toolkit/modules/moz.build
toolkit/modules/tests/xpcshell/test_BinarySearch.js
toolkit/modules/tests/xpcshell/test_NewTabUtils.js
toolkit/modules/tests/xpcshell/xpcshell.ini
--- a/browser/base/content/newtab/page.js
+++ b/browser/base/content/newtab/page.js
@@ -60,23 +60,20 @@ let gPage = {
           site.refreshThumbnail();
         }
       }
     }
   },
 
   /**
    * Updates the whole page and the grid when the storage has changed.
-   * @param aOnlyIfHidden If true, the page is updated only if it's hidden in
-   *                      the preloader.
    */
-  update: function Page_update(aOnlyIfHidden=false) {
-    let skipUpdate = aOnlyIfHidden && this.allowBackgroundCaptures;
+  update: function Page_update() {
     // The grid might not be ready yet as we initialize it asynchronously.
-    if (gGrid.ready && !skipUpdate) {
+    if (gGrid.ready) {
       gGrid.refresh();
     }
   },
 
   /**
    * Internally initializes the page. This runs only when/if the feature
    * is/gets enabled.
    */
--- a/browser/base/content/test/newtab/browser.ini
+++ b/browser/base/content/test/newtab/browser.ini
@@ -19,9 +19,8 @@ skip-if = os == "mac" # Intermittent fai
 [browser_newtab_drag_drop_ext.js]
 [browser_newtab_drop_preview.js]
 [browser_newtab_focus.js]
 [browser_newtab_perwindow_private_browsing.js]
 [browser_newtab_reset.js]
 [browser_newtab_tabsync.js]
 [browser_newtab_undo.js]
 [browser_newtab_unpin.js]
-[browser_newtab_update.js]
deleted file mode 100644
--- a/browser/base/content/test/newtab/browser_newtab_update.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-/**
- * Checks that newtab is updated as its links change.
- */
-
-function runTests() {
-  if (NewTabUtils.allPages.updateScheduledForHiddenPages) {
-    // Wait for dynamic updates triggered by the previous test to finish.
-    yield whenPagesUpdated(null, true);
-  }
-
-  // First, start with an empty page.  setLinks will trigger a hidden page
-  // update because it calls clearHistory.  We need to wait for that update to
-  // happen so that the next time we wait for a page update below, we catch the
-  // right update and not the one triggered by setLinks.
-  //
-  // Why this weird way of yielding?  First, these two functions don't return
-  // promises, they call TestRunner.next when done.  Second, the point at which
-  // setLinks is done is independent of when the page update will happen, so
-  // calling whenPagesUpdated cannot wait until that time.
-  setLinks([]);
-  whenPagesUpdated(null, true);
-  yield null;
-  yield null;
-
-  // Strategy: Add some visits, open a new page, check the grid, repeat.
-  fillHistory([link(1)]);
-  yield whenPagesUpdated(null, true);
-  yield addNewTabPageTab();
-  checkGrid("1,,,,,,,,");
-
-  fillHistory([link(2)]);
-  yield whenPagesUpdated(null, true);
-  yield addNewTabPageTab();
-  checkGrid("2,1,,,,,,,");
-
-  fillHistory([link(1)]);
-  yield whenPagesUpdated(null, true);
-  yield addNewTabPageTab();
-  checkGrid("1,2,,,,,,,");
-
-  fillHistory([link(2), link(3), link(4)]);
-  yield whenPagesUpdated(null, true);
-  yield addNewTabPageTab();
-  checkGrid("2,1,3,4,,,,,");
-}
-
-function link(id) {
-  return { url: "http://example.com/#" + id, title: "site#" + id };
-}
--- a/browser/base/content/test/newtab/head.js
+++ b/browser/base/content/test/newtab/head.js
@@ -154,44 +154,30 @@ function clearHistory(aCallback) {
     executeSoon(aCallback);
   }, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
 
   PlacesUtils.history.removeAllPages();
 }
 
 function fillHistory(aLinks, aCallback) {
   let numLinks = aLinks.length;
-  if (!numLinks) {
-    if (aCallback)
-      executeSoon(aCallback);
-    return;
-  }
-
   let transitionLink = Ci.nsINavHistoryService.TRANSITION_LINK;
 
-  // Important: To avoid test failures due to clock jitter on Windows XP, call
-  // Date.now() once here, not each time through the loop.
-  let now = Date.now() * 1000;
-
-  for (let i = 0; i < aLinks.length; i++) {
-    let link = aLinks[i];
+  for (let link of aLinks.reverse()) {
     let place = {
       uri: makeURI(link.url),
       title: link.title,
-      // Links are secondarily sorted by visit date descending, so decrease the
-      // visit date as we progress through the array so that links appear in the
-      // grid in the order they're present in the array.
-      visits: [{visitDate: now - i, transitionType: transitionLink}]
+      visits: [{visitDate: Date.now() * 1000, transitionType: transitionLink}]
     };
 
     PlacesUtils.asyncHistory.updatePlaces(place, {
       handleError: function () ok(false, "couldn't add visit to history"),
       handleResult: function () {},
       handleCompletion: function () {
-        if (--numLinks == 0 && aCallback)
+        if (--numLinks == 0)
           aCallback();
       }
     });
   }
 }
 
 /**
  * Allows to specify the list of pinned links (that have a fixed position in
@@ -512,28 +498,22 @@ function createDragEvent(aEventType, aDa
   event.initDragEvent(aEventType, true, true, getContentWindow(), 0, 0, 0, 0, 0,
                       false, false, false, false, 0, null, dataTransfer);
 
   return event;
 }
 
 /**
  * Resumes testing when all pages have been updated.
- * @param aCallback Called when done. If not specified, TestRunner.next is used.
- * @param aOnlyIfHidden If true, this resumes testing only when an update that
- *                      applies to pre-loaded, hidden pages is observed.  If
- *                      false, this resumes testing when any update is observed.
  */
-function whenPagesUpdated(aCallback, aOnlyIfHidden=false) {
+function whenPagesUpdated(aCallback) {
   let page = {
-    update: function (onlyIfHidden=false) {
-      if (onlyIfHidden == aOnlyIfHidden) {
-        NewTabUtils.allPages.unregister(this);
-        executeSoon(aCallback || TestRunner.next);
-      }
+    update: function () {
+      NewTabUtils.allPages.unregister(this);
+      executeSoon(aCallback || TestRunner.next);
     }
   };
 
   NewTabUtils.allPages.register(page);
   registerCleanupFunction(function () {
     NewTabUtils.allPages.unregister(page);
   });
 }
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -2334,32 +2334,16 @@ NS_IMETHODIMP
 nsDownloadManager::OnTitleChanged(nsIURI *aURI,
                                   const nsAString &aPageTitle,
                                   const nsACString &aGUID)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDownloadManager::OnFrecencyChanged(nsIURI* aURI,
-                                     int32_t aNewFrecency,
-                                     const nsACString& aGUID,
-                                     bool aHidden,
-                                     PRTime aLastVisitDate)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDownloadManager::OnManyFrecenciesChanged()
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsDownloadManager::OnDeleteURI(nsIURI *aURI,
                                const nsACString& aGUID,
                                uint16_t aReason)
 {
   // This method in not normally invoked when mUseJSTransfer is enabled, however
   // we provide an extra check in case it is called manually by add-ons.
   NS_ENSURE_STATE(!mUseJSTransfer);
 
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -936,18 +936,16 @@ Database::InitFunctions()
   rv = MatchAutoCompleteFunction::create(mMainConn);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = CalculateFrecencyFunction::create(mMainConn);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = GenerateGUIDFunction::create(mMainConn);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = FixupURLFunction::create(mMainConn);
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = FrecencyNotificationFunction::create(mMainConn);
-  NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
 Database::InitTempTriggers()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -1180,32 +1180,27 @@ private:
     MOZ_ASSERT(aPlace.shouldUpdateFrecency);
 
     nsresult rv;
     { // First, set our frecency to the proper value.
       nsCOMPtr<mozIStorageStatement> stmt;
       if (aPlace.placeId) {
         stmt = mHistory->GetStatement(
           "UPDATE moz_places "
-          "SET frecency = NOTIFY_FRECENCY("
-            "CALCULATE_FRECENCY(:page_id), "
-            "url, guid, hidden, last_visit_date"
-          ") "
+          "SET frecency = CALCULATE_FRECENCY(:page_id) "
           "WHERE id = :page_id"
         );
         NS_ENSURE_STATE(stmt);
         rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), aPlace.placeId);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       else {
         stmt = mHistory->GetStatement(
           "UPDATE moz_places "
-          "SET frecency = NOTIFY_FRECENCY("
-            "CALCULATE_FRECENCY(id), url, guid, hidden, last_visit_date"
-          ") "
+          "SET frecency = CALCULATE_FRECENCY(id) "
           "WHERE url = :page_url"
         );
         NS_ENSURE_STATE(stmt);
         rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aPlace.spec);
         NS_ENSURE_SUCCESS(rv, rv);
       }
       mozStorageStatementScoper scoper(stmt);
 
@@ -2037,24 +2032,23 @@ History::InsertPlace(const VisitData& aP
   NS_ENSURE_STATE(stmt);
   mozStorageStatementScoper scoper(stmt);
 
   nsresult rv = stmt->BindStringByName(NS_LITERAL_CSTRING("rev_host"),
                                        aPlace.revHost);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("url"), aPlace.spec);
   NS_ENSURE_SUCCESS(rv, rv);
-  nsString title = aPlace.title;
   // Empty strings should have no title, just like nsNavHistory::SetPageTitle.
-  if (title.IsEmpty()) {
+  if (aPlace.title.IsEmpty()) {
     rv = stmt->BindNullByName(NS_LITERAL_CSTRING("title"));
   }
   else {
-    title.Assign(StringHead(aPlace.title, TITLE_LENGTH_MAX));
-    rv = stmt->BindStringByName(NS_LITERAL_CSTRING("title"), title);
+    rv = stmt->BindStringByName(NS_LITERAL_CSTRING("title"),
+                                StringHead(aPlace.title, TITLE_LENGTH_MAX));
   }
   NS_ENSURE_SUCCESS(rv, rv);
   rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("typed"), aPlace.typed);
   NS_ENSURE_SUCCESS(rv, rv);
   // When inserting a page for a first visit that should not appear in
   // autocomplete, for example an error page, use a zero frecency.
   int32_t frecency = aPlace.shouldUpdateFrecency ? aPlace.frecency : 0;
   rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("frecency"), frecency);
@@ -2066,23 +2060,16 @@ History::InsertPlace(const VisitData& aP
     rv = GenerateGUID(guid);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("guid"), guid);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = stmt->Execute();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Post an onFrecencyChanged observer notification.
-  const nsNavHistory* navHistory = nsNavHistory::GetConstHistoryService();
-  NS_ENSURE_STATE(navHistory);
-  navHistory->DispatchFrecencyChangedNotification(aPlace.spec, frecency, guid,
-                                                  aPlace.hidden,
-                                                  aPlace.visitTime);
-
   return NS_OK;
 }
 
 nsresult
 History::UpdatePlace(const VisitData& aPlace)
 {
   NS_PRECONDITION(!NS_IsMainThread(), "must be called off of the main thread!");
   NS_PRECONDITION(aPlace.placeId > 0, "must have a valid place id!");
--- a/toolkit/components/places/SQLFunctions.cpp
+++ b/toolkit/components/places/SQLFunctions.cpp
@@ -744,68 +744,10 @@ namespace places {
       src.Cut(0, 4);
     }
 
     result->SetAsAString(src);
     NS_ADDREF(*_result = result);
     return NS_OK;
   }
 
-////////////////////////////////////////////////////////////////////////////////
-//// Frecency Changed Notification Function
-
-  /* static */
-  nsresult
-  FrecencyNotificationFunction::create(mozIStorageConnection *aDBConn)
-  {
-    nsRefPtr<FrecencyNotificationFunction> function =
-      new FrecencyNotificationFunction();
-    nsresult rv = aDBConn->CreateFunction(
-      NS_LITERAL_CSTRING("notify_frecency"), 5, function
-    );
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return NS_OK;
-  }
-
-  NS_IMPL_ISUPPORTS1(
-    FrecencyNotificationFunction,
-    mozIStorageFunction
-  )
-
-  NS_IMETHODIMP
-  FrecencyNotificationFunction::OnFunctionCall(mozIStorageValueArray *aArgs,
-                                               nsIVariant **_result)
-  {
-    uint32_t numArgs;
-    nsresult rv = aArgs->GetNumEntries(&numArgs);
-    NS_ENSURE_SUCCESS(rv, rv);
-    MOZ_ASSERT(numArgs == 5);
-
-    int32_t newFrecency = aArgs->AsInt32(0);
-
-    nsAutoCString spec;
-    rv = aArgs->GetUTF8String(1, spec);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsAutoCString guid;
-    rv = aArgs->GetUTF8String(2, guid);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    bool hidden = static_cast<bool>(aArgs->AsInt32(3));
-    PRTime lastVisitDate = static_cast<PRTime>(aArgs->AsInt64(4));
-
-    const nsNavHistory* navHistory = nsNavHistory::GetConstHistoryService();
-    NS_ENSURE_STATE(navHistory);
-    navHistory->DispatchFrecencyChangedNotification(spec, newFrecency, guid,
-                                                    hidden, lastVisitDate);
-
-    nsCOMPtr<nsIWritableVariant> result =
-      do_CreateInstance("@mozilla.org/variant;1");
-    NS_ENSURE_STATE(result);
-    rv = result->SetAsInt32(newFrecency);
-    NS_ENSURE_SUCCESS(rv, rv);
-    NS_ADDREF(*_result = result);
-    return NS_OK;
-  }
-
 } // namespace places
 } // namespace mozilla
--- a/toolkit/components/places/SQLFunctions.h
+++ b/toolkit/components/places/SQLFunctions.h
@@ -275,49 +275,12 @@ public:
    * Registers the function with the specified database connection.
    *
    * @param aDBConn
    *        The database connection to register with.
    */
   static nsresult create(mozIStorageConnection *aDBConn);
 };
 
-
-////////////////////////////////////////////////////////////////////////////////
-//// Frecency Changed Notification Function
-
-/**
- * For a given place, posts a runnable to the main thread that calls
- * onFrecencyChanged on nsNavHistory's nsINavHistoryObservers.  The passed-in
- * newFrecency value is returned unchanged.
- *
- * @param newFrecency
- *        The place's new frecency.
- * @param url
- *        The place's URL.
- * @param guid
- *        The place's GUID.
- * @param hidden
- *        The place's hidden boolean.
- * @param lastVisitDate
- *        The place's last visit date.
- * @return newFrecency
- */
-class FrecencyNotificationFunction MOZ_FINAL : public mozIStorageFunction
-{
-public:
-  NS_DECL_THREADSAFE_ISUPPORTS
-  NS_DECL_MOZISTORAGEFUNCTION
-
-  /**
-   * Registers the function with the specified database connection.
-   *
-   * @param aDBConn
-   *        The database connection to register with.
-   */
-  static nsresult create(mozIStorageConnection *aDBConn);
-};
-
-
 } // namespace places
 } // namespace storage
 
 #endif // mozilla_places_SQLFunctions_h_
--- a/toolkit/components/places/nsINavHistoryService.idl
+++ b/toolkit/components/places/nsINavHistoryService.idl
@@ -18,17 +18,17 @@ interface nsIFile;
 
 interface nsINavHistoryContainerResultNode;
 interface nsINavHistoryQueryResultNode;
 interface nsINavHistoryQuery;
 interface nsINavHistoryQueryOptions;
 interface nsINavHistoryResult;
 interface nsINavHistoryBatchCallback;
 
-[scriptable, uuid(7daefb58-6989-4d22-a471-54f0b19b778a)]
+[scriptable, uuid(91d104bb-17ef-404b-9f9a-d9ed8de6824c)]
 interface nsINavHistoryResultNode : nsISupports
 {
   /**
    * Indentifies the parent result node in the result set. This is null for
    * top level nodes.
    */
   readonly attribute nsINavHistoryContainerResultNode parent;
 
@@ -605,17 +605,17 @@ interface nsINavHistoryResult : nsISuppo
 
 /**
  * Similar to nsIRDFObserver for history. Note that we don't pass the data
  * source since that is always the global history.
  *
  * DANGER! If you are in the middle of a batch transaction, there may be a
  * database transaction active. You can still access the DB, but be careful.
  */
-[scriptable, uuid(0f0f45b0-13a1-44ae-a0ab-c6046ec6d4da)]
+[scriptable, uuid(45e2970b-9b00-4473-9938-39d6beaf4248)]
 interface nsINavHistoryObserver : nsISupports
 {
   /**
    * Notifies you that a bunch of things are about to change, don't do any
    * heavy-duty processing until onEndUpdateBatch is called.
    */
   void onBeginUpdateBatch();
 
@@ -671,47 +671,16 @@ interface nsINavHistoryObserver : nsISup
    * @param aGUID
    *        The unique ID associated with the page.
    */
   void onTitleChanged(in nsIURI aURI,
                       in AString aPageTitle,
                       in ACString aGUID);
 
   /**
-   * Called when an individual page's frecency has changed.
-   *
-   * This is not called for pages whose frecencies change as the result of some
-   * large operation where some large or unknown number of frecencies change at
-   * once.  Use onManyFrecenciesChanged to detect such changes.
-   *
-   * @param aURI
-   *        The page's URI.
-   * @param aNewFrecency
-   *        The page's new frecency.
-   * @param aGUID
-   *        The page's GUID.
-   * @param aHidden
-   *        True if the page is marked as hidden.
-   * @param aVisitDate
-   *        The page's last visit date.
-   */
-  void onFrecencyChanged(in nsIURI aURI,
-                         in long aNewFrecency,
-                         in ACString aGUID,
-                         in boolean aHidden,
-                         in PRTime aVisitDate);
-
-  /**
-   * Called when the frecencies of many pages have changed at once.
-   *
-   * onFrecencyChanged is not called for each of those pages.
-   */
-  void onManyFrecenciesChanged();
-
-  /**
    * Removed by the user.
    */
   const unsigned short REASON_DELETED = 0;
   /**
    * Removed by automatic expiration.
    */
   const unsigned short REASON_EXPIRED = 1;
 
--- a/toolkit/components/places/nsNavBookmarks.cpp
+++ b/toolkit/components/places/nsNavBookmarks.cpp
@@ -2837,34 +2837,16 @@ nsNavBookmarks::OnTitleChanged(nsIURI* a
 {
   // NOOP. We don't consume page titles from moz_places anymore.
   // Title-change notifications are sent from SetItemTitle.
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
-nsNavBookmarks::OnFrecencyChanged(nsIURI* aURI,
-                                  int32_t aNewFrecency,
-                                  const nsACString& aGUID,
-                                  bool aHidden,
-                                  PRTime aLastVisitDate)
-{
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsNavBookmarks::OnManyFrecenciesChanged()
-{
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
 nsNavBookmarks::OnPageChanged(nsIURI* aURI,
                               uint32_t aChangedAttribute,
                               const nsAString& aNewValue,
                               const nsACString& aGUID)
 {
   nsresult rv;
   if (aChangedAttribute == nsINavHistoryObserver::ATTRIBUTE_FAVICON) {
     ItemChangeData changeData;
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -530,92 +530,16 @@ nsNavHistory::NotifyTitleChange(nsIURI* 
                                 const nsString& aTitle,
                                 const nsACString& aGUID)
 {
   MOZ_ASSERT(!aGUID.IsEmpty());
   NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
                    nsINavHistoryObserver, OnTitleChanged(aURI, aTitle, aGUID));
 }
 
-void
-nsNavHistory::NotifyFrecencyChanged(nsIURI* aURI,
-                                    int32_t aNewFrecency,
-                                    const nsACString& aGUID,
-                                    bool aHidden,
-                                    PRTime aLastVisitDate)
-{
-  MOZ_ASSERT(!aGUID.IsEmpty());
-  NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
-                   nsINavHistoryObserver,
-                   OnFrecencyChanged(aURI, aNewFrecency, aGUID, aHidden,
-                                     aLastVisitDate));
-}
-
-void
-nsNavHistory::NotifyManyFrecenciesChanged()
-{
-  NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
-                   nsINavHistoryObserver,
-                   OnManyFrecenciesChanged());
-}
-
-namespace {
-
-class FrecencyNotification : public nsRunnable
-{
-public:
-  FrecencyNotification(const nsACString& aSpec,
-                       int32_t aNewFrecency,
-                       const nsACString& aGUID,
-                       bool aHidden,
-                       PRTime aLastVisitDate)
-    : mSpec(aSpec)
-    , mNewFrecency(aNewFrecency)
-    , mGUID(aGUID)
-    , mHidden(aHidden)
-    , mLastVisitDate(aLastVisitDate)
-  {
-  }
-
-  NS_IMETHOD Run()
-  {
-    MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread");
-    nsNavHistory* navHistory = nsNavHistory::GetHistoryService();
-    if (navHistory) {
-      nsCOMPtr<nsIURI> uri;
-      (void)NS_NewURI(getter_AddRefs(uri), mSpec);
-      navHistory->NotifyFrecencyChanged(uri, mNewFrecency, mGUID, mHidden,
-                                        mLastVisitDate);
-    }
-    return NS_OK;
-  }
-
-private:
-  nsCString mSpec;
-  int32_t mNewFrecency;
-  nsCString mGUID;
-  bool mHidden;
-  PRTime mLastVisitDate;
-};
-
-} // anonymous namespace
-
-void
-nsNavHistory::DispatchFrecencyChangedNotification(const nsACString& aSpec,
-                                                  int32_t aNewFrecency,
-                                                  const nsACString& aGUID,
-                                                  bool aHidden,
-                                                  PRTime aLastVisitDate) const
-{
-  nsCOMPtr<nsIRunnable> notif = new FrecencyNotification(aSpec, aNewFrecency,
-                                                         aGUID, aHidden,
-                                                         aLastVisitDate);
-  (void)NS_DispatchToMainThread(notif);
-}
-
 int32_t
 nsNavHistory::GetDaysOfHistory() {
   MOZ_ASSERT(NS_IsMainThread(), "This can only be called on the main thread");
 
   if (mDaysOfHistory != -1)
     return mDaysOfHistory;
 
   // SQLite doesn't have a CEIL() function, so we must do that later.
@@ -999,78 +923,42 @@ NS_IMETHODIMP
 nsNavHistory::GetHasHistoryEntries(bool* aHasEntries)
 {
   NS_ENSURE_ARG_POINTER(aHasEntries);
   *aHasEntries = GetDaysOfHistory() > 0;
   return NS_OK;
 }
 
 
-namespace {
-
-class InvalidateAllFrecenciesCallback : public AsyncStatementCallback
-{
-public:
-  InvalidateAllFrecenciesCallback()
-  {
-  }
-
-  NS_IMETHOD HandleCompletion(uint16_t aReason)
-  {
-    if (aReason == REASON_FINISHED) {
-      nsNavHistory *navHistory = nsNavHistory::GetHistoryService();
-      NS_ENSURE_STATE(navHistory);
-      navHistory->NotifyManyFrecenciesChanged();
-    }
-    return NS_OK;
-  }
-};
-
-} // anonymous namespace
-
 nsresult
 nsNavHistory::invalidateFrecencies(const nsCString& aPlaceIdsQueryString)
 {
   // Exclude place: queries by setting their frecency to zero.
-  nsCString invalidFrecenciesSQLFragment(
-    "UPDATE moz_places SET frecency = "
-  );
-  if (!aPlaceIdsQueryString.IsEmpty())
-    invalidFrecenciesSQLFragment.AppendLiteral("NOTIFY_FRECENCY(");
-  invalidFrecenciesSQLFragment.AppendLiteral(
-      "(CASE "
-       "WHEN url BETWEEN 'place:' AND 'place;' "
-       "THEN 0 "
-       "ELSE -1 "
-       "END) "
-  );
-  if (!aPlaceIdsQueryString.IsEmpty()) {
-    invalidFrecenciesSQLFragment.AppendLiteral(
-      ", url, guid, hidden, last_visit_date) "
-    );
-  }
-  invalidFrecenciesSQLFragment.AppendLiteral(
+  nsAutoCString invalideFrecenciesSQLFragment(
+    "UPDATE moz_places SET frecency = (CASE "
+      "WHEN url BETWEEN 'place:' AND 'place;' "
+      "THEN 0 "
+      "ELSE -1 "
+      "END) "
     "WHERE frecency > 0 "
   );
+
   if (!aPlaceIdsQueryString.IsEmpty()) {
-    invalidFrecenciesSQLFragment.AppendLiteral("AND id IN(");
-    invalidFrecenciesSQLFragment.Append(aPlaceIdsQueryString);
-    invalidFrecenciesSQLFragment.AppendLiteral(")");
+    invalideFrecenciesSQLFragment.AppendLiteral("AND id IN(");
+    invalideFrecenciesSQLFragment.Append(aPlaceIdsQueryString);
+    invalideFrecenciesSQLFragment.AppendLiteral(")");
   }
-  nsRefPtr<InvalidateAllFrecenciesCallback> cb =
-    aPlaceIdsQueryString.IsEmpty() ? new InvalidateAllFrecenciesCallback()
-                                   : nullptr;
 
   nsCOMPtr<mozIStorageAsyncStatement> stmt = mDB->GetAsyncStatement(
-    invalidFrecenciesSQLFragment
+    invalideFrecenciesSQLFragment
   );
   NS_ENSURE_STATE(stmt);
 
   nsCOMPtr<mozIStoragePendingStatement> ps;
-  nsresult rv = stmt->ExecuteAsync(cb, getter_AddRefs(ps));
+  nsresult rv = stmt->ExecuteAsync(nullptr, getter_AddRefs(ps));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 
 // Call this method before visiting a URL in order to help determine the
 // transition type of the visit.
@@ -3185,40 +3073,16 @@ nsNavHistory::Observe(nsISupports *aSubj
   else if (strcmp(aTopic, TOPIC_IDLE_DAILY) == 0) {
     (void)DecayFrecency();
   }
 
   return NS_OK;
 }
 
 
-namespace {
-
-class DecayFrecencyCallback : public AsyncStatementTelemetryTimer
-{
-public:
-  DecayFrecencyCallback()
-    : AsyncStatementTelemetryTimer(Telemetry::PLACES_IDLE_FRECENCY_DECAY_TIME_MS)
-  {
-  }
-
-  NS_IMETHOD HandleCompletion(uint16_t aReason)
-  {
-    (void)AsyncStatementTelemetryTimer::HandleCompletion(aReason);
-    if (aReason == REASON_FINISHED) {
-      nsNavHistory *navHistory = nsNavHistory::GetHistoryService();
-      NS_ENSURE_STATE(navHistory);
-      navHistory->NotifyManyFrecenciesChanged();
-    }
-    return NS_OK;
-  }
-};
-
-} // anonymous namespace
-
 nsresult
 nsNavHistory::DecayFrecency()
 {
   nsresult rv = FixInvalidFrecencies();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Globally decay places frecency rankings to estimate reduced frecency
   // values of pages that haven't been visited for a while, i.e., they do
@@ -3246,17 +3110,18 @@ nsNavHistory::DecayFrecency()
   NS_ENSURE_STATE(deleteAdaptive);
 
   mozIStorageBaseStatement *stmts[] = {
     decayFrecency.get(),
     decayAdaptive.get(),
     deleteAdaptive.get()
   };
   nsCOMPtr<mozIStoragePendingStatement> ps;
-  nsRefPtr<DecayFrecencyCallback> cb = new DecayFrecencyCallback();
+  nsRefPtr<AsyncStatementTelemetryTimer> cb =
+    new AsyncStatementTelemetryTimer(Telemetry::PLACES_IDLE_FRECENCY_DECAY_TIME_MS);
   rv = mDB->MainConn()->ExecuteAsync(stmts, ArrayLength(stmts), cb,
                                      getter_AddRefs(ps));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 
@@ -4442,19 +4307,17 @@ void ParseSearchTermsFromQueries(const n
 } // anonymous namespace
 
 
 nsresult
 nsNavHistory::UpdateFrecency(int64_t aPlaceId)
 {
   nsCOMPtr<mozIStorageAsyncStatement> updateFrecencyStmt = mDB->GetAsyncStatement(
     "UPDATE moz_places "
-    "SET frecency = NOTIFY_FRECENCY("
-      "CALCULATE_FRECENCY(:page_id), url, guid, hidden, last_visit_date"
-    ") "
+    "SET frecency = CALCULATE_FRECENCY(:page_id) "
     "WHERE id = :page_id"
   );
   NS_ENSURE_STATE(updateFrecencyStmt);
   nsresult rv = updateFrecencyStmt->BindInt64ByName(NS_LITERAL_CSTRING("page_id"),
                                                     aPlaceId);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<mozIStorageAsyncStatement> updateHiddenStmt = mDB->GetAsyncStatement(
     "UPDATE moz_places "
@@ -4477,53 +4340,28 @@ nsNavHistory::UpdateFrecency(int64_t aPl
   rv = mDB->MainConn()->ExecuteAsync(stmts, ArrayLength(stmts), cb,
                                      getter_AddRefs(ps));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 
-namespace {
-
-class FixInvalidFrecenciesCallback : public AsyncStatementCallbackNotifier
-{
-public:
-  FixInvalidFrecenciesCallback()
-    : AsyncStatementCallbackNotifier(TOPIC_FRECENCY_UPDATED)
-  {
-  }
-
-  NS_IMETHOD HandleCompletion(uint16_t aReason)
-  {
-    nsresult rv = AsyncStatementCallbackNotifier::HandleCompletion(aReason);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (aReason == REASON_FINISHED) {
-      nsNavHistory *navHistory = nsNavHistory::GetHistoryService();
-      NS_ENSURE_STATE(navHistory);
-      navHistory->NotifyManyFrecenciesChanged();
-    }
-    return NS_OK;
-  }
-};
-
-} // anonymous namespace
-
 nsresult
 nsNavHistory::FixInvalidFrecencies()
 {
   nsCOMPtr<mozIStorageAsyncStatement> stmt = mDB->GetAsyncStatement(
     "UPDATE moz_places "
     "SET frecency = CALCULATE_FRECENCY(id) "
     "WHERE frecency < 0"
   );
   NS_ENSURE_STATE(stmt);
 
-  nsRefPtr<FixInvalidFrecenciesCallback> callback =
-    new FixInvalidFrecenciesCallback();
+  nsRefPtr<AsyncStatementCallbackNotifier> callback =
+    new AsyncStatementCallbackNotifier(TOPIC_FRECENCY_UPDATED);
   nsCOMPtr<mozIStoragePendingStatement> ps;
   (void)stmt->ExecuteAsync(callback, getter_AddRefs(ps));
 
   return NS_OK;
 }
 
 
 #ifdef MOZ_XUL
--- a/toolkit/components/places/nsNavHistory.h
+++ b/toolkit/components/places/nsNavHistory.h
@@ -413,39 +413,16 @@ public:
 
   /**
    * Fires onTitleChanged event to nsINavHistoryService observers
    */
   void NotifyTitleChange(nsIURI* aURI,
                          const nsString& title,
                          const nsACString& aGUID);
 
-  /**
-   * Fires onFrecencyChanged event to nsINavHistoryService observers
-   */
-  void NotifyFrecencyChanged(nsIURI* aURI,
-                             int32_t aNewFrecency,
-                             const nsACString& aGUID,
-                             bool aHidden,
-                             PRTime aLastVisitDate);
-
-  /**
-   * Fires onManyFrecenciesChanged event to nsINavHistoryService observers
-   */
-  void NotifyManyFrecenciesChanged();
-
-  /**
-   * Posts a runnable to the main thread that calls NotifyFrecencyChanged.
-   */
-  void DispatchFrecencyChangedNotification(const nsACString& aSpec,
-                                           int32_t aNewFrecency,
-                                           const nsACString& aGUID,
-                                           bool aHidden,
-                                           PRTime aLastVisitDate) const;
-
   bool isBatching() {
     return mBatchLevel > 0;
   }
 
 private:
   ~nsNavHistory();
 
   // used by GetHistoryService
--- a/toolkit/components/places/nsNavHistoryResult.cpp
+++ b/toolkit/components/places/nsNavHistoryResult.cpp
@@ -2609,34 +2609,16 @@ nsNavHistoryQueryResultNode::OnTitleChan
       }
     }
   }
 
   return ChangeTitles(aURI, newTitle, true, onlyOneEntry);
 }
 
 
-NS_IMETHODIMP
-nsNavHistoryQueryResultNode::OnFrecencyChanged(nsIURI* aURI,
-                                               int32_t aNewFrecency,
-                                               const nsACString& aGUID,
-                                               bool aHidden,
-                                               PRTime aLastVisitDate)
-{
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsNavHistoryQueryResultNode::OnManyFrecenciesChanged()
-{
-  return NS_OK;
-}
-
-
 /**
  * Here, we can always live update by just deleting all occurrences of
  * the given URI.
  */
 NS_IMETHODIMP
 nsNavHistoryQueryResultNode::OnDeleteURI(nsIURI* aURI,
                                          const nsACString& aGUID,
                                          uint16_t aReason)
@@ -4676,34 +4658,16 @@ nsNavHistoryResult::OnTitleChanged(nsIUR
                                    const nsACString& aGUID)
 {
   ENUMERATE_HISTORY_OBSERVERS(OnTitleChanged(aURI, aPageTitle, aGUID));
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
-nsNavHistoryResult::OnFrecencyChanged(nsIURI* aURI,
-                                      int32_t aNewFrecency,
-                                      const nsACString& aGUID,
-                                      bool aHidden,
-                                      PRTime aLastVisitDate)
-{
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsNavHistoryResult::OnManyFrecenciesChanged()
-{
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
 nsNavHistoryResult::OnDeleteURI(nsIURI *aURI,
                                 const nsACString& aGUID,
                                 uint16_t aReason)
 {
   ENUMERATE_HISTORY_OBSERVERS(OnDeleteURI(aURI, aGUID, aReason));
   return NS_OK;
 }
 
--- a/toolkit/components/places/nsNavHistoryResult.h
+++ b/toolkit/components/places/nsNavHistoryResult.h
@@ -59,20 +59,16 @@ private:
 
 
 // Declare methods for implementing nsINavBookmarkObserver
 // and nsINavHistoryObserver (some methods, such as BeginUpdateBatch overlap)
 #define NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE                          \
   NS_DECL_NSINAVBOOKMARKOBSERVER                                        \
   NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle,  \
                             const nsACString& aGUID);                   \
-  NS_IMETHOD OnFrecencyChanged(nsIURI* aURI, int32_t aNewFrecency,      \
-                               const nsACString& aGUID, bool aHidden,   \
-                               PRTime aLastVisitDate);                  \
-  NS_IMETHOD OnManyFrecenciesChanged();                                 \
   NS_IMETHOD OnDeleteURI(nsIURI *aURI, const nsACString& aGUID,         \
                          uint16_t aReason);                             \
   NS_IMETHOD OnClearHistory();                                          \
   NS_IMETHOD OnPageChanged(nsIURI *aURI, uint32_t aChangedAttribute,    \
                            const nsAString &aNewValue,                  \
                            const nsACString &aGUID);                    \
   NS_IMETHOD OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,            \
                             const nsACString& aGUID, uint16_t aReason,  \
deleted file mode 100644
--- a/toolkit/components/places/tests/unit/test_frecency_observers.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function run_test() {
-  run_next_test();
-}
-
-// Each of these tests a path that triggers a frecency update.  Together they
-// hit all sites that update a frecency.
-
-// InsertVisitedURIs::UpdateFrecency and History::InsertPlace
-add_task(function test_InsertVisitedURIs_UpdateFrecency_and_History_InsertPlace() {
-  // InsertPlace is at the end of a path that UpdateFrecency is also on, so kill
-  // two birds with one stone and expect two notifications.  Trigger the path by
-  // adding a download.
-  let uri = NetUtil.newURI("http://example.com/a");
-  Cc["@mozilla.org/browser/download-history;1"].
-    getService(Ci.nsIDownloadHistory).
-    addDownload(uri);
-  yield Promise.all([onFrecencyChanged(uri), onFrecencyChanged(uri)]);
-});
-
-// nsNavHistory::UpdateFrecency
-add_task(function test_nsNavHistory_UpdateFrecency() {
-  let bm = PlacesUtils.bookmarks;
-  let uri = NetUtil.newURI("http://example.com/b");
-  bm.insertBookmark(bm.unfiledBookmarksFolder, uri,
-                    Ci.nsINavBookmarksService.DEFAULT_INDEX, "test");
-  yield onFrecencyChanged(uri);
-});
-
-// nsNavHistory::invalidateFrecencies for particular pages
-add_task(function test_nsNavHistory_invalidateFrecencies_somePages() {
-  let uri = NetUtil.newURI("http://test-nsNavHistory-invalidateFrecencies-somePages.com/");
-  // Bookmarking the URI is enough to add it to moz_places, and importantly, it
-  // means that removePagesFromHost doesn't remove it from moz_places, so its
-  // frecency is able to be changed.
-  let bm = PlacesUtils.bookmarks;
-  bm.insertBookmark(bm.unfiledBookmarksFolder, uri,
-                    Ci.nsINavBookmarksService.DEFAULT_INDEX, "test");
-  PlacesUtils.history.removePagesFromHost(uri.host, false);
-  yield onFrecencyChanged(uri);
-});
-
-// nsNavHistory::invalidateFrecencies for all pages
-add_task(function test_nsNavHistory_invalidateFrecencies_allPages() {
-  PlacesUtils.history.removeAllPages();
-  yield onManyFrecenciesChanged();
-});
-
-// nsNavHistory::DecayFrecency and nsNavHistory::FixInvalidFrecencies
-add_task(function test_nsNavHistory_DecayFrecency_and_nsNavHistory_FixInvalidFrecencies() {
-  // FixInvalidFrecencies is at the end of a path that DecayFrecency is also on,
-  // so expect two notifications.  Trigger the path by making nsNavHistory
-  // observe the idle-daily notification.
-  PlacesUtils.history.QueryInterface(Ci.nsIObserver).
-    observe(null, "idle-daily", "");
-  yield Promise.all([onManyFrecenciesChanged(), onManyFrecenciesChanged()]);
-});
-
-function onFrecencyChanged(expectedURI) {
-  let deferred = Promise.defer();
-  let obs = new NavHistoryObserver();
-  obs.onFrecencyChanged =
-    (uri, newFrecency, guid, hidden, visitDate) => {
-      PlacesUtils.history.removeObserver(obs);
-      do_check_true(!!uri);
-      do_check_true(uri.equals(expectedURI));
-      deferred.resolve();
-    };
-  PlacesUtils.history.addObserver(obs, false);
-  return deferred.promise;
-}
-
-function onManyFrecenciesChanged() {
-  let deferred = Promise.defer();
-  let obs = new NavHistoryObserver();
-  obs.onManyFrecenciesChanged = () => {
-    PlacesUtils.history.removeObserver(obs);
-    do_check_true(true);
-    deferred.resolve();
-  };
-  PlacesUtils.history.addObserver(obs, false);
-  return deferred.promise;
-}
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -108,17 +108,16 @@ skip-if = os == "android"
 fail-if = os == "android"
 [test_multi_word_tags.js]
 [test_nsINavHistoryViewer.js]
 # Bug 902248: intermittent timeouts on all platforms
 skip-if = true
 [test_null_interfaces.js]
 [test_onItemChanged_tags.js]
 [test_pageGuid_bookmarkGuid.js]
-[test_frecency_observers.js]
 [test_placeURIs.js]
 [test_PlacesUtils_asyncGetBookmarkIds.js]
 [test_PlacesUtils_lazyobservers.js]
 [test_placesTxn.js]
 [test_preventive_maintenance.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [test_preventive_maintenance_checkAndFixDatabase.js]
deleted file mode 100644
--- a/toolkit/modules/BinarySearch.jsm
+++ /dev/null
@@ -1,74 +0,0 @@
-/* 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/. */
-
-"use strict";
-
-this.EXPORTED_SYMBOLS = [
-  "BinarySearch",
-];
-
-this.BinarySearch = Object.freeze({
-
-  /**
-   * Returns the index of the given target in the given array or -1 if the
-   * target is not found.
-   *
-   * See search() for a description of this function's parameters.
-   *
-   * @return The index of `target` in `array` or -1 if `target` is not found.
-   */
-  indexOf: function (array, target, comparator) {
-    let [found, idx] = this.search(array, target, comparator);
-    return found ? idx : -1;
-  },
-
-  /**
-   * Returns the index within the given array where the given target may be
-   * inserted to keep the array ordered.
-   *
-   * See search() for a description of this function's parameters.
-   *
-   * @return The index in `array` where `target` may be inserted to keep `array`
-   *         ordered.
-   */
-  insertionIndexOf: function (array, target, comparator) {
-    return this.search(array, target, comparator)[1];
-  },
-
-  /**
-   * Searches for the given target in the given array.
-   *
-   * @param  array
-   *         An array whose elements are ordered by `comparator`.
-   * @param  target
-   *         The value to search for.
-   * @param  comparator
-   *         A function that takes two arguments and compares them, returning a
-   *         negative number if the first should be ordered before the second,
-   *         zero if the first and second have the same ordering, or a positive
-   *         number if the second should be ordered before the first.  The first
-   *         argument is always `target`, and the second argument is a value
-   *         from the array.
-   * @return An array with two elements.  If `target` is found, the first
-   *         element is true, and the second element is its index in the array.
-   *         If `target` is not found, the first element is false, and the
-   *         second element is the index where it may be inserted to keep the
-   *         array ordered.
-   */
-  search: function (array, target, comparator) {
-    let low = 0;
-    let high = array.length - 1;
-    while (low <= high) {
-      let mid = Math.floor((low + high) / 2);
-      let cmp = comparator(target, array[mid]);
-      if (cmp == 0)
-        return [true, mid];
-      if (cmp < 0)
-        high = mid - 1;
-      else
-        low = mid + 1;
-    }
-    return [false, low];
-  },
-});
--- a/toolkit/modules/NewTabUtils.jsm
+++ b/toolkit/modules/NewTabUtils.jsm
@@ -14,23 +14,16 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
   "resource://gre/modules/PlacesUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
   "resource://gre/modules/PageThumbs.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "BinarySearch",
-  "resource://gre/modules/BinarySearch.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "Timer", () => {
-  return Cu.import("resource://gre/modules/Timer.jsm", {});
-});
-
 XPCOMUtils.defineLazyGetter(this, "gPrincipal", function () {
   let uri = Services.io.newURI("about:newtab", null, null);
   return Services.scriptSecurityManager.getNoAppCodebasePrincipal(uri);
 });
 
 XPCOMUtils.defineLazyGetter(this, "gCryptoHash", function () {
   return Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
 });
@@ -46,28 +39,22 @@ XPCOMUtils.defineLazyGetter(this, "gUnic
 const PREF_NEWTAB_ENABLED = "browser.newtabpage.enabled";
 
 // The preference that tells the number of rows of the newtab grid.
 const PREF_NEWTAB_ROWS = "browser.newtabpage.rows";
 
 // The preference that tells the number of columns of the newtab grid.
 const PREF_NEWTAB_COLUMNS = "browser.newtabpage.columns";
 
-// The maximum number of results PlacesProvider retrieves from history.
+// The maximum number of results we want to retrieve from history.
 const HISTORY_RESULTS_LIMIT = 100;
 
-// The maximum number of links Links.getLinks will return.
-const LINKS_GET_LINKS_LIMIT = 100;
-
 // The gather telemetry topic.
 const TOPIC_GATHER_TELEMETRY = "gather-telemetry";
 
-// The amount of time we wait while coalescing updates for hidden pages.
-const SCHEDULE_UPDATE_TIMEOUT_MS = 1000;
-
 /**
  * Calculate the MD5 hash for a string.
  * @param aValue
  *        The string to convert.
  * @return The base64 representation of the MD5 hash.
  */
 function toHash(aValue) {
   let value = gUnicodeConverter.convertToByteArray(aValue);
@@ -252,45 +239,25 @@ let AllPages = {
    */
   get length() {
     return this._pages.length;
   },
 
   /**
    * Updates all currently active pages but the given one.
    * @param aExceptPage The page to exclude from updating.
-   * @param aHiddenPagesOnly If true, only pages hidden in the preloader are
-   *                         updated.
    */
-  update: function AllPages_update(aExceptPage, aHiddenPagesOnly=false) {
+  update: function AllPages_update(aExceptPage) {
     this._pages.forEach(function (aPage) {
       if (aExceptPage != aPage)
-        aPage.update(aHiddenPagesOnly);
+        aPage.update();
     });
   },
 
   /**
-   * Many individual link changes may happen in a small amount of time over
-   * multiple turns of the event loop.  This method coalesces updates by waiting
-   * a small amount of time before updating hidden pages.
-   */
-  scheduleUpdateForHiddenPages: function AllPages_scheduleUpdateForHiddenPages() {
-    if (!this._scheduleUpdateTimeout) {
-      this._scheduleUpdateTimeout = Timer.setTimeout(() => {
-        delete this._scheduleUpdateTimeout;
-        this.update(null, true);
-      }, SCHEDULE_UPDATE_TIMEOUT_MS);
-    }
-  },
-
-  get updateScheduledForHiddenPages() {
-    return !!this._scheduleUpdateTimeout;
-  },
-
-  /**
    * Implements the nsIObserver interface to get notified when the preference
    * value changes or when a new copy of a page thumbnail is available.
    */
   observe: function AllPages_observe(aSubject, aTopic, aData) {
     if (aTopic == "nsPref:changed") {
       // Clear the cached value.
       this._enabled = null;
     }
@@ -533,231 +500,85 @@ let BlockedLinks = {
 };
 
 /**
  * Singleton that serves as the default link provider for the grid. It queries
  * the history to retrieve the most frequently visited sites.
  */
 let PlacesProvider = {
   /**
-   * Set this to change the maximum number of links the provider will provide.
-   */
-  maxNumLinks: HISTORY_RESULTS_LIMIT,
-
-  /**
-   * Must be called before the provider is used.
-   */
-  init: function PlacesProvider_init() {
-    PlacesUtils.history.addObserver(this, true);
-  },
-
-  /**
    * Gets the current set of links delivered by this provider.
    * @param aCallback The function that the array of links is passed to.
    */
   getLinks: function PlacesProvider_getLinks(aCallback) {
     let options = PlacesUtils.history.getNewQueryOptions();
-    options.maxResults = this.maxNumLinks;
+    options.maxResults = HISTORY_RESULTS_LIMIT;
 
     // Sort by frecency, descending.
     options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_FRECENCY_DESCENDING
 
     let links = [];
 
     let callback = {
       handleResult: function (aResultSet) {
         let row;
 
         while ((row = aResultSet.getNextRow())) {
           let url = row.getResultByIndex(1);
           if (LinkChecker.checkLoadURI(url)) {
             let title = row.getResultByIndex(2);
-            let frecency = row.getResultByIndex(12);
-            let lastVisitDate = row.getResultByIndex(5);
-            links.push({
-              url: url,
-              title: title,
-              frecency: frecency,
-              lastVisitDate: lastVisitDate,
-            });
+            links.push({url: url, title: title});
           }
         }
       },
 
       handleError: function (aError) {
         // Should we somehow handle this error?
         aCallback([]);
       },
 
       handleCompletion: function (aReason) {
-        // The Places query breaks ties in frecency by place ID descending, but
-        // that's different from how Links.compareLinks breaks ties, because
-        // compareLinks doesn't have access to place IDs.  It's very important
-        // that the initial list of links is sorted in the same order imposed by
-        // compareLinks, because Links uses compareLinks to perform binary
-        // searches on the list.  So, ensure the list is so ordered.
-        let i = 1;
-        let outOfOrder = [];
-        while (i < links.length) {
-          if (Links.compareLinks(links[i - 1], links[i]) > 0)
-            outOfOrder.push(links.splice(i, 1)[0]);
-          else
-            i++;
-        }
-        for (let link of outOfOrder) {
-          i = BinarySearch.insertionIndexOf(links, link,
-                                            Links.compareLinks.bind(Links));
-          links.splice(i, 0, link);
-        }
-
         aCallback(links);
       }
     };
 
     // Execute the query.
     let query = PlacesUtils.history.getNewQuery();
     let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase);
     db.asyncExecuteLegacyQueries([query], 1, options, callback);
-  },
-
-  /**
-   * Registers an object that will be notified when the provider's links change.
-   * @param aObserver An object with the following optional properties:
-   *        * onLinkChanged: A function that's called when a single link
-   *          changes.  It's passed the provider and the link object.  Only the
-   *          link's `url` property is guaranteed to be present.  If its `title`
-   *          property is present, then its title has changed, and the
-   *          property's value is the new title.  If any sort properties are
-   *          present, then its position within the provider's list of links may
-   *          have changed, and the properties' values are the new sort-related
-   *          values.  Note that this link may not necessarily have been present
-   *          in the lists returned from any previous calls to getLinks.
-   *        * onManyLinksChanged: A function that's called when many links
-   *          change at once.  It's passed the provider.  You should call
-   *          getLinks to get the provider's new list of links.
-   */
-  addObserver: function PlacesProvider_addObserver(aObserver) {
-    this._observers.push(aObserver);
-  },
-
-  _observers: [],
-
-  /**
-   * Called by the history service.
-   */
-  onFrecencyChanged: function PlacesProvider_onFrecencyChanged(aURI, aNewFrecency, aGUID, aHidden, aLastVisitDate) {
-    // The implementation of the query in getLinks excludes hidden and
-    // unvisited pages, so it's important to exclude them here, too.
-    if (!aHidden && aLastVisitDate) {
-      this._callObservers("onLinkChanged", {
-        url: aURI.spec,
-        frecency: aNewFrecency,
-        lastVisitDate: aLastVisitDate,
-      });
-    }
-  },
-
-  /**
-   * Called by the history service.
-   */
-  onManyFrecenciesChanged: function PlacesProvider_onManyFrecenciesChanged() {
-    this._callObservers("onManyLinksChanged");
-  },
-
-  /**
-   * Called by the history service.
-   */
-  onTitleChanged: function PlacesProvider_onTitleChanged(aURI, aNewTitle, aGUID) {
-    this._callObservers("onLinkChanged", {
-      url: aURI.spec,
-      title: aNewTitle
-    });
-  },
-
-  _callObservers: function PlacesProvider__callObservers(aMethodName, aArg) {
-    for (let obs of this._observers) {
-      if (obs[aMethodName]) {
-        try {
-          obs[aMethodName](this, aArg);
-        } catch (err) {
-          Cu.reportError(err);
-        }
-      }
-    }
-  },
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver,
-                                         Ci.nsISupportsWeakReference]),
+  }
 };
 
 /**
  * Singleton that provides access to all links contained in the grid (including
- * the ones that don't fit on the grid). A link is a plain object that looks
- * like this:
+ * the ones that don't fit on the grid). A link is a plain object with title
+ * and url properties.
  *
- * {
- *   url: "http://www.mozilla.org/",
- *   title: "Mozilla",
- *   frecency: 1337,
- *   lastVisitDate: 1394678824766431,
- * }
+ * Example:
+ *
+ * {url: "http://www.mozilla.org/", title: "Mozilla"}
  */
 let Links = {
   /**
-   * The maximum number of links returned by getLinks.
+   * The links cache.
    */
-  maxNumLinks: LINKS_GET_LINKS_LIMIT,
-
-  /**
-   * The link providers.
-   */
-  _providers: new Set(),
+  _links: null,
 
   /**
-   * A mapping from each provider to an object { sortedLinks, linkMap }.
-   * sortedLinks is the cached, sorted array of links for the provider.  linkMap
-   * is a Map from link URLs to link objects.
+   * The default provider for links.
    */
-  _providerLinks: new Map(),
-
-  /**
-   * The properties of link objects used to sort them.
-   */
-  _sortProperties: [
-    "frecency",
-    "lastVisitDate",
-    "url",
-  ],
+  _provider: PlacesProvider,
 
   /**
    * List of callbacks waiting for the cache to be populated.
    */
   _populateCallbacks: [],
 
   /**
-   * Adds a link provider.
-   * @param aProvider The link provider.
-   */
-  addProvider: function Links_addProvider(aProvider) {
-    this._providers.add(aProvider);
-    aProvider.addObserver(this);
-  },
-
-  /**
-   * Removes a link provider.
-   * @param aProvider The link provider.
-   */
-  removeProvider: function Links_removeProvider(aProvider) {
-    if (!this._providers.delete(aProvider))
-      throw new Error("Unknown provider");
-    this._providerLinks.delete(aProvider);
-  },
-
-  /**
-   * Populates the cache with fresh links from the providers.
+   * Populates the cache with fresh links from the current provider.
    * @param aCallback The callback to call when finished (optional).
    * @param aForce When true, populates the cache even when it's already filled.
    */
   populateCache: function Links_populateCache(aCallback, aForce) {
     let callbacks = this._populateCallbacks;
 
     // Enqueue the current callback.
     callbacks.push(aCallback);
@@ -775,37 +596,37 @@ let Links = {
             callback();
           } catch (e) {
             // We want to proceed even if a callback fails.
           }
         }
       }
     }
 
-    let numProvidersRemaining = this._providers.size;
-    for (let provider of this._providers) {
-      this._populateProviderCache(provider, () => {
-        if (--numProvidersRemaining == 0)
-          executeCallbacks();
-      }, aForce);
+    if (this._links && !aForce) {
+      executeCallbacks();
+    } else {
+      this._provider.getLinks(function (aLinks) {
+        this._links = aLinks;
+        executeCallbacks();
+      }.bind(this));
+
+      this._addObserver();
     }
-
-    this._addObserver();
   },
 
   /**
    * Gets the current set of links contained in the grid.
    * @return The links in the grid.
    */
   getLinks: function Links_getLinks() {
     let pinnedLinks = Array.slice(PinnedLinks.links);
-    let links = this._getMergedProviderLinks();
 
     // Filter blocked and pinned links.
-    links = links.filter(function (link) {
+    let links = (this._links || []).filter(function (link) {
       return !BlockedLinks.isBlocked(link) && !PinnedLinks.isPinned(link);
     });
 
     // Try to fill the gaps between pinned links.
     for (let i = 0; i < pinnedLinks.length && links.length; i++)
       if (!pinnedLinks[i])
         pinnedLinks[i] = links.shift();
 
@@ -815,209 +636,30 @@ let Links = {
 
     return pinnedLinks;
   },
 
   /**
    * Resets the links cache.
    */
   resetCache: function Links_resetCache() {
-    this._providerLinks.clear();
-  },
-
-  /**
-   * Compares two links.
-   * @param aLink1 The first link.
-   * @param aLink2 The second link.
-   * @return A negative number if aLink1 is ordered before aLink2, zero if
-   *         aLink1 and aLink2 have the same ordering, or a positive number if
-   *         aLink1 is ordered after aLink2.
-   */
-  compareLinks: function Links_compareLinks(aLink1, aLink2) {
-    for (let prop of this._sortProperties) {
-      if (!(prop in aLink1) || !(prop in aLink2))
-        throw new Error("Comparable link missing required property: " + prop);
-    }
-    return aLink2.frecency - aLink1.frecency ||
-           aLink2.lastVisitDate - aLink1.lastVisitDate ||
-           aLink1.url.localeCompare(aLink2.url);
-  },
-
-  /**
-   * Calls getLinks on the given provider and populates our cache for it.
-   * @param aProvider The provider whose cache will be populated.
-   * @param aCallback The callback to call when finished.
-   * @param aForce When true, populates the provider's cache even when it's
-   *               already filled.
-   */
-  _populateProviderCache: function Links_populateProviderCache(aProvider, aCallback, aForce) {
-    if (this._providerLinks.has(aProvider) && !aForce) {
-      aCallback();
-    } else {
-      aProvider.getLinks(links => {
-        // Filter out null and undefined links so we don't have to deal with
-        // them in getLinks when merging links from providers.
-        links = links.filter((link) => !!link);
-        this._providerLinks.set(aProvider, {
-          sortedLinks: links,
-          linkMap: links.reduce((map, link) => {
-            map.set(link.url, link);
-            return map;
-          }, new Map()),
-        });
-        aCallback();
-      });
-    }
-  },
-
-  /**
-   * Merges the cached lists of links from all providers whose lists are cached.
-   * @return The merged list.
-   */
-  _getMergedProviderLinks: function Links__getMergedProviderLinks() {
-    // Build a list containing a copy of each provider's sortedLinks list.
-    let linkLists = [];
-    for (let links of this._providerLinks.values()) {
-      linkLists.push(links.sortedLinks.slice());
-    }
-
-    function getNextLink() {
-      let minLinks = null;
-      for (let links of linkLists) {
-        if (links.length &&
-            (!minLinks || Links.compareLinks(links[0], minLinks[0]) < 0))
-          minLinks = links;
-      }
-      return minLinks ? minLinks.shift() : null;
-    }
-
-    let finalLinks = [];
-    for (let nextLink = getNextLink();
-         nextLink && finalLinks.length < this.maxNumLinks;
-         nextLink = getNextLink()) {
-      finalLinks.push(nextLink);
-    }
-
-    return finalLinks;
-  },
-
-  /**
-   * Called by a provider to notify us when a single link changes.
-   * @param aProvider The provider whose link changed.
-   * @param aLink The link that changed.  If the link is new, it must have all
-   *              of the _sortProperties.  Otherwise, it may have as few or as
-   *              many as is convenient.
-   */
-  onLinkChanged: function Links_onLinkChanged(aProvider, aLink) {
-    if (!("url" in aLink))
-      throw new Error("Changed links must have a url property");
-
-    let links = this._providerLinks.get(aProvider);
-    if (!links)
-      // This is not an error, it just means that between the time the provider
-      // was added and the future time we call getLinks on it, it notified us of
-      // a change.
-      return;
-
-    let { sortedLinks, linkMap } = links;
-
-    // Nothing to do if the list is full and the link isn't in it and shouldn't
-    // be in it.
-    if (!linkMap.has(aLink.url) &&
-        sortedLinks.length &&
-        sortedLinks.length == aProvider.maxNumLinks) {
-      let lastLink = sortedLinks[sortedLinks.length - 1];
-      if (this.compareLinks(lastLink, aLink) < 0)
-        return;
-    }
-
-    let updatePages = false;
-
-    // Update the title in O(1).
-    if ("title" in aLink) {
-      let link = linkMap.get(aLink.url);
-      if (link && link.title != aLink.title) {
-        link.title = aLink.title;
-        updatePages = true;
-      }
-    }
-
-    // Update the link's position in O(lg n).
-    if (this._sortProperties.some((prop) => prop in aLink)) {
-      let link = linkMap.get(aLink.url);
-      if (link) {
-        // The link is already in the list.
-        let idx = this._indexOf(sortedLinks, link);
-        if (idx < 0)
-          throw new Error("Link should be in _sortedLinks if in _linkMap");
-        sortedLinks.splice(idx, 1);
-        for (let prop of this._sortProperties) {
-          if (prop in aLink)
-            link[prop] = aLink[prop];
-        }
-      }
-      else {
-        // The link is new.
-        for (let prop of this._sortProperties) {
-          if (!(prop in aLink))
-            throw new Error("New link missing required sort property: " + prop);
-        }
-        // Copy the link object so that if the caller changes it, it doesn't
-        // screw up our bookkeeping.
-        link = {};
-        for (let [prop, val] of Iterator(aLink)) {
-          link[prop] = val;
-        }
-        linkMap.set(link.url, link);
-      }
-      let idx = this._insertionIndexOf(sortedLinks, link);
-      sortedLinks.splice(idx, 0, link);
-      if (sortedLinks.length > aProvider.maxNumLinks) {
-        let lastLink = sortedLinks.pop();
-        linkMap.delete(lastLink.url);
-      }
-      updatePages = true;
-    }
-
-    if (updatePages)
-      AllPages.scheduleUpdateForHiddenPages();
-  },
-
-  /**
-   * Called by a provider to notify us when many links change.
-   */
-  onManyLinksChanged: function Links_onManyLinksChanged(aProvider) {
-    this._populateProviderCache(aProvider, () => {
-      AllPages.scheduleUpdateForHiddenPages();
-    }, true);
-  },
-
-  _indexOf: function Links__indexOf(aArray, aLink) {
-    return this._binsearch(aArray, aLink, "indexOf");
-  },
-
-  _insertionIndexOf: function Links__insertionIndexOf(aArray, aLink) {
-    return this._binsearch(aArray, aLink, "insertionIndexOf");
-  },
-
-  _binsearch: function Links__binsearch(aArray, aLink, aMethod) {
-    return BinarySearch[aMethod](aArray, aLink, this.compareLinks.bind(this));
+    this._links = null;
   },
 
   /**
    * 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.resetCache();
+      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);
@@ -1127,30 +769,21 @@ let ExpirationFilter = {
 
 /**
  * Singleton that provides the public API of this JSM.
  */
 this.NewTabUtils = {
   _initialized: false,
 
   init: function NewTabUtils_init() {
-    if (this.initWithoutProviders()) {
-      PlacesProvider.init();
-      Links.addProvider(PlacesProvider);
-    }
-  },
-
-  initWithoutProviders: function NewTabUtils_initWithoutProviders() {
     if (!this._initialized) {
       this._initialized = true;
       ExpirationFilter.init();
       Telemetry.init();
-      return true;
     }
-    return false;
   },
 
   /**
    * Restores all sites that have been removed from the grid.
    */
   restore: function NewTabUtils_restore() {
     Storage.clear();
     Links.resetCache();
--- a/toolkit/modules/moz.build
+++ b/toolkit/modules/moz.build
@@ -6,17 +6,16 @@
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/xpcshell/xpcshell.ini']
 BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
 MOCHITEST_MANIFESTS += ['tests/mochitest/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
 
 EXTRA_JS_MODULES += [
     'AsyncShutdown.jsm',
-    'BinarySearch.jsm',
     'BrowserUtils.jsm',
     'CharsetMenu.jsm',
     'debug.js',
     'DeferredTask.jsm',
     'Deprecated.jsm',
     'Dict.jsm',
     'DirectoryLinksProvider.jsm',
     'FileUtils.jsm',
deleted file mode 100644
--- a/toolkit/modules/tests/xpcshell/test_BinarySearch.js
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-Components.utils.import("resource://gre/modules/BinarySearch.jsm");
-
-function run_test() {
-  // empty array
-  ok([], 1, false, 0);
-
-  // one-element array
-  ok([2], 2, true, 0);
-  ok([2], 1, false, 0);
-  ok([2], 3, false, 1);
-
-  // two-element array
-  ok([2, 4], 2, true, 0);
-  ok([2, 4], 4, true, 1);
-  ok([2, 4], 1, false, 0);
-  ok([2, 4], 3, false, 1);
-  ok([2, 4], 5, false, 2);
-
-  // three-element array
-  ok([2, 4, 6], 2, true, 0);
-  ok([2, 4, 6], 4, true, 1);
-  ok([2, 4, 6], 6, true, 2);
-  ok([2, 4, 6], 1, false, 0);
-  ok([2, 4, 6], 3, false, 1);
-  ok([2, 4, 6], 5, false, 2);
-  ok([2, 4, 6], 7, false, 3);
-
-  // duplicates
-  ok([2, 2], 2, true, 0);
-  ok([2, 2], 1, false, 0);
-  ok([2, 2], 3, false, 2);
-
-  // duplicates on the left
-  ok([2, 2, 4], 2, true, 1);
-  ok([2, 2, 4], 4, true, 2);
-  ok([2, 2, 4], 1, false, 0);
-  ok([2, 2, 4], 3, false, 2);
-  ok([2, 2, 4], 5, false, 3);
-
-  // duplicates on the right
-  ok([2, 4, 4], 2, true, 0);
-  ok([2, 4, 4], 4, true, 1);
-  ok([2, 4, 4], 1, false, 0);
-  ok([2, 4, 4], 3, false, 1);
-  ok([2, 4, 4], 5, false, 3);
-
-  // duplicates in the middle
-  ok([2, 4, 4, 6], 2, true, 0);
-  ok([2, 4, 4, 6], 4, true, 1);
-  ok([2, 4, 4, 6], 6, true, 3);
-  ok([2, 4, 4, 6], 1, false, 0);
-  ok([2, 4, 4, 6], 3, false, 1);
-  ok([2, 4, 4, 6], 5, false, 3);
-  ok([2, 4, 4, 6], 7, false, 4);
-
-  // duplicates all around
-  ok([2, 2, 4, 4, 6, 6], 2, true, 0);
-  ok([2, 2, 4, 4, 6, 6], 4, true, 2);
-  ok([2, 2, 4, 4, 6, 6], 6, true, 4);
-  ok([2, 2, 4, 4, 6, 6], 1, false, 0);
-  ok([2, 2, 4, 4, 6, 6], 3, false, 2);
-  ok([2, 2, 4, 4, 6, 6], 5, false, 4);
-  ok([2, 2, 4, 4, 6, 6], 7, false, 6);
-}
-
-function ok(array, target, expectedFound, expectedIdx) {
-  let [found, idx] = BinarySearch.search(array, target, cmp);
-  do_check_eq(found, expectedFound);
-  do_check_eq(idx, expectedIdx);
-
-  idx = expectedFound ? expectedIdx : -1;
-  do_check_eq(BinarySearch.indexOf(array, target, cmp), idx);
-  do_check_eq(BinarySearch.insertionIndexOf(array, target, cmp), expectedIdx);
-}
-
-function cmp(num1, num2) {
-  return num1 - num2;
-}
deleted file mode 100644
--- a/toolkit/modules/tests/xpcshell/test_NewTabUtils.js
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// See also browser/base/content/test/newtab/.
-
-const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-Cu.import("resource://gre/modules/NewTabUtils.jsm");
-Cu.import("resource://gre/modules/Promise.jsm");
-
-function run_test() {
-  run_next_test();
-}
-
-add_test(function multipleProviders() {
-  // Make each provider generate NewTabUtils.links.maxNumLinks links to check
-  // that no more than maxNumLinks are actually returned in the merged list.
-  let evenLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks, 2);
-  let evenProvider = new TestProvider(done => done(evenLinks));
-  let oddLinks = makeLinks(0, 2 * NewTabUtils.links.maxNumLinks - 1, 2);
-  let oddProvider = new TestProvider(done => done(oddLinks));
-
-  NewTabUtils.initWithoutProviders();
-  NewTabUtils.links.addProvider(evenProvider);
-  NewTabUtils.links.addProvider(oddProvider);
-
-  // This is sync since the providers' getLinks are sync.
-  NewTabUtils.links.populateCache(function () {}, false);
-
-  let links = NewTabUtils.links.getLinks();
-  let expectedLinks = makeLinks(NewTabUtils.links.maxNumLinks,
-                                2 * NewTabUtils.links.maxNumLinks,
-                                1);
-  do_check_eq(links.length, NewTabUtils.links.maxNumLinks);
-  do_check_links(links, expectedLinks);
-
-  NewTabUtils.links.removeProvider(evenProvider);
-  NewTabUtils.links.removeProvider(oddProvider);
-  run_next_test();
-});
-
-add_test(function changeLinks() {
-  let expectedLinks = makeLinks(0, 20, 2);
-  let provider = new TestProvider(done => done(expectedLinks));
-
-  NewTabUtils.initWithoutProviders();
-  NewTabUtils.links.addProvider(provider);
-
-  // This is sync since the provider's getLinks is sync.
-  NewTabUtils.links.populateCache(function () {}, false);
-
-  do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
-
-  // Notify of a new link.
-  let newLink = {
-    url: "http://example.com/19",
-    title: "My frecency is 19",
-    frecency: 19,
-    lastVisitDate: 0,
-  };
-  expectedLinks.splice(1, 0, newLink);
-  provider.notifyLinkChanged(newLink);
-  do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
-
-  // Notify of a link that's changed sort criteria.
-  newLink.frecency = 17;
-  expectedLinks.splice(1, 1);
-  expectedLinks.splice(2, 0, newLink);
-  provider.notifyLinkChanged({
-    url: newLink.url,
-    frecency: 17,
-  });
-  do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
-
-  // Notify of a link that's changed title.
-  newLink.title = "My frecency is now 17";
-  provider.notifyLinkChanged({
-    url: newLink.url,
-    title: newLink.title,
-  });
-  do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
-
-  // Notify of a new link again, but this time make it overflow maxNumLinks.
-  provider.maxNumLinks = expectedLinks.length;
-  newLink = {
-    url: "http://example.com/21",
-    frecency: 21,
-    lastVisitDate: 0,
-  };
-  expectedLinks.unshift(newLink);
-  expectedLinks.pop();
-  do_check_eq(expectedLinks.length, provider.maxNumLinks); // Sanity check.
-  provider.notifyLinkChanged(newLink);
-  do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
-
-  // Notify of many links changed.
-  expectedLinks = makeLinks(0, 3, 1);
-  provider.notifyManyLinksChanged();
-  // NewTabUtils.links will now repopulate its cache, which is sync since
-  // the provider's getLinks is sync.
-  do_check_links(NewTabUtils.links.getLinks(), expectedLinks);
-
-  NewTabUtils.links.removeProvider(provider);
-  run_next_test();
-});
-
-add_task(function oneProviderAlreadyCached() {
-  let links1 = makeLinks(0, 10, 1);
-  let provider1 = new TestProvider(done => done(links1));
-
-  NewTabUtils.initWithoutProviders();
-  NewTabUtils.links.addProvider(provider1);
-
-  // This is sync since the provider's getLinks is sync.
-  NewTabUtils.links.populateCache(function () {}, false);
-  do_check_links(NewTabUtils.links.getLinks(), links1);
-
-  let links2 = makeLinks(10, 20, 1);
-  let provider2 = new TestProvider(done => done(links2));
-  NewTabUtils.links.addProvider(provider2);
-
-  NewTabUtils.links.populateCache(function () {}, false);
-  do_check_links(NewTabUtils.links.getLinks(), links2.concat(links1));
-
-  NewTabUtils.links.removeProvider(provider1);
-  NewTabUtils.links.removeProvider(provider2);
-});
-
-function TestProvider(getLinksFn) {
-  this.getLinks = getLinksFn;
-  this._observers = new Set();
-}
-
-TestProvider.prototype = {
-  addObserver: function (observer) {
-    this._observers.add(observer);
-  },
-  notifyLinkChanged: function (link) {
-    this._notifyObservers("onLinkChanged", link);
-  },
-  notifyManyLinksChanged: function () {
-    this._notifyObservers("onManyLinksChanged");
-  },
-  _notifyObservers: function (observerMethodName, arg) {
-    for (let obs of this._observers) {
-      if (obs[observerMethodName])
-        obs[observerMethodName](this, arg);
-    }
-  },
-};
-
-function do_check_links(actualLinks, expectedLinks) {
-  do_check_true(Array.isArray(actualLinks));
-  do_check_eq(actualLinks.length, expectedLinks.length);
-  for (let i = 0; i < expectedLinks.length; i++) {
-    let expected = expectedLinks[i];
-    let actual = actualLinks[i];
-    do_check_eq(actual.url, expected.url);
-    do_check_eq(actual.title, expected.title);
-    do_check_eq(actual.frecency, expected.frecency);
-    do_check_eq(actual.lastVisitDate, expected.lastVisitDate);
-  }
-}
-
-function makeLinks(frecRangeStart, frecRangeEnd, step) {
-  let links = [];
-  // Remember, links are ordered by frecency descending.
-  for (let i = frecRangeEnd; i > frecRangeStart; i -= step) {
-    links.push({
-      url: "http://example.com/" + i,
-      title: "My frecency is " + i,
-      frecency: i,
-      lastVisitDate: 0,
-    });
-  }
-  return links;
-}
--- a/toolkit/modules/tests/xpcshell/xpcshell.ini
+++ b/toolkit/modules/tests/xpcshell/xpcshell.ini
@@ -3,24 +3,22 @@ head =
 tail =
 support-files =
   propertyLists/bug710259_propertyListBinary.plist
   propertyLists/bug710259_propertyListXML.plist
   chromeappsstore.sqlite
   zips/zen.zip
 
 [test_AsyncShutdown.js]
-[test_BinarySearch.js]
 [test_DeferredTask.js]
 [test_dict.js]
 [test_DirectoryLinksProvider.js]
 [test_FileUtils.js]
 [test_Http.js]
 [test_Log.js]
-[test_NewTabUtils.js]
 [test_PermissionsUtils.js]
 [test_Preferences.js]
 [test_Promise.js]
 [test_propertyListsUtils.js]
 [test_readCertPrefs.js]
 [test_Services.js]
 [test_sqlite.js]
 [test_task.js]