Bug 499828 - kill LAZY_ADD and use async storage instead. r=sdwilsh
authorMarco Bonardo <mbonardo@mozilla.com>
Thu, 22 Jul 2010 14:09:10 +0200
changeset 48075 87fddd37683891218f1f11bf9388c4d6720ce153
parent 48074 42c05e0583620961678a14ecc8e3164d63ab7650
child 48076 dfaba4e449bd256d5e2329a1167e6c48df3f9329
push id14561
push usermak77@bonardo.net
push dateThu, 22 Jul 2010 12:10:30 +0000
treeherdermozilla-central@87fddd376838 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssdwilsh
bugs499828
milestone2.0b3pre
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 499828 - kill LAZY_ADD and use async storage instead. r=sdwilsh
docshell/test/browser/browser_bug503832.js
docshell/test/chrome/bug293235_window.xul
toolkit/components/places/src/AsyncFaviconHelpers.cpp
toolkit/components/places/src/nsFaviconService.cpp
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/places/src/nsNavHistory.h
toolkit/components/places/tests/browser/browser_bug399606.js
toolkit/components/places/tests/head_common.js
toolkit/components/places/tests/mochitest/bug_411966/redirect.js
toolkit/components/places/tests/mochitest/test_bug_461710.html
toolkit/components/places/tests/network/test_history_redirects.js
toolkit/components/places/tests/unit/test_404630.js
toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js
--- a/docshell/test/browser/browser_bug503832.js
+++ b/docshell/test/browser/browser_bug503832.js
@@ -22,16 +22,19 @@ function test() {
                 is(aPageTitle, pagetitle, "Correct page title for " + aURI);
                 return;
             case fragmenturl:
                 is(aPageTitle, pagetitle, "Correct page title for " + aURI);
                 // If titles for fragment URLs aren't set, this code
                 // branch won't be called and the test will timeout,
                 // resulting in a failure
                 historyService.removeObserver(historyObserver, false);
+
+                gBrowser.removeCurrentTab();
+
                 finish();
             }
         },
         onBeforeDeleteURI: function(aURI) {},
         onDeleteURI: function(aURI) {},
         onClearHistory: function() {},
         onPageChanged: function(aURI, aWhat, aValue) {},
         onDeleteVisits: function () {},
@@ -71,21 +74,16 @@ function test() {
     function onPageLoad() {
         gBrowser.selectedBrowser.removeEventListener(
             "DOMContentLoaded", onPageLoad, true);
 
         // Now that the page is loaded, click on fragment link
         EventUtils.sendMouseEvent({type:'click'}, 'firefox-link',
                                   gBrowser.selectedBrowser.contentWindow);
 
-        // Give the event system enough time to do its things
-        setTimeout(function() {
-                       gBrowser.removeCurrentTab();
-                   }, 100);
-
         // Test finishes in historyObserver.onTitleChanged() above
     }
 
     // Make sure neither of the test pages haven't been loaded before.
     var info = getNavHistoryEntry(makeURI(pageurl));
     ok(!info, "The test page must not have been visited already.");
     info = getNavHistoryEntry(makeURI(fragmenturl));
     ok(!info, "The fragment test page must not have been visited already.");
--- a/docshell/test/chrome/bug293235_window.xul
+++ b/docshell/test/chrome/bug293235_window.xul
@@ -87,28 +87,35 @@
       link1.className = "";
       function snapshotsEqual(snap1, snap2) {
         return compareSnapshots(snap1, snap2, true)[0];
       }
       ok(!snapshotsEqual(refLink, refVisited), "references should not match");
       ok(snapshotsEqual(refLink, snapshotWindow(TestWindow.getWindow())),
          "link should initially be blue");
 
+      // Because adding visits is async, we will not be notified imemdiately.
+      let visitObserver = {
+        observe: function(aSubject, aTopic, aData)
+        {
+          if (!testURI.equals(aSubject.QueryInterface(Ci.nsIURI))) {
+            return;
+          }
+          os.removeObserver(this, aTopic);
+          SimpleTest.executeSoon(nextTest);
+        },
+      };
+      os.addObserver(visitObserver, "uri-visit-saved", false);
+
       // Load the page that the link on the previous page points to.
       doPageNavigation({
-        uri: getHttpUrl("bug293235_p2.html"),
-        onNavComplete: nextTest
+        uri: getHttpUrl("bug293235_p2.html")
       });
       yield;
 
-      // Because of LAZY_ADD, we will not be notified for three seconds
-      // Wait for four seconds just to be safe.
-      setTimeout(nextTest, 4000);
-      yield;
-
       // And the nodes get notified after the "link-visited" topic, so
       // we need to execute soon...
       SimpleTest.executeSoon(nextTest);
       yield;
 
       // Go back, verify the original page was loaded from the bfcache,
       // and verify that the link is now purple, per the
       // :visited style.
--- a/toolkit/components/places/src/AsyncFaviconHelpers.cpp
+++ b/toolkit/components/places/src/AsyncFaviconHelpers.cpp
@@ -327,17 +327,17 @@ GetEffectivePageStep::HandleResult(mozIS
     FAVICONSTEP_FAIL_IF_FALSE_RV(NS_SUCCEEDED(rv), rv);
   }
   else {
     NS_ASSERTION(mSubStep == 1, "Wrong sub-step?");
     nsCAutoString spec;
     rv = row->GetUTF8String(0, spec);
     FAVICONSTEP_FAIL_IF_FALSE_RV(NS_SUCCEEDED(rv), rv);
     // We always want to use the bookmark uri.
-    rv = mStepper->mPageURI->SetSpec(spec);
+    rv = NS_NewURI(getter_AddRefs(mStepper->mPageURI), spec);
     FAVICONSTEP_FAIL_IF_FALSE_RV(NS_SUCCEEDED(rv), rv);
     // Since we got a result, this is a bookmark.
     mIsBookmarked = true;
   }
 
   return NS_OK;
 }
 
--- a/toolkit/components/places/src/nsFaviconService.cpp
+++ b/toolkit/components/places/src/nsFaviconService.cpp
@@ -488,34 +488,21 @@ nsFaviconService::SetAndLoadFaviconForPa
                                            nsIFaviconDataCallback* aCallback)
 {
   NS_ENSURE_ARG(aPageURI);
   NS_ENSURE_ARG(aFaviconURI);
 
   if (mFaviconsExpirationRunning)
     return NS_OK;
 
-#ifdef LAZY_ADD
-  // Unfortunatly, even if DoSetAndLoadFaviconForPage is completely async,
-  // this method still needs to enqueue a lazy message, because in case of first
-  // visit to a page, the moz_places entry would not yet exists.
-  // So the icon has to wait for visits addition.  Once visits addition will be
-  // async, this can go away.
-  nsNavHistory* historyService = nsNavHistory::GetHistoryService();
-  NS_ENSURE_TRUE(historyService, NS_ERROR_OUT_OF_MEMORY);
-  return historyService->AddLazyLoadFaviconMessage(aPageURI,
-                                                   aFaviconURI,
-                                                   aForceReload,
-                                                   aCallback);
-#else
-  return DoSetAndLoadFaviconForPage(aPageURI,
-                                    aFaviconURI,
-                                    aForceReload,
-                                    aCallback);
-#endif
+  nsresult rv = DoSetAndLoadFaviconForPage(aPageURI, aFaviconURI, aForceReload,
+                                           aCallback);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
 }
 
 
 nsresult
 nsFaviconService::DoSetAndLoadFaviconForPage(nsIURI* aPageURI,
                                              nsIURI* aFaviconURI,
                                              PRBool aForceReload,
                                              nsIFaviconDataCallback* aCallback)
--- a/toolkit/components/places/src/nsNavHistory.cpp
+++ b/toolkit/components/places/src/nsNavHistory.cpp
@@ -157,27 +157,16 @@ using namespace mozilla::places;
 
 // In order to avoid calling PR_now() too often we use a cached "now" value
 // for repeating stuff.  These are milliseconds between "now" cache refreshes.
 #define RENEW_CACHED_NOW_TIMEOUT ((PRInt32)3 * PR_MSEC_PER_SEC)
 
 // USECS_PER_DAY == PR_USEC_PER_SEC * 60 * 60 * 24;
 static const PRInt64 USECS_PER_DAY = LL_INIT(20, 500654080);
 
-#ifdef LAZY_ADD
-
-// time that we'll wait before committing messages
-#define LAZY_MESSAGE_TIMEOUT (3 * PR_MSEC_PER_SEC)
-
-// the maximum number of times we'll postpone a lazy timer before committing
-// See StartLazyTimer()
-#define MAX_LAZY_TIMER_DEFERMENTS 2
-
-#endif // LAZY_ADD
-
 // character-set annotation
 #define CHARSET_ANNO NS_LITERAL_CSTRING("URIProperties/characterSet")
 
 // These macros are used when splitting history by date.
 // These are the day containers and catch-all final container.
 #define HISTORY_ADDITIONAL_DATE_CONT_NUM 3
 // We use a guess of the number of months considering all of them 30 days
 // long, but we split only the last 6 months.
@@ -372,20 +361,16 @@ nsNavHistory::nsNavHistory()
 , mNumVisitsForFrecency(10)
 , mTagsFolder(-1)
 , mInPrivateBrowsing(PRIVATEBROWSING_NOTINITED)
 , mDatabaseStatus(DATABASE_STATUS_OK)
 , mHasHistoryEntries(-1)
 , mCanNotify(true)
 , mCacheObservers("history-observers")
 {
-#ifdef LAZY_ADD
-  mLazyTimerSet = PR_TRUE;
-  mLazyTimerDeferments = 0;
-#endif
   NS_ASSERTION(!gHistoryService,
                "Attempting to create two instances of the service!");
   gHistoryService = this;
 }
 
 
 nsNavHistory::~nsNavHistory()
 {
@@ -2031,27 +2016,16 @@ nsNavHistory::FindLastVisit(nsIURI* aURI
 // nsNavHistory::IsURIStringVisited
 //
 //    Takes a URL as a string and returns true if we've visited it.
 //
 //    Be careful to always reset the statement since it will be reused.
 
 PRBool nsNavHistory::IsURIStringVisited(const nsACString& aURIString)
 {
-#ifdef LAZY_ADD
-  // check the lazy list to see if this has recently been added
-  for (PRUint32 i = 0; i < mLazyMessages.Length(); i ++) {
-    if (mLazyMessages[i].type == LazyMessage::Type_AddURI) {
-      if (aURIString.Equals(mLazyMessages[i].uriSpec))
-        return PR_TRUE;
-    }
-  }
-#endif
-
-  // check the main DB
   mozStorageStatementScoper scoper(mDBIsPageVisited);
   nsresult rv = URIBinder::Bind(mDBIsPageVisited, 0, aURIString);
   NS_ENSURE_SUCCESS(rv, PR_FALSE);
 
   PRBool hasMore = PR_FALSE;
   rv = mDBIsPageVisited->ExecuteStep(&hasMore);
   NS_ENSURE_SUCCESS(rv, PR_FALSE);
   return hasMore;
@@ -2635,17 +2609,16 @@ nsNavHistory::CalculateFullVisitCount(PR
   return NS_OK;
 }
 
 
 // Call this method before visiting a URL in order to help determine the
 // transition type of the visit.
 // Later, in AddVisitChain() the next visit to this page will be associated to
 // TRANSITION_BOOKMARK.
-// Note, AddVisitChain() is not called immediately if LAZY_ADD is enabled.
 //
 // @see MarkPageAsTyped
 
 NS_IMETHODIMP
 nsNavHistory::MarkPageAsFollowedBookmark(nsIURI* aURI)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
   NS_ENSURE_ARG(aURI);
@@ -4611,21 +4584,16 @@ nsNavHistory::CleanupPlacesOnVisitsDelet
 //    We don't do duplicates removal, URIs array should be cleaned-up before.
 
 NS_IMETHODIMP
 nsNavHistory::RemovePages(nsIURI **aURIs, PRUint32 aLength, PRBool aDoBatchNotify)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
   NS_ENSURE_ARG(aURIs);
 
-#ifdef LAZY_ADD
-  // We must ensure to remove pages from the lazy messages queue too.
-  CommitLazyMessages();
-#endif
-
   nsresult rv;
   // build a list of place ids to delete
   nsCString deletePlaceIdsQueryString;
   for (PRUint32 i = 0; i < aLength; i++) {
     PRInt64 placeId;
     rv = GetUrlIdFor(aURIs[i], &placeId, PR_FALSE);
     NS_ENSURE_SUCCESS(rv, rv);
     if (placeId != 0) {
@@ -4685,21 +4653,16 @@ nsNavHistory::RemovePage(nsIURI *aURI)
 //
 //    This sends onBeginUpdateBatch/onEndUpdateBatch to observers
 
 NS_IMETHODIMP
 nsNavHistory::RemovePagesFromHost(const nsACString& aHost, PRBool aEntireDomain)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
 
-#ifdef LAZY_ADD
-  // We must ensure to remove pages from the lazy messages queue too.
-  CommitLazyMessages();
-#endif
-
   nsresult rv;
   // Local files don't have any host name. We don't want to delete all files in
   // history when we get passed an empty string, so force to exact match
   if (aHost.IsEmpty())
     aEntireDomain = PR_FALSE;
 
   // translate "(local files)" to an empty host name
   // be sure to use the TitleForDomain to get the localized name
@@ -4778,21 +4741,16 @@ nsNavHistory::RemovePagesFromHost(const 
 //
 //    This method sends onBeginUpdateBatch/onEndUpdateBatch to observers
 
 NS_IMETHODIMP
 nsNavHistory::RemovePagesByTimeframe(PRTime aBeginTime, PRTime aEndTime)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
 
-#ifdef LAZY_ADD
-  // We must ensure to remove pages from the lazy messages queue too.
-  CommitLazyMessages();
-#endif
-
   nsresult rv;
   // build a list of place ids to delete
   nsCString deletePlaceIdsQueryString;
 
   // we only need to know if a place has a visit into the given timeframe
   // this query is faster than actually selecting in moz_historyvisits
   nsCOMPtr<mozIStorageStatement> selectByTime;
   rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
@@ -4854,21 +4812,16 @@ nsNavHistory::RemovePagesByTimeframe(PRT
  * @param aEndTime
  *        The end of the timeframe, inclusive
  */
 NS_IMETHODIMP
 nsNavHistory::RemoveVisitsByTimeframe(PRTime aBeginTime, PRTime aEndTime)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
 
-#ifdef LAZY_ADD
-  // We must ensure to remove pages from the lazy messages queue too.
-  CommitLazyMessages();
-#endif
-
   nsresult rv;
 
   // Build a list of place IDs whose visits fall entirely within the timespan.
   // These places will be deleted by the call to CleanupPlacesOnVisitsDelete
   // below.
   nsCString deletePlaceIdsQueryString;
   {
     nsCOMPtr<mozIStorageStatement> selectByTime;
@@ -4951,21 +4904,16 @@ nsNavHistory::RemoveVisitsByTimeframe(PR
 
 NS_IMETHODIMP
 nsNavHistory::RemoveAllPages()
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
 
   mozStorageTransaction transaction(mDBConn, PR_FALSE);
 
-#ifdef LAZY_ADD
-  // We must ensure to remove pages from the lazy messages queue too.
-  CommitLazyMessages();
-#endif
-
   // reset frecency for all items that will _not_ be deleted
   // Note, we set frecency to -visit_count since we use that value in our
   // idle query to figure out which places to recalcuate frecency first.
   // We must do this before deleting visits.
   nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     "UPDATE moz_places_view SET frecency = -MAX(visit_count, 1) "
     "WHERE id IN("
       "SELECT h.id FROM moz_places_temp h "
@@ -5029,17 +4977,16 @@ nsNavHistory::HidePage(nsIURI *aURI)
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
 // Call this method before visiting a URL in order to help determine the
 // transition type of the visit.
 // Later, in AddVisitChain() the next visit to this page will be associated to
 // TRANSITION_TYPED.
-// Note, AddVisitChain() is not called immediately if LAZY_ADD is enabled.
 //
 // @see MarkPageAsFollowedBookmark
 
 NS_IMETHODIMP
 nsNavHistory::MarkPageAsTyped(nsIURI *aURI)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
   NS_ENSURE_ARG(aURI);
@@ -5064,17 +5011,16 @@ nsNavHistory::MarkPageAsTyped(nsIURI *aU
   return NS_OK;
 }
 
 
 // Call this method before visiting a URL in order to help determine the
 // transition type of the visit.
 // Later, in AddVisitChain() the next visit to this page will be associated to
 // TRANSITION_FRAMED_LINK or TRANSITION_LINK.
-// Note, AddVisitChain() is not called immediately if LAZY_ADD is enabled.
 //
 // @see MarkPageAsTyped
 
 NS_IMETHODIMP
 nsNavHistory::MarkPageAsFollowedLink(nsIURI *aURI)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
   NS_ENSURE_ARG(aURI);
@@ -5113,17 +5059,17 @@ nsNavHistory::RegisterOpenPage(nsIURI* a
     return NS_OK;
 
   PRBool canAdd = PR_FALSE;
   nsresult rv = CanAddURI(aURI, &canAdd);
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt64 placeId;
   // Note: If the URI has never been added to history (but can be added),
-  // LAZY_ADD will cause this to add an orphan page, until the visit is added.
+  // this could add an orphan page, until the visit is added.
   rv = GetUrlIdFor(aURI, &placeId, canAdd);
   NS_ENSURE_SUCCESS(rv, rv);
   if (placeId == 0)
     return NS_OK;
 
   mozStorageStatementScoper scoper(mDBRegisterOpenPage);
 
   rv = mDBRegisterOpenPage->BindInt64ByName(NS_LITERAL_CSTRING("page_id"),
@@ -5247,33 +5193,18 @@ nsNavHistory::AddURI(nsIURI *aURI, PRBoo
   PRBool canAdd = PR_FALSE;
   nsresult rv = CanAddURI(aURI, &canAdd);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!canAdd)
     return NS_OK;
 
   PRTime now = PR_Now();
 
-#ifdef LAZY_ADD
-  LazyMessage message;
-  rv = message.Init(LazyMessage::Type_AddURI, aURI);
-  NS_ENSURE_SUCCESS(rv, rv);
-  message.isRedirect = aRedirect;
-  message.isToplevel = aToplevel;
-  if (aReferrer) {
-    rv = aReferrer->Clone(getter_AddRefs(message.referrer));
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-  message.time = now;
-  rv = AddLazyMessage(message);
-  NS_ENSURE_SUCCESS(rv, rv);
-#else
   rv = AddURIInternal(aURI, now, aRedirect, aToplevel, aReferrer);
   NS_ENSURE_SUCCESS(rv, rv);
-#endif
 
   return NS_OK;
 }
 
 
 // nsNavHistory::AddURIInternal
 //
 //    This does the work of AddURI so it can be done lazily.
@@ -5498,32 +5429,29 @@ nsNavHistory::SetPageTitle(nsIURI* aURI,
   // Don't update the page title inside the private browsing mode.
   if (InPrivateBrowsingMode())
     return NS_OK;
 
   // if aTitle is empty we want to clear the previous title.
   // We don't want to set it to an empty string, but to a NULL value,
   // so we use SetIsVoid and SetPageTitleInternal will take care of that
 
-#ifdef LAZY_ADD
-  LazyMessage message;
-  nsresult rv = message.Init(LazyMessage::Type_Title, aURI);
-  NS_ENSURE_SUCCESS(rv, rv);
-  message.title = aTitle;
-  if (aTitle.IsEmpty())
-    message.title.SetIsVoid(PR_TRUE);
-  return AddLazyMessage(message);
-#else
+  nsresult rv;
   if (aTitle.IsEmpty()) {
+    // Using a void string to bind a NULL in the database.
     nsString voidString;
     voidString.SetIsVoid(PR_TRUE);
-    return SetPageTitleInternal(aURI, voidString);
-  }
-  return SetPageTitleInternal(aURI, aTitle);
-#endif
+    rv = SetPageTitleInternal(aURI, voidString);
+  }
+  else {
+    rv = SetPageTitleInternal(aURI, aTitle);
+  }
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNavHistory::GetPageTitle(nsIURI* aURI, nsAString& aTitle)
 {
   NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread");
   NS_ENSURE_ARG(aURI);
 
@@ -5788,28 +5716,16 @@ nsNavHistory::Observe(nsISupports *aSubj
     if (mPrefBranch)
       mPrefBranch->RemoveObserver("", this);
 
     // Force a preferences save.
     nsCOMPtr<nsIPrefService> prefService = do_QueryInterface(mPrefBranch);
     if (prefService)
       prefService->SavePrefFile(nsnull);
 
-#ifdef LAZY_ADD
-    // Commit all pending lazy messages.
-    CommitLazyMessages(PR_TRUE);
-
-    // Kill lazy timer or it could fire later when statements won't be valid
-    // anymore.
-    if (mLazyTimer) {
-      mLazyTimer->Cancel();
-      mLazyTimer = 0;
-    }
-#endif
-
     // Finalize all statements.
     nsresult rv = FinalizeInternalStatements();
     NS_ENSURE_SUCCESS(rv, rv);
 
     // NOTE: We don't close the connection because the sync service could still
     // need it for a final flush.
   }
 
@@ -5859,35 +5775,19 @@ nsNavHistory::Observe(nsISupports *aSubj
     NS_ENSURE_TRUE(mDBConn, NS_OK);
 
     (void)DecayFrecency();
     (void)VacuumDatabase();
   }
 
   else if (strcmp(aTopic, NS_PRIVATE_BROWSING_SWITCH_TOPIC) == 0) {
     if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_ENTER).Equals(aData)) {
-#ifdef LAZY_ADD
-      // Commit all lazy messages in order to protect against edge cases where a
-      // lazy message which is not allowed in private browsing mode has been
-      // added before entering the private browsing mode, and is going to be
-      // scheduled to be processed after entering the private browsing mode.
-      CommitLazyMessages();
-#endif
-
       mInPrivateBrowsing = PR_TRUE;
     }
     else if (NS_LITERAL_STRING(NS_PRIVATE_BROWSING_LEAVE).Equals(aData)) {
-#ifdef LAZY_ADD
-      // Commit all lazy messages in order to protect against edge cases where a
-      // lazy message which should be processed in private browsing mode has been
-      // added before leaving the private browsing mode, and is going to be
-      // scheduled to be processed after leaving the private browsing mode.
-      CommitLazyMessages();
-#endif
-
       mInPrivateBrowsing = PR_FALSE;
     }
   }
 
   else if (strcmp(aTopic, TOPIC_PLACES_INIT_COMPLETE) == 0) {
     nsCOMPtr<nsIObserverService> os =
       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
     NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
@@ -6053,134 +5953,16 @@ nsNavHistory::DecayFrecency()
   nsCOMPtr<mozIStoragePendingStatement> ps;
   rv = mDBConn->ExecuteAsync(stmts, NS_ARRAY_LENGTH(stmts), nsnull,
                              getter_AddRefs(ps));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
-// Lazy stuff ******************************************************************
-
-#ifdef LAZY_ADD
-
-nsresult
-nsNavHistory::AddLazyLoadFaviconMessage(nsIURI* aPageURI,
-                                        nsIURI* aFaviconURI,
-                                        PRBool aForceReload,
-                                        nsIFaviconDataCallback* aCallback)
-{
-  LazyMessage message;
-  nsresult rv = message.Init(LazyMessage::Type_Favicon, aPageURI);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = aFaviconURI->Clone(getter_AddRefs(message.favicon));
-  NS_ENSURE_SUCCESS(rv, rv);
-  message.alwaysLoadFavicon = aForceReload;
-  message.callback = aCallback;
-  return AddLazyMessage(message);
-}
-
-
-// nsNavHistory::StartLazyTimer
-//
-//    This schedules flushing of the lazy message queue for the future.
-//
-//    If we already have timer set, we canel it and schedule a new timer in
-//    the future. This saves you from having to wait if you open a bunch of
-//    pages in a row. However, we don't want to defer too long, so we'll only
-//    push it back MAX_LAZY_TIMER_DEFERMENTS times. After that we always
-//    let the timer go the next time.
-
-nsresult
-nsNavHistory::StartLazyTimer()
-{
-  if (! mLazyTimer) {
-    mLazyTimer = do_CreateInstance("@mozilla.org/timer;1");
-    if (! mLazyTimer)
-      return NS_ERROR_OUT_OF_MEMORY;
-  } else {
-    if (mLazyTimerSet) {
-      if (mLazyTimerDeferments >= MAX_LAZY_TIMER_DEFERMENTS) {
-        // already set and we don't want to push it back any later, use that one
-        return NS_OK;
-      } else {
-        // push back the active timer
-        mLazyTimer->Cancel();
-        mLazyTimerDeferments ++;
-      }
-    }
-  }
-  nsresult rv = mLazyTimer->InitWithFuncCallback(LazyTimerCallback, this,
-                                                 LAZY_MESSAGE_TIMEOUT,
-                                                 nsITimer::TYPE_ONE_SHOT);
-  NS_ENSURE_SUCCESS(rv, rv);
-  mLazyTimerSet = PR_TRUE;
-  return NS_OK;
-}
-
-
-// nsNavHistory::AddLazyMessage
-
-nsresult
-nsNavHistory::AddLazyMessage(const LazyMessage& aMessage)
-{
-  if (! mLazyMessages.AppendElement(aMessage))
-    return NS_ERROR_OUT_OF_MEMORY;
-  return StartLazyTimer();
-}
-
-
-// nsNavHistory::LazyTimerCallback
-
-void // static
-nsNavHistory::LazyTimerCallback(nsITimer* aTimer, void* aClosure)
-{
-  nsNavHistory* that = static_cast<nsNavHistory*>(aClosure);
-  that->mLazyTimerSet = PR_FALSE;
-  that->mLazyTimerDeferments = 0;
-  that->CommitLazyMessages();
-}
-
-// nsNavHistory::CommitLazyMessages
-
-void
-nsNavHistory::CommitLazyMessages(PRBool aIsShutdown)
-{
-  mozStorageTransaction transaction(mDBConn, PR_TRUE);
-  for (PRUint32 i = 0; i < mLazyMessages.Length(); i ++) {
-    LazyMessage& message = mLazyMessages[i];
-    switch (message.type) {
-      case LazyMessage::Type_AddURI:
-        AddURIInternal(message.uri, message.time, message.isRedirect,
-                       message.isToplevel, message.referrer);
-        break;
-      case LazyMessage::Type_Title:
-        SetPageTitleInternal(message.uri, message.title);
-        break;
-      case LazyMessage::Type_Favicon: {
-        // Favicons cannot use async channels after shutdown.
-        if (aIsShutdown)
-          continue;
-        nsFaviconService* faviconService = nsFaviconService::GetFaviconService();
-        if (faviconService) {
-          faviconService->DoSetAndLoadFaviconForPage(message.uri,
-                                                     message.favicon,
-                                                     message.alwaysLoadFavicon,
-                                                     message.callback);
-        }
-        break;
-      }
-      default:
-        NS_NOTREACHED("Invalid lazy message type");
-    }
-  }
-  mLazyMessages.Clear();
-}
-#endif // LAZY_ADD
-
 
 // Query stuff *****************************************************************
 
 // Helper class for QueryToSelectClause
 //
 // This class helps to build part of the WHERE clause. It supports 
 // multiple queries by appending the query index to the parameter name. 
 // For the query with index 0 the parameter name is not altered what
--- a/toolkit/components/places/src/nsNavHistory.h
+++ b/toolkit/components/places/src/nsNavHistory.h
@@ -65,19 +65,16 @@
 #include "nsINavBookmarksService.h"
 #include "nsIPrivateBrowsingService.h"
 #include "nsIFaviconService.h"
 #include "nsNavHistoryResult.h"
 #include "nsNavHistoryQuery.h"
 
 #include "mozilla/storage.h"
 
-// define to enable lazy link adding
-#define LAZY_ADD
-
 #define QUERYUPDATE_TIME 0
 #define QUERYUPDATE_SIMPLE 1
 #define QUERYUPDATE_COMPLEX 2
 #define QUERYUPDATE_COMPLEX_WITH_BOOKMARKS 3
 #define QUERYUPDATE_HOST 4
 
 // This magic number specified an uninitialized value for the
 // mInPrivateBrowsing member
@@ -188,27 +185,16 @@ public:
       nsCOMPtr<nsINavHistoryService> serv =
         do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
       NS_ENSURE_TRUE(serv, nsnull);
       NS_ASSERTION(gHistoryService, "Should have static instance pointer now");
     }
     return gHistoryService;
   }
 
-#ifdef LAZY_ADD
-  /**
-   * Adds a lazy message for adding a favicon. Used by the favicon service so
-   * that favicons are handled lazily just like page adds.
-   */
-  nsresult AddLazyLoadFaviconMessage(nsIURI* aPageURI,
-                                     nsIURI* aFaviconURI,
-                                     PRBool aForceReload,
-                                     nsIFaviconDataCallback* aCallback);
-#endif
-
   /**
    * Returns the database ID for the given URI, or 0 if not found and autoCreate
    * is false.
    */
   nsresult GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
                        PRBool aAutoCreate);
 
   nsresult CalculateFullVisitCount(PRInt64 aPlaceId, PRInt32 *aVisitCount);
@@ -615,69 +601,16 @@ protected:
   PRTime GetNow();
   PRTime mCachedNow;
   nsCOMPtr<nsITimer> mExpireNowTimer;
   /**
    * Called when the cached now value is expired and needs renewal.
    */
   static void expireNowTimerCallback(nsITimer* aTimer, void* aClosure);
 
-#ifdef LAZY_ADD
-  // lazy add committing
-  struct LazyMessage {
-    enum MessageType { Type_Invalid, Type_AddURI, Type_Title, Type_Favicon };
-    LazyMessage()
-    {
-      type = Type_Invalid;
-      isRedirect = PR_FALSE;
-      isToplevel = PR_FALSE;
-      time = 0;
-      alwaysLoadFavicon = PR_FALSE;
-    }
-
-    // call this with common parms to initialize. Caller is responsible for
-    // setting other elements manually depending on type.
-    nsresult Init(MessageType aType, nsIURI* aURI)
-    {
-      NS_ENSURE_ARG_POINTER(aURI);
-      type = aType;
-      nsresult rv = aURI->Clone(getter_AddRefs(uri));
-      NS_ENSURE_SUCCESS(rv, rv);
-      return uri->GetSpec(uriSpec);
-    }
-
-    // common elements
-    MessageType type;
-    nsCOMPtr<nsIURI> uri;
-    nsCString uriSpec; // stringified version of URI, for quick isVisited
-
-    // valid when type == Type_AddURI
-    nsCOMPtr<nsIURI> referrer;
-    PRBool isRedirect;
-    PRBool isToplevel;
-    PRTime time;
-
-    // valid when type == Type_Title
-    nsString title;
-
-    // valid when type == LAZY_FAVICON
-    nsCOMPtr<nsIURI> favicon;
-    PRBool alwaysLoadFavicon;
-    nsCOMPtr<nsIFaviconDataCallback> callback;
-  };
-  nsTArray<LazyMessage> mLazyMessages;
-  nsCOMPtr<nsITimer> mLazyTimer;
-  PRBool mLazyTimerSet;
-  PRUint32 mLazyTimerDeferments; // see StartLazyTimer
-  nsresult StartLazyTimer();
-  nsresult AddLazyMessage(const LazyMessage& aMessage);
-  static void LazyTimerCallback(nsITimer* aTimer, void* aClosure);
-  void CommitLazyMessages(PRBool aIsShutdown = PR_FALSE);
-#endif
-
   nsresult ConstructQueryString(const nsCOMArray<nsNavHistoryQuery>& aQueries, 
                                 nsNavHistoryQueryOptions* aOptions,
                                 nsCString& queryString,
                                 PRBool& aParamsPresent,
                                 StringHash& aAddParams);
 
   nsresult QueryToSelectClause(nsNavHistoryQuery* aQuery,
                                nsNavHistoryQueryOptions* aOptions,
--- a/toolkit/components/places/tests/browser/browser_bug399606.js
+++ b/toolkit/components/places/tests/browser/browser_bug399606.js
@@ -33,20 +33,20 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  * 
  * ***** END LICENSE BLOCK ***** */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
+gBrowser.selectedTab = gBrowser.addTab();
+
 function test() {
-  // Due to LAZY_ADD this is an async test.
   waitForExplicitFinish();
-  const LAZY_ADD_TIMER = 3000;
 
   var URIs = [
     "http://example.com/tests/toolkit/components/places/tests/browser/399606-window.location.href.html",
     "http://example.com/tests/toolkit/components/places/tests/browser/399606-history.go-0.html",
     "http://example.com/tests/toolkit/components/places/tests/browser/399606-location.replace.html",
     "http://example.com/tests/toolkit/components/places/tests/browser/399606-location.reload.html",
     "http://example.com/tests/toolkit/components/places/tests/browser/399606-httprefresh.html",
     "http://example.com/tests/toolkit/components/places/tests/browser/399606-window.location.html",
@@ -72,24 +72,40 @@ function test() {
     onDeleteURI: function(aURI) {},
     onClearHistory: function() {},
     onPageChanged: function(aURI, aWhat, aValue) {},
     onDeleteVisits: function() {},
     QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
   };
   hs.addObserver(historyObserver, false);
 
+  /**
+   * Clears history invoking callback when done.
+   */
+  function waitForClearHistory(aCallback)
+  {
+    let observer = {
+      observe: function(aSubject, aTopic, aData)
+      {
+        Services.obs.removeObserver(this, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
+        aCallback(aSubject, aTopic, aData);
+      }
+    };
+    Services.obs.addObserver(observer, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
+    PlacesUtils.bhistory.removeAllPages();
+  }
+
   function confirm_results() {
+    gBrowser.removeCurrentTab();
     hs.removeObserver(historyObserver, false);
     for (let aURI in historyObserver.visitCount) {
       is(historyObserver.visitCount[aURI], 1,
          "onVisit has been received right number of times for " + aURI);
     }
-    hs.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
-    finish();
+    waitForClearHistory(finish);
   }
 
   var loadCount = 0;
   function handleLoad(aEvent) {
     loadCount++;
     info("new load count is " + loadCount);
 
     if (loadCount == 3) {
@@ -102,13 +118,13 @@ function test() {
   function check_next_uri() {
     if (URIs.length) {
       let uri = URIs.shift();
       loadCount = 0;
       gBrowser.addEventListener("DOMContentLoaded", handleLoad, true);
       content.location.href = uri;
     }
     else {
-      setTimeout(confirm_results, LAZY_ADD_TIMER * 2.5);
+      confirm_results();
     }
   }
   executeSoon(check_next_uri);
 }
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -282,56 +282,28 @@ function check_no_bookmarks() {
   root.containerOpen = true;
   do_check_eq(root.childCount, 0);
   root.containerOpen = false;
 }
 
 
 
 /**
- * Sets title synchronously for a page in moz_places synchronously.
- * History.SetPageTitle uses LAZY_ADD so we can't rely on it.
+ * Sets title synchronously for a page in moz_places.
  *
  * @param aURI
  *        An nsIURI to set the title for.
  * @param aTitle
  *        The title to set the page to.
  * @throws if the page is not found in the database.
  *
- * @note this function only exists because we have no API to do this. It should
- *       be added in bug 421897.
+ * @note This is just a test compatibility mock.
  */
 function setPageTitle(aURI, aTitle) {
-  // Check that the page exists.
-  let stmt = DBConn().createStatement(
-    "SELECT id FROM moz_places_view WHERE url = :url"
-  );
-  stmt.params.url = aURI.spec;
-  try {
-    if (!stmt.executeStep()) {
-      do_throw("Unable to find page " + aURI.spec);
-      return;
-    }
-  }
-  finally {
-    stmt.finalize();
-  }
-
-  // Update the title
-  stmt = DBConn().createStatement(
-    "UPDATE moz_places_view SET title = :title WHERE url = :url"
-  );
-  stmt.params.title = aTitle;
-  stmt.params.url = aURI.spec;
-  try {
-    stmt.execute();
-  }
-  finally {
-    stmt.finalize();
-  }
+  PlacesUtils.history.setPageTitle(aURI, aTitle);
 }
 
 
 /**
  * Clears history invoking callback when done.
  *
  * @param aCallback
  *        Callback function to be called once clear history has finished.
--- a/toolkit/components/places/tests/mochitest/bug_411966/redirect.js
+++ b/toolkit/components/places/tests/mochitest/bug_411966/redirect.js
@@ -151,23 +151,16 @@ StreamListener.prototype = {
 };
 
 // Check Callback.
 function checkDB(data){
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   var referrer = this.mChannel.QueryInterface(Ci.nsIHttpChannel).referrer;
   ghist.addURI(this.mChannel.URI, true, true, referrer);
 
-  // We have to wait since we use lazy_add, lazy_timer is 3s
-  setTimeout("checkDBOnTimeout()", 4000);
-}
-
-function checkDBOnTimeout() {
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-
   // Get all pages visited from the original typed one
   var sql = "SELECT url FROM moz_historyvisits_view " +
             "JOIN moz_places_view h ON h.id = place_id " +
             "WHERE from_visit IN " +
               "(SELECT v.id FROM moz_historyvisits_view v " +
               "JOIN moz_places_view p ON p.id = v.place_id " +
               "WHERE p.url = ?1)";
   var stmt = mDBConn.createStatement(sql);
--- a/toolkit/components/places/tests/mochitest/test_bug_461710.html
+++ b/toolkit/components/places/tests/mochitest/test_bug_461710.html
@@ -14,22 +14,26 @@ https://bugzilla.mozilla.org/show_bug.cg
 <p id="display"></p>
 <iframe id="iframe"></iframe>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 461710 **/
 
 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+SimpleTest.waitForExplicitFinish();
+
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cr = Components.results;
-Components.utils.import("resource://gre/modules/NetUtil.jsm");
 
-const LAZY_ADD_TIMER = 3000;
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+var gIframe = document.getElementById("iframe");
 
 /**
  * Helper function which waits until another function returns true, and
  * then notifies a callback.
  *
  * Original function stolen from docshell/test/chrome/docshell_helpers.js.
  *
  * Parameters:
@@ -63,23 +67,22 @@ var testpath = document.location.pathnam
 var prefix = "http://mochi.test:8888" + testpath;
 var subtests = [
                    "visited_page.html",   // 1
                    "link_page.html",      // 2
                    "link_page-2.html",    // 3
                    "link_page-3.html"     // 4
                ];
 
-
 var testNum = 0;
 function loadNextTest() {
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
   // run the initialization code for each test
-  switch (++ testNum) {
+  switch (++testNum) {
     case 1:
       // nothing to do here
       break;
 
     case 2:
       ok(!pb.privateBrowsingEnabled, "Test #" + testNum + " should be run outside of private mode");
       break;
 
@@ -92,29 +95,28 @@ function loadNextTest() {
       pb.privateBrowsingEnabled = false;
       ok(!pb.privateBrowsingEnabled, "Test #" + testNum + " should be run outside of private mode");
       break;
 
     default:
       ok(false, "Unexpected call to loadNextTest for test #" + testNum);
   }
 
-  if (testNum == 1) {
-    // Because of LAZY_ADD, the page won't be marked as visited until three seconds,
-    // so wait for four seconds to be safe
-    setTimeout(handleLoad, LAZY_ADD_TIMER * 2);
-  } else {
+  if (testNum == 1)
+    observer.expectURL(prefix + subtests[0], "uri-visit-saved");
+  else
     observer.expectURL(prefix + subtests[0]);
-    waitForTrue(function() observer.resolved, function() {
-      // And the nodes get notified after the "link-visited" topic, so
-      // we need to execute soon...
-      SimpleTest.executeSoon(handleLoad);
-    });
-  }
-  iframe.src = prefix + subtests[testNum-1];
+
+  waitForTrue(function() observer.resolved, function() {
+    // And the nodes get notified after the "link-visited" topic, so
+    // we need to execute soon...
+    SimpleTest.executeSoon(handleLoad);
+  });
+
+  gIframe.src = prefix + subtests[testNum-1];
 }
 
 function getColor(doc, win, id) {
   var elem = doc.getElementById(id);
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
                 getInterface(Components.interfaces.nsIDOMWindowUtils);
   return utils.getVisitedDependentComputedStyle(elem, "", "color");
@@ -123,31 +125,31 @@ function getColor(doc, win, id) {
 function checkTest() {
   switch (testNum) {
     case 1:
       // nothing to do here, we just want to mark the page as visited
       break;
 
     case 2:
       // run outside of private mode, link should appear as visited
-      var doc = iframe.contentDocument;
+      var doc = gIframe.contentDocument;
       var win = doc.defaultView;
       is(getColor(doc, win, "link"), kRed, "Visited link coloring should work outside of private mode");
       break;
 
     case 3:
       // run inside of private mode, link should appear as not visited
-      var doc = iframe.contentDocument;
+      var doc = gIframe.contentDocument;
       var win = doc.defaultView;
       is(getColor(doc, win, "link"), kBlue, "Visited link coloring should not work inside of private mode");
       break;
 
     case 4:
       // run outside of private mode, link should appear as visited
-      var doc = iframe.contentDocument;
+      var doc = gIframe.contentDocument;
       var win = doc.defaultView;
       is(getColor(doc, win, "link"), kRed, "Visited link coloring should work outside of private mode");
       break;
 
     default:
       ok(false, "Unexpected call to checkTest for test #" + testNum);
   }
 }
@@ -171,64 +173,53 @@ function get_PBSvc() {
 function handleLoad() {
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
   checkTest();
 
   if (testNum < subtests.length) {
     loadNextTest();
   } else {
-    prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
+    try {
+      Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session");
+    } catch(ex) {}
     SimpleTest.finish();
   }
 }
 
 const URI_VISITED_RESOLUTION_TOPIC = "visited-status-resolution";
-var os, observer = {
+var observer = {
   uri: null,
   resolved: true,
   observe: function (aSubject, aTopic, aData) {
-    SimpleTest.is(aTopic, URI_VISITED_RESOLUTION_TOPIC, "Unexpected topic");
-
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
     if (this.uri.equals(aSubject.QueryInterface(Ci.nsIURI))) {
       this.resolved = true;
 
-      os.removeObserver(this, URI_VISITED_RESOLUTION_TOPIC);
+      Services.obs.removeObserver(this, aTopic);
     }
   },
-  expectURL: function (url) {
+  expectURL: function (url, aOverrideTopic) {
     ok(this.resolved, "Can't set the expected URL when another is yet to be resolved");
     this.resolved = false;
 
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
 
     this.uri = NetUtil.newURI(url);
-    os.addObserver(this, URI_VISITED_RESOLUTION_TOPIC, false);
+    var topic = aOverrideTopic || URI_VISITED_RESOLUTION_TOPIC;
+    Services.obs.addObserver(this, topic, false);
   }
 };
 
 var pb = get_PBSvc();
 if (!pb) { // Private Browsing might not be available
   ok(true, "Private Browsing is not available");
   SimpleTest.finish();
 } else {
-  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
-
-  var prefBranch = Cc["@mozilla.org/preferences-service;1"].
-                   getService(Ci.nsIPrefBranch);
-  prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
-
-  os = Cc["@mozilla.org/observer-service;1"].
-           getService(Ci.nsIObserverService);
-
-  var iframe = document.getElementById("iframe");
-
-  SimpleTest.waitForExplicitFinish();
-
+  Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
   loadNextTest();
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/places/tests/network/test_history_redirects.js
+++ b/toolkit/components/places/tests/network/test_history_redirects.js
@@ -210,20 +210,16 @@ ChannelListener.prototype = {
     do_check_true(this._got_onstartrequest);
     do_check_true(this._got_onchannelredirect);
     do_check_true(this._buffer.length > 0);
 
     // The referrer is wrong since it's the first element in the redirects
     // chain, but this is good, since it will test a special path.
     ghist3.addURI(uri(FOUND_URL), false, true, uri(PERMA_REDIR_URL));
 
-    // This forces a CommitLazyMessages, so we don't have to wait for LAZY_ADD.
-    // Actually trying to delete visits in future.
-    hs.removeVisitsByTimeframe((Date.now() * 1000) + 1, (Date.now() * 1000) + 2);
-
     continue_test();
   },
 
   // nsIChannelEventSink
   onChannelRedirect: function (aOldChannel, aNewChannel, aFlags) {
     print("onChannelRedirect");
     this._got_onchannelredirect = true;
     ghist3.addDocumentRedirect(aOldChannel, aNewChannel, aFlags, true);
--- a/toolkit/components/places/tests/unit/test_404630.js
+++ b/toolkit/components/places/tests/unit/test_404630.js
@@ -31,30 +31,41 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-// Get favicon service
-try {
-  var faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
-                       getService(Ci.nsIFaviconService);
-} catch(ex) {
-  do_throw("Could not get favicon service\n");
-} 
+function run_test() {
+  do_test_pending();
 
-// main
-function run_test() {
+  let exceptionCaught = false;
+  try {
+    PlacesUtils.favicons.setAndLoadFaviconForPage(
+      null, uri("http://www.mozilla.com/favicon.ico"), false
+    );
+  } catch (ex) {
+    exceptionCaught = true;
+  }
+  do_check_true(exceptionCaught, "should throw because page param is null");
+
+  exceptionCaught = false;
   try {
-    faviconService.setAndLoadFaviconForPage(null, uri("http://www.mozilla.com/favicon.ico"), false);
-    do_throw("should throw because page param is null");
-  } catch (ex) {}
+    PlacesUtils.favicons.setAndLoadFaviconForPage(
+      uri("http://www.mozilla.com"), null, false
+    );
+    do_throw("should throw because favicon param is null");
+  } catch (ex) {
+    exceptionCaught = true;
+  }
+  do_check_true(exceptionCaught, "should throw because page param is null");
 
-  try {
-    faviconService.setAndLoadFaviconForPage(uri("http://www.mozilla.com"), null, false);
-    do_throw("should throw because favicon param is null");
-  } catch (ex) {}
+  PlacesUtils.favicons.setAndLoadFaviconForPage(
+    uri("http://www.google.com"), uri("http://www.google.com/favicon.ico"),
+    false, continue_test
+  );
+}
 
-  faviconService.setAndLoadFaviconForPage(uri("http://www.google.com"), uri("http://www.google.com/favicon.ico"), false);
+function continue_test(aFaviconData) {
+  do_test_finished();
 }
--- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
+++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
@@ -35,26 +35,22 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Tests for nsIFaviconService::SetAndLoadFaviconForPage()
  */
 
-var iconsvc = Cc["@mozilla.org/browser/favicon-service;1"].
-              getService(Ci.nsIFaviconService);
+var iconsvc = PlacesUtils.favicons;
 
 function addBookmark(aURI) {
-  var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-              getService(Ci.nsINavBookmarksService);
-  return bmsvc.insertBookmark(bmsvc.unfiledBookmarksFolder,
-                              aURI,
-                              bmsvc.DEFAULT_INDEX,
-                              aURI.spec);
+  var bs = PlacesUtils.bookmarks;
+  return bs.insertBookmark(bs.unfiledBookmarksFolder, aURI,
+                           bs.DEFAULT_INDEX, aURI.spec);
 }
 
 function checkAddSucceeded(pageURI, mimetype, data) {
   var savedFaviconURI = iconsvc.getFaviconForPage(pageURI);
   var outMimeType = {};
   var outData = iconsvc.getFaviconData(savedFaviconURI, outMimeType, {});
 
   // Ensure input and output are identical
@@ -189,15 +185,13 @@ var historyObserver = {
 
 var currentTestIndex = 0;
 function run_test() {
   do_test_pending();
 
   // check that the favicon loaded correctly
   do_check_eq(favicons[0].data.length, 344);
 
-  var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
-           getService(Ci.nsINavHistoryService);
-  hs.addObserver(historyObserver, false);
+  PlacesUtils.history.addObserver(historyObserver, false);
 
   // Start the tests
   tests[currentTestIndex].go();
 };
--- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js
+++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage_failures.js
@@ -39,28 +39,19 @@
 /*
  * Tests failing cases of setAndLoadFaviconForPage
  */
 
 const PB_KEEP_SESSION_PREF = "browser.privatebrowsing.keep_current_session";
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyServiceGetter(this, "iconsvc",
-                                   "@mozilla.org/browser/favicon-service;1",
-                                   "nsIFaviconService");
-XPCOMUtils.defineLazyServiceGetter(this, "hs",
-                                   "@mozilla.org/browser/nav-history-service;1",
-                                   "nsINavHistoryService");
 XPCOMUtils.defineLazyServiceGetter(this, "pb",
                                    "@mozilla.org/privatebrowsing;1",
                                    "nsIPrivateBrowsingService");
-XPCOMUtils.defineLazyServiceGetter(this, "prefs",
-                                   "@mozilla.org/preferences-service;1",
-                                   "nsIPrefBranch");
 
 let favicons = [
   {
     uri: uri(do_get_file("favicon-normal16.png")),
     data: readFileData(do_get_file("favicon-normal16.png")),
     mimetype: "image/png",
     size: 286
   },
@@ -74,63 +65,63 @@ let favicons = [
 
 let tests = [
 
   {
     desc: "test setAndLoadFaviconForPage for about: URIs",
     pageURI: uri("about:test1"),
     go: function go1() {
 
-      iconsvc.setAndLoadFaviconForPage(this.pageURI, favicons[0].uri, true);
+      PlacesUtils.favicons.setAndLoadFaviconForPage(this.pageURI, favicons[0].uri, true);
     },
     clean: function clean1() {}
   },
 
   {
     desc: "test setAndLoadFaviconForPage with history disabled",
     pageURI: uri("http://test2.bar/"),
     go: function go2() {
       // Temporarily disable history.
-      prefs.setBoolPref("places.history.enabled", false);
+      Services.prefs.setBoolPref("places.history.enabled", false);
 
-      iconsvc.setAndLoadFaviconForPage(this.pageURI, favicons[0].uri, true);
+      PlacesUtils.favicons.setAndLoadFaviconForPage(this.pageURI, favicons[0].uri, true);
     },
     clean: function clean2() {
       try {
-        prefs.clearUserPref("places.history.enabled");
+        Services.prefs.clearUserPref("places.history.enabled");
       } catch (ex) {}
     }
   },
 
   {
     desc: "test setAndLoadFaviconForPage in PB mode for non-bookmarked URI",
     pageURI: uri("http://test3.bar/"),
     go: function go3() {
       if (!("@mozilla.org/privatebrowsing;1" in Cc))
         return;
 
       // Enable PB mode.
-      prefs.setBoolPref(PB_KEEP_SESSION_PREF, true);
+      Services.prefs.setBoolPref(PB_KEEP_SESSION_PREF, true);
       pb.privateBrowsingEnabled = true;
 
-      iconsvc.setAndLoadFaviconForPage(this.pageURI, favicons[0].uri, true);
+      PlacesUtils.favicons.setAndLoadFaviconForPage(this.pageURI, favicons[0].uri, true);
     },
     clean: function clean3() {
       if (!("@mozilla.org/privatebrowsing;1" in Cc))
         return;
 
       pb.privateBrowsingEnabled = false;
     }
   },
 
   { // This is a valid icon set test, that will cause the closing notification.
     desc: "test setAndLoadFaviconForPage for valid history uri",
     pageURI: uri("http://test4.bar/"),
     go: function go4() {
-      iconsvc.setAndLoadFaviconForPage(this.pageURI, favicons[1].uri, true);
+      PlacesUtils.favicons.setAndLoadFaviconForPage(this.pageURI, favicons[1].uri, true);
     },
     clean: function clean4() {}
   },
 
 ];
 
 let historyObserver = {
   onBeginUpdateBatch: function() {},
@@ -149,17 +140,17 @@ let historyObserver = {
     // dump tables, useful if the test fails.
     dump_table("moz_places_temp");
     dump_table("moz_favicons");
 
     // Ensure we have been called by the last test.
     do_check_true(pageURI.equals(uri("http://test4.bar/")));
 
     // Ensure there is only one entry in favicons table.
-    let stmt = PlacesServices.DBConn.createStatement(
+    let stmt = DBConn().createStatement(
       "SELECT url FROM moz_favicons"
     );
     let c = 0;
     try {
       while (stmt.executeStep()) {
         do_check_eq(stmt.row.url, favicons[1].uri.spec);
         c++;
       }
@@ -173,30 +164,24 @@ let historyObserver = {
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
 };
 
 let currentTest = null;
 
 function run_test() {
-  // Disabled till LAZY_ADD is killed, this test should be fixed, since the
-  // below timeout is clearly wrong due to 3s lazy timer.  But fixing it right
-  // now would mean making it take about 12s to run.  This is not acceptable.
-  // See bug 555519.
-  return;
-
   do_test_pending();
 
   // check that the favicon loaded correctly
   do_check_eq(favicons[0].data.length, favicons[0].size);
   do_check_eq(favicons[1].data.length, favicons[1].size);
 
   // Observe history for onPageChanged notification.
-  hs.addObserver(historyObserver, false);
+  PlacesUtils.history.addObserver(historyObserver, false);
 
   // We run all the tests, then we wait for an onPageChanged notification,
   // ideally only the last test is successful, so it should be the only
   // notification we get.  Once we get it, test finishes.
   runNextTest();
 };
 
 function runNextTest() {