Bug 607117 - create GUIDs for all bookmark and history items automatically
authorShawn Wilsher <me@shawnwilsher.com>
Thu, 02 Dec 2010 14:09:52 -0800
changeset 59375 790de2a5e9f55225e3c7968eab2cd36a6ab1a6d8
parent 59374 d52263688514eaab1738adc4b63089e1db48f0d1
child 59376 b44a01549b605cffa8eab154b54a2972ed6c872c
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
bugs607117
milestone2.0b8pre
Bug 607117 - create GUIDs for all bookmark and history items automatically Part 2 - Make entries in moz_places generate guids automagically r=mak
toolkit/components/places/src/AsyncFaviconHelpers.cpp
toolkit/components/places/src/History.cpp
toolkit/components/places/src/SQLFunctions.cpp
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/places/tests/cpp/places_test_harness.h
toolkit/components/places/tests/cpp/places_test_harness_tail.h
toolkit/components/places/tests/cpp/test_IHistory.cpp
toolkit/components/places/tests/head_common.js
toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
toolkit/components/places/tests/unit/test_favicons.js
toolkit/components/places/tests/unit/test_history.js
toolkit/components/places/tests/unit/test_isvisited.js
--- a/toolkit/components/places/src/AsyncFaviconHelpers.cpp
+++ b/toolkit/components/places/src/AsyncFaviconHelpers.cpp
@@ -749,18 +749,18 @@ AsyncAssociateIconToPage::Run()
 
     mIcon.status |= ICON_STATUS_SAVED;
   }
 
   // If the page does not have an id, try to insert a new one.
   if (mPage.id == 0) {
     nsCOMPtr<mozIStorageStatement> stmt =
       mFaviconSvc->mSyncStatements.GetCachedStatement(NS_LITERAL_CSTRING(
-        "INSERT INTO moz_places (url, rev_host, favicon_id) "
-        "VALUES (:page_url, :rev_host, :favicon_id) "
+        "INSERT INTO moz_places (url, rev_host, favicon_id, guid) "
+        "VALUES (:page_url, :rev_host, :favicon_id, GENERATE_GUID()) "
       ));
     NS_ENSURE_STATE(stmt);
     mozStorageStatementScoper scoper(stmt);
     rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mPage.spec);
     NS_ENSURE_SUCCESS(rv, rv);
     // The rev_host can be null.
     if (mPage.revHost.IsEmpty()) {
       rv = stmt->BindNullByName(NS_LITERAL_CSTRING("rev_host"));
--- a/toolkit/components/places/src/History.cpp
+++ b/toolkit/components/places/src/History.cpp
@@ -11,17 +11,17 @@
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is Places code.
  *
  * The Initial Developer of the Original Code is
- * Mozilla Foundation.
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -348,18 +348,18 @@ public:
       NS_ENSURE_SUCCESS(rv, rv);
     }
     // Otherwise, the page was not in moz_places, so now we have to add it.
     else {
       NS_ASSERTION(mPlace.placeId == 0, "should not have a valid place id!");
 
       stmt = mHistory->syncStatements.GetCachedStatement(
           "INSERT INTO moz_places "
-            "(url, rev_host, hidden, typed) "
-          "VALUES (:page_url, :rev_host, :hidden, :typed) "
+            "(url, rev_host, hidden, typed, guid) "
+          "VALUES (:page_url, :rev_host, :hidden, :typed, GENERATE_GUID()) "
         );
       NS_ENSURE_STATE(stmt);
 
       rv = stmt->BindStringByName(NS_LITERAL_CSTRING("rev_host"),
                                   mPlace.revHost);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), mPlace.spec);
       NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/places/src/SQLFunctions.cpp
+++ b/toolkit/components/places/src/SQLFunctions.cpp
@@ -10,17 +10,17 @@
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is Places code.
  *
  * The Initial Developer of the Original Code is
- * Mozilla Corporation.
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -43,16 +43,17 @@
 #include "nsEscape.h"
 #include "mozIPlacesAutoComplete.h"
 #include "SQLFunctions.h"
 #include "nsMathUtils.h"
 #include "nsUTF8Utils.h"
 #include "nsINavHistoryService.h"
 #include "nsPrintfCString.h"
 #include "nsNavHistory.h"
+#include "nsIRandomGenerator.h"
 
 using namespace mozilla::storage;
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Anonymous Helpers
 
 namespace {
 
@@ -591,16 +592,23 @@ namespace places {
 
   //////////////////////////////////////////////////////////////////////////////
   //// GenerateGUIDFunction
 
   /* static */
   nsresult
   GenerateGUIDFunction::create(mozIStorageConnection *aDBConn)
   {
+    // We need this service to be initialized on the main thread because it is
+    // not threadsafe.  We are about to use it asynchronously, so initialize it
+    // now.
+    nsCOMPtr<nsIRandomGenerator> rg =
+      do_GetService("@mozilla.org/security/random-generator;1");
+    NS_ENSURE_STATE(rg);
+
     nsCOMPtr<GenerateGUIDFunction> function = new GenerateGUIDFunction();
     nsresult rv = aDBConn->CreateFunction(
       NS_LITERAL_CSTRING("generate_guid"), 0, function
     );
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
   }
--- a/toolkit/components/places/src/nsNavHistory.cpp
+++ b/toolkit/components/places/src/nsNavHistory.cpp
@@ -514,18 +514,18 @@ nsNavHistory::Init()
   NS_ENSURE_TRUE(mRecentTyped.Init(RECENT_EVENTS_INITIAL_CACHE_SIZE),
                  NS_ERROR_OUT_OF_MEMORY);
   NS_ENSURE_TRUE(mRecentLink.Init(RECENT_EVENTS_INITIAL_CACHE_SIZE),
                  NS_ERROR_OUT_OF_MEMORY);
   NS_ENSURE_TRUE(mRecentBookmark.Init(RECENT_EVENTS_INITIAL_CACHE_SIZE),
                  NS_ERROR_OUT_OF_MEMORY);
   NS_ENSURE_TRUE(mRecentRedirects.Init(RECENT_EVENTS_INITIAL_CACHE_SIZE),
                  NS_ERROR_OUT_OF_MEMORY);
-  
-  // Rmbed visits hash table.
+
+  // Embed visits hash table.
   NS_ENSURE_TRUE(mEmbedVisits.Init(EMBED_VISITS_INITIAL_CACHE_SIZE),
                  NS_ERROR_OUT_OF_MEMORY);
 
   /*****************************************************************************
    *** IMPORTANT NOTICE!
    ***
    *** Nothing after these add observer calls should return anything but NS_OK.
    *** If a failure code is returned, this nsNavHistory object will be held onto
@@ -1348,18 +1348,19 @@ nsNavHistory::GetStatement(const nsCOMPt
   ));
 
   // We have both sync and async users, so it could happen that an async
   // statement tries to insert a page when a sync statement just added it.
   // We should ignore the insertion in such a case, the async implementer
   // will fetch the id of the existing entry.
   RETURN_IF_STMT(mDBAddNewPage, NS_LITERAL_CSTRING(
     "INSERT OR IGNORE INTO moz_places "
-      "(url, title, rev_host, hidden, typed, frecency) "
-    "VALUES (:page_url, :page_title, :rev_host, :hidden, :typed, :frecency) "
+      "(url, title, rev_host, hidden, typed, frecency, guid) "
+    "VALUES (:page_url, :page_title, :rev_host, :hidden, :typed, :frecency, "
+             "GENERATE_GUID()) "
   ));
 
   RETURN_IF_STMT(mDBGetTags, NS_LITERAL_CSTRING(
     "/* do not warn (bug 487594) */ "
     "SELECT GROUP_CONCAT(tag_title, ', ') "
     "FROM ( "
       "SELECT t.title AS tag_title "
       "FROM moz_bookmarks b "
@@ -5705,16 +5706,34 @@ nsNavHistory::Observe(nsISupports *aSubj
     // Stop observing preferences changes.
     if (mPrefBranch)
       mPrefBranch->RemoveObserver("", this);
 
     // Finalize all statements.
     nsresult rv = FinalizeInternalStatements();
     NS_ENSURE_SUCCESS(rv, rv);
 
+#ifdef DEBUG
+    { // Sanity check that all places have guids.
+      nsCOMPtr<mozIStorageStatement> stmt;
+      nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
+        "SELECT * "
+        "FROM moz_places "
+        "WHERE guid IS NULL "
+      ), getter_AddRefs(stmt));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      PRBool haveNullGuids;
+      rv = stmt->ExecuteStep(&haveNullGuids);
+      NS_ENSURE_SUCCESS(rv, rv);
+      NS_ASSERTION(!haveNullGuids,
+                   "Someone added a place without adding a GUID!");
+    }
+#endif
+
     // Finally, close the connection.
     nsRefPtr<PlacesEvent> closeListener =
       new PlacesEvent(TOPIC_PLACES_CONNECTION_CLOSED);
     (void)mDBConn->AsyncClose(closeListener);
   }
 
 #ifdef MOZ_XUL
   else if (strcmp(aTopic, TOPIC_AUTOCOMPLETE_FEEDBACK_INCOMING) == 0) {
--- a/toolkit/components/places/tests/cpp/places_test_harness.h
+++ b/toolkit/components/places/tests/cpp/places_test_harness.h
@@ -11,17 +11,17 @@
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is places test code.
  *
  * The Initial Developer of the Original Code is
- * Mozilla Foundation.
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -82,17 +82,17 @@ static size_t gPassedTests = 0;
 #ifdef LINUX
 // XXX Linux opt builds on tinderbox are orange due to linking with stdlib.
 // This is sad and annoying, but it's a workaround that works.
 #define do_check_eq(aExpected, aActual) \
   do_check_true(aExpected == aActual)
 #else
 #include <sstream>
 
-#define do_check_eq(aExpected, aActual) \
+#define do_check_eq(aActual, aExpected) \
   PR_BEGIN_MACRO \
     gTotalTests++; \
     if (aExpected == aActual) { \
       gPassedTests++; \
     } else { \
       std::ostringstream temp; \
       temp << "Expected '" << aExpected << "', got '" << aActual <<"' at "; \
       temp << __FILE__ << ":" << __LINE__ << "!"; \
@@ -140,16 +140,17 @@ addURI(nsIURI* aURI)
 }
 
 struct PlaceRecord
 {
   PRInt64 id;
   PRInt32 hidden;
   PRInt32 typed;
   PRInt32 visitCount;
+  nsCString guid;
 };
 
 struct VisitRecord
 {
   PRInt64 id;
   PRInt64 lastVisitId;
   PRInt32 transitionType;
 };
@@ -196,17 +197,17 @@ do_get_place(nsIURI* aURI, PlaceRecord& 
   nsCOMPtr<mozIStorageConnection> dbConn = do_get_db();
   nsCOMPtr<mozIStorageStatement> stmt;
 
   nsCString spec;
   nsresult rv = aURI->GetSpec(spec);
   do_check_success(rv);
 
   rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
-    "SELECT id, hidden, typed, visit_count FROM moz_places "
+    "SELECT id, hidden, typed, visit_count, guid FROM moz_places "
     "WHERE url=?1 "
   ), getter_AddRefs(stmt));
   do_check_success(rv);
 
   rv = stmt->BindUTF8StringByIndex(0, spec);
   do_check_success(rv);
 
   PRBool hasResults;
@@ -220,16 +221,18 @@ do_get_place(nsIURI* aURI, PlaceRecord& 
   rv = stmt->GetInt64(0, &result.id);
   do_check_success(rv);
   rv = stmt->GetInt32(1, &result.hidden);
   do_check_success(rv);
   rv = stmt->GetInt32(2, &result.typed);
   do_check_success(rv);
   rv = stmt->GetInt32(3, &result.visitCount);
   do_check_success(rv);
+  rv = stmt->GetUTF8String(4, result.guid);
+  do_check_success(rv);
 }
 
 /**
  * Gets the most recent visit to a place.
  *
  * @param placeID ID from the moz_places table
  * @param result Out parameter where visit is stored
  */
--- a/toolkit/components/places/tests/cpp/places_test_harness_tail.h
+++ b/toolkit/components/places/tests/cpp/places_test_harness_tail.h
@@ -11,17 +11,17 @@
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
  * The Original Code is places test code.
  *
  * The Initial Developer of the Original Code is
- * Mozilla Foundation.
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/toolkit/components/places/tests/cpp/test_IHistory.cpp
+++ b/toolkit/components/places/tests/cpp/test_IHistory.cpp
@@ -356,17 +356,17 @@ namespace test_observer_topic_dispatched
       }
 
       // Check that we have either the visited or not visited string.
       bool visited = !!NS_LITERAL_STRING(URI_VISITED).Equals(aData);
       bool notVisited = !!NS_LITERAL_STRING(URI_NOT_VISITED).Equals(aData);
       do_check_true(visited || notVisited);
 
       // Check to make sure we got the state we expected.
-      do_check_eq(mExpectVisit, visited);
+      do_check_eq(visited, mExpectVisit);
 
       // Indicate that we've been notified.
       mNotified = true;
 
       // Remove ourselves as an observer.
       nsCOMPtr<nsIObserverService> observerService =
         do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
       (void)observerService->RemoveObserver(this,
@@ -442,17 +442,17 @@ test_visituri_inserts()
   finisher->WaitForNotification();
 
   PlaceRecord place;
   do_get_place(visitedURI, place);
 
   do_check_true(place.id > 0);
   do_check_false(place.hidden);
   do_check_false(place.typed);
-  do_check_eq(1, place.visitCount);
+  do_check_eq(place.visitCount, 1);
 
   run_next_test();
 }
 
 void
 test_visituri_updates()
 {
   nsCOMPtr<IHistory> history(do_get_IHistory());
@@ -466,17 +466,17 @@ test_visituri_updates()
 
   history->VisitURI(visitedURI, lastURI, mozilla::IHistory::TOP_LEVEL);
   finisher = new VisitURIObserver();
   finisher->WaitForNotification();
 
   PlaceRecord place;
   do_get_place(visitedURI, place);
 
-  do_check_eq(2, place.visitCount);
+  do_check_eq(place.visitCount, 2);
 
   run_next_test();
 }
 
 void
 test_visituri_preserves_shown_and_typed()
 {
   nsCOMPtr<IHistory> history(do_get_IHistory());
@@ -510,18 +510,18 @@ test_visituri_creates_visit()
   finisher->WaitForNotification();
 
   PlaceRecord place;
   VisitRecord visit;
   do_get_place(visitedURI, place);
   do_get_lastVisit(place.id, visit);
 
   do_check_true(visit.id > 0);
-  do_check_eq(0, visit.lastVisitId);
-  do_check_eq(nsINavHistoryService::TRANSITION_LINK, visit.transitionType);
+  do_check_eq(visit.lastVisitId, 0);
+  do_check_eq(visit.transitionType, nsINavHistoryService::TRANSITION_LINK);
 
   run_next_test();
 }
 
 void
 test_visituri_transition_typed()
 {
   nsCOMPtr<nsINavHistoryService> navHistory = do_get_NavHistory();
@@ -564,16 +564,37 @@ test_visituri_transition_embed()
   do_get_lastVisit(place.id, visit);
 
   do_check_eq(place.id, 0);
   do_check_eq(visit.id, 0);
 
   run_next_test();
 }
 
+void
+test_new_visit_adds_place_guid()
+{
+  // First, add a visit and wait.  This will also add a place.
+  nsCOMPtr<nsIURI> visitedURI(new_test_uri());
+  nsCOMPtr<IHistory> history(do_get_IHistory());
+  nsresult rv = history->VisitURI(visitedURI, NULL,
+                                  mozilla::IHistory::TOP_LEVEL);
+  do_check_success(rv);
+  nsCOMPtr<VisitURIObserver> finisher = new VisitURIObserver();
+  finisher->WaitForNotification();
+
+  // Check that we have a guid for our visit.
+  PlaceRecord place;
+  do_get_place(visitedURI, place);
+  do_check_eq(place.visitCount, 1);
+  do_check_eq(place.guid.Length(), 12);
+
+  run_next_test();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 //// IPC-only Tests
 
 #ifdef MOZ_IPC
 void
 test_two_null_links_same_uri()
 {
   // Tests that we do not crash when we have had two NULL Links passed to
@@ -614,16 +635,17 @@ Test gTests[] = {
   TEST(test_RegisterVisitedCallback_returns_before_notifying),
   TEST(test_observer_topic_dispatched),
   TEST(test_visituri_inserts),
   TEST(test_visituri_updates),
   TEST(test_visituri_preserves_shown_and_typed),
   TEST(test_visituri_creates_visit),
   TEST(test_visituri_transition_typed),
   TEST(test_visituri_transition_embed),
+  TEST(test_new_visit_adds_place_guid),
 
   // The rest of these tests are tests that are only run in IPC builds.
 #ifdef MOZ_IPC
   TEST(test_two_null_links_same_uri),
 #endif // MOZ_IPC
 };
 
 const char* file = __FILE__;
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -572,8 +572,27 @@ function waitForAsyncUpdates(aCallback, 
  *
  * @param aGuid
  *        The guid to test.
  */
 function do_check_valid_places_guid(aGuid)
 {
   do_check_true(/^[a-zA-Z0-9\-_]{12}$/.test(aGuid), Components.stack.caller);
 }
+
+/**
+ * Tests that a guid was set in moz_places for a given uri.
+ *
+ * @param aURI
+ *        The uri to check.
+ */
+function do_check_guid_for_uri(aURI)
+{
+  let stmt = DBConn().createStatement(
+    "SELECT guid "
+  + "FROM moz_places "
+  + "WHERE url = :url "
+  );
+  stmt.params.url = aURI.spec;
+  do_check_true(stmt.executeStep());
+  do_check_valid_places_guid(stmt.row.guid);
+  stmt.finalize();
+}
--- a/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
+++ b/toolkit/components/places/tests/unit/test_doSetAndLoadFaviconForPage.js
@@ -51,16 +51,17 @@ function addBookmark(aURI) {
 function checkAddSucceeded(pageURI, mimetype, data) {
   var savedFaviconURI = iconsvc.getFaviconForPage(pageURI);
   var outMimeType = {};
   var outData = iconsvc.getFaviconData(savedFaviconURI, outMimeType, {});
 
   // Ensure input and output are identical
   do_check_eq(mimetype, outMimeType.value);
   do_check_true(compareArrays(data, outData));
+  do_check_guid_for_uri(pageURI);
 }
 
 var favicons = [
   {
     uri: uri(do_get_file("favicon-normal32.png")),
     data: readFileData(do_get_file("favicon-normal32.png")),
     mimetype: "image/png"
   }
--- a/toolkit/components/places/tests/unit/test_favicons.js
+++ b/toolkit/components/places/tests/unit/test_favicons.js
@@ -326,32 +326,35 @@ histsvc.addVisit(page3URI, Date.now() * 
                  histsvc.TRANSITION_TYPED, false, 0);
 
 // set first page icon
 try {
   iconsvc.setFaviconData(icon1URI, icon1Data, icon1Data.length,
                          icon1MimeType, Number.MAX_VALUE);
 } catch (ex) {}
 iconsvc.setFaviconUrlForPage(page1URI, icon1URI);
+do_check_guid_for_uri(page1URI);
 var savedIcon1URI = iconsvc.getFaviconForPage(page1URI);
 
 // set second page icon
 try {
   iconsvc.setFaviconData(icon2URI, icon2Data, icon2Data.length,
                          icon2MimeType, Number.MAX_VALUE);
 } catch (ex) {}
 iconsvc.setFaviconUrlForPage(page2URI, icon2URI);
+do_check_guid_for_uri(page2URI);
 var savedIcon2URI = iconsvc.getFaviconForPage(page2URI);
 
 // set third page icon as the same as first page one
 try {
   iconsvc.setFaviconData(icon1URI, icon1Data, icon1Data.length,
                          icon1MimeType, Number.MAX_VALUE);
 } catch (ex) {}
 iconsvc.setFaviconUrlForPage(page3URI, icon1URI);
+do_check_guid_for_uri(page3URI);
 var savedIcon3URI = iconsvc.getFaviconForPage(page3URI);
 
 // check first page icon
 var out1MimeType = {};
 var out1Data = iconsvc.getFaviconData(savedIcon1URI, out1MimeType);
 do_check_eq(icon1MimeType, out1MimeType.value);
 checkArrays(icon1Data, out1Data);
 
--- a/toolkit/components/places/tests/unit/test_history.js
+++ b/toolkit/components/places/tests/unit/test_history.js
@@ -57,16 +57,17 @@ function add_visit(aURI, aReferrer) {
   var visitId = histsvc.addVisit(aURI,
                                  Date.now() * 1000,
                                  aReferrer,
                                  histsvc.TRANSITION_TYPED, // user typed in URL bar
                                  false, // not redirect
                                  0);
   dump("### Added visit with id of " + visitId + "\n");
   do_check_true(gh.isVisited(aURI));
+  do_check_guid_for_uri(aURI);
   return visitId;
 }
 
 /**
  * Checks to see that a URI is in the database.
  *
  * @param aURI
  *        The URI to check.
--- a/toolkit/components/places/tests/unit/test_isvisited.js
+++ b/toolkit/components/places/tests/unit/test_isvisited.js
@@ -42,22 +42,25 @@
 // Get history service
 try {
   var gh = Cc["@mozilla.org/browser/global-history;2"].
            getService(Ci.nsIGlobalHistory2);
 } catch(ex) {
   do_throw("Could not get the global history service\n");
 } 
 
-function add_uri_to_history(aURI) {
+function add_uri_to_history(aURI, aCheckForGuid) {
   var referrer = uri("about:blank");
   gh.addURI(aURI,
             false, // not redirect
             true, // top level 
             referrer);
+  if (aCheckForGuid === undefined) {
+    do_check_guid_for_uri(aURI);
+  }
 }
 
 // main
 function run_test() {
   // add a http:// uri 
   var uri1 = uri("http://mozilla.com");
   add_uri_to_history(uri1);
   do_check_true(gh.isVisited(uri1));
@@ -97,13 +100,13 @@ function run_test() {
     }
     catch(e) {
       // nsIIOService.newURI() can throw if e.g. our app knows about imap://
       // but the account is not set up and so the URL is invalid for us.
       // Note this in the log but ignore as it's not the subject of this test.
       print("Exception thrown for '" + currentURL + "', ignored.");
     }
     if (cantAddUri) {
-      add_uri_to_history(cantAddUri);
+      add_uri_to_history(cantAddUri, false);
       do_check_false(gh.isVisited(cantAddUri));
     }
   }
 }