Bug 633266 - nsINavHistoryObserver: also pass in GUID whenever we pass in a URI. r=mak
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Wed, 08 Jun 2011 17:10:28 +0200
changeset 70780 78012c46e991066ac09e4d93d6b34916d2a7ab96
parent 70779 e1789ade94d552ffb9a7a190f1dedacb51dec695
child 70781 c8b4de69103695b95a0d32ef741d5a98468a2eff
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmak
bugs633266
milestone7.0a1
Bug 633266 - nsINavHistoryObserver: also pass in GUID whenever we pass in a URI. r=mak Part 1: Tests
toolkit/components/places/tests/head_common.js
toolkit/components/places/tests/unit/test_async_history_api.js
toolkit/components/places/tests/unit/test_history_observer.js
toolkit/components/places/tests/unit/test_onBeforeDeleteURI_observer.js
toolkit/components/places/tests/unit/xpcshell.ini
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -605,40 +605,60 @@ function do_check_valid_places_guid(aGui
 {
   if (!aStack) {
     aStack = Components.stack.caller;
   }
   do_check_true(/^[a-zA-Z0-9\-_]{12}$/.test(aGuid), aStack);
 }
 
 /**
+ * Retrieves the guid for a given uri.
+ *
+ * @param aURI
+ *        The uri to check.
+ * @param [optional] aStack
+ *        The stack frame used to report the error.
+ * @return the associated the guid.
+ */
+function do_get_guid_for_uri(aURI,
+                             aStack)
+{
+  if (!aStack) {
+    aStack = Components.stack.caller;
+  }
+  let stmt = DBConn().createStatement(
+    "SELECT guid "
+  + "FROM moz_places "
+  + "WHERE url = :url "
+  );
+  stmt.params.url = aURI.spec;
+  do_check_true(stmt.executeStep(), aStack);
+  let guid = stmt.row.guid;
+  stmt.finalize();
+  do_check_valid_places_guid(guid, aStack);
+  return guid;
+}
+
+/**
  * Tests that a guid was set in moz_places for a given uri.
  *
  * @param aURI
  *        The uri to check.
  * @param [optional] aGUID
  *        The expected guid in the database.
  */
 function do_check_guid_for_uri(aURI,
                                aGUID)
 {
   let caller = Components.stack.caller;
-  let stmt = DBConn().createStatement(
-    "SELECT guid "
-  + "FROM moz_places "
-  + "WHERE url = :url "
-  );
-  stmt.params.url = aURI.spec;
-  do_check_true(stmt.executeStep(), caller);
-  do_check_valid_places_guid(stmt.row.guid, caller);
+  let guid = do_get_guid_for_uri(aURI, caller);
   if (aGUID) {
     do_check_valid_places_guid(aGUID, caller);
-    do_check_eq(stmt.row.guid, aGUID, caller);
+    do_check_eq(guid, aGUID, caller);
   }
-  stmt.finalize();
 }
 
 /**
  * Logs info to the console in the standard way (includes the filename).
  *
  * @param aMessage
  *        The message to log to the console.
  */
--- a/toolkit/components/places/tests/unit/test_async_history_api.js
+++ b/toolkit/components/places/tests/unit/test_async_history_api.js
@@ -102,34 +102,37 @@ TitleChangedObserver.prototype = {
  *
  * @param aURI
  *        The URI of the page we expect a notification for.
  * @param aCallback
  *        The method to call when we have gotten the proper notification about
  *        being visited.
  */
 function VisitObserver(aURI,
+                       aGUID,
                        aCallback)
 {
   this.uri = aURI;
+  this.guid = aGUID;
   this.callback = aCallback;
 }
 VisitObserver.prototype = {
   __proto__: NavHistoryObserver.prototype,
   onVisit: function(aURI,
                     aVisitId,
                     aTime,
                     aSessionId,
                     aReferringId,
-                    aTransitionType)
+                    aTransitionType,
+                    aGUID)
   {
     do_log_info("onVisit(" + aURI.spec + ", " + aVisitId + ", " + aTime +
                 ", " + aSessionId + ", " + aReferringId + ", " +
-                aTransitionType + ")");
-    if (!this.uri.equals(aURI)) {
+                aTransitionType + ", " + aGUID + ")"); 
+    if (!this.uri.equals(aURI) || this.guid != aGUID) {
       return;
     }
     this.callback(aTime, aTransitionType);
   },
 };
 
 /**
  * Tests that a title was set properly in the database.
@@ -1168,31 +1171,33 @@ function test_title_change_notifies()
   gHistory.updatePlaces(place);
 }
 
 function test_visit_notifies()
 {
   // There are two observers we need to see for each visit.  One is an
   // nsINavHistoryObserver and the other is the uri-visit-saved observer topic.
   let place = {
+    guid: "abcdefghijkl",
     uri: NetUtil.newURI(TEST_DOMAIN + "test_visit_notifies"),
     visits: [
       new VisitInfo(),
     ],
   };
   do_check_false(gGlobalHistory.isVisited(place.uri));
 
   let callbackCount = 0;
   let finisher = function() {
     if (++callbackCount == 2) {
       waitForAsyncUpdates(run_next_test);
     }
   }
-  let visitObserver = new VisitObserver(place.uri, function(aVisitDate,
-                                                            aTransitionType) {
+  let visitObserver = new VisitObserver(place.uri, place.guid,
+                                        function(aVisitDate,
+                                                 aTransitionType) {
     let visit = place.visits[0];
     do_check_eq(visit.visitDate, aVisitDate);
     do_check_eq(visit.transitionType, aTransitionType);
 
     PlacesUtils.history.removeObserver(visitObserver);
     finisher();
   });
   PlacesUtils.history.addObserver(visitObserver, false);
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unit/test_history_observer.js
@@ -0,0 +1,91 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Generic nsINavHistoryObserver that doesn't implement anything, but provides
+ * dummy methods to prevent errors about an object not having a certain method.
+ */
+function NavHistoryObserver() {
+}
+NavHistoryObserver.prototype = {
+  onBeginUpdateBatch: function() { },
+  onEndUpdateBatch: function() { },
+  onVisit: function() { },
+  onTitleChanged: function() { },
+  onBeforeDeleteURI: function() { },
+  onDeleteURI: function() { },
+  onClearHistory: function() { },
+  onPageChanged: function() { },
+  onDeleteVisits: function() { },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavHistoryObserver])
+};
+
+/**
+ * Registers a one-time history observer for and calls the callback
+ * when the specified nsINavHistoryObserver method is called.
+ */
+function onNotify(callback) {
+  let obs = new NavHistoryObserver();
+  obs[callback.name] = function () {
+    PlacesUtils.history.removeObserver(this);
+    callback.apply(this, arguments);
+  };
+  PlacesUtils.history.addObserver(obs, false);
+}
+
+/**
+ * Adds a TRANSITION_TYPED visit to the history database.
+ */
+function add_visit(uri, timestamp) {
+  uri = uri || NetUtil.newURI("http://firefox.com/");
+  timestamp = timestamp || Date.now() * 1000;
+  PlacesUtils.history.addVisit(
+    uri, timestamp, null, Ci.nsINavHistoryService.TRANSITION_TYPED, false, 0);
+  return [uri, timestamp];
+}
+
+function run_test() {
+  run_next_test();
+}
+
+add_test(function test_onVisit() {
+  onNotify(function onVisit(aURI, aVisitID, aTime, aSessionID, aReferringID,
+                            aTransitionType, aGUID) {
+    do_check_true(aURI.equals(testuri));
+    do_check_true(aVisitID > 0);
+    do_check_eq(aTime, testtime);
+    do_check_eq(aSessionID, 0);
+    do_check_eq(aReferringID, 0);
+    do_check_eq(aTransitionType, Ci.nsINavHistoryService.TRANSITION_TYPED);
+    do_check_guid_for_uri(aURI, aGUID);
+
+    run_next_test();
+  });
+  let testuri = NetUtil.newURI("http://firefox.com/");
+  let testtime = Date.now() * 1000;
+  add_visit(testuri, testtime);
+});
+
+add_test(function test_onBeforeDeleteURI() {
+  onNotify(function onBeforeDeleteURI(aURI, aGUID) {
+    do_check_true(aURI.equals(testuri));
+    do_check_guid_for_uri(aURI, aGUID);
+
+    run_next_test();
+  });
+  let [testuri] = add_visit();
+  PlacesUtils.bhistory.removePage(testuri);
+});
+
+add_test(function test_onDeleteURI() {
+  onNotify(function onDeleteURI(aURI, aGUID) {
+    do_check_true(aURI.equals(testuri));
+    // Can't use do_check_guid_for_uri() here because the visit is already gone.
+    do_check_eq(aGUID, testguid);
+
+    run_next_test();
+  });
+  let [testuri] = add_visit();
+  let testguid = do_get_guid_for_uri(testuri);
+  PlacesUtils.bhistory.removePage(testuri);
+});
--- a/toolkit/components/places/tests/unit/test_onBeforeDeleteURI_observer.js
+++ b/toolkit/components/places/tests/unit/test_onBeforeDeleteURI_observer.js
@@ -63,24 +63,27 @@ Observer.prototype =
   },
   onVisit: function(aURI, aVisitID, aTime, aSessionId, aReferringId,
                     aTransitionType, _added)
   {
   },
   onTitleChanged: function(aURI, aPageTable)
   {
   },
-  onBeforeDeleteURI: function(aURI)
+  onBeforeDeleteURI: function(aURI, aGUID)
   {
     this.removedURI = aURI;
+    this.removedGUID = aGUID;
+    do_check_guid_for_uri(aURI, aGUID);
   },
-  onDeleteURI: function(aURI)
+  onDeleteURI: function(aURI, aGUID)
   {
     do_check_false(this.checked);
     do_check_true(this.removedURI.equals(aURI));
+    do_check_eq(this.removedGUID, aGUID);
     this.checked = true;
   },
   onPageChanged: function(aURI, aWhat, aValue)
   {
   },
   onDeleteVisits: function()
   {
   },
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -59,16 +59,17 @@ tail =
 [test_favicons.js]
 [test_frecency.js]
 [test_getChildIndex.js]
 [test_history.js]
 [test_history_autocomplete_tags.js]
 [test_history_catobs.js]
 [test_history_import.js]
 [test_history_notifications.js]
+[test_history_observer.js]
 [test_history_removeAllPages.js]
 [test_history_sidebar.js]
 [test_isvisited.js]
 [test_lastModified.js]
 [test_livemarkService_getLivemarkIdForFeedURI.js]
 [test_markpageas.js]
 [test_migrateFrecency.js]
 [test_moz-anno_favicon_mime_type.js]