Bug 1282770 - Convert uses of PU.asyncHistory.updatePlaces in browser/components/migration to PU.history.insertMany. r=mak
authorGanesh Chaitanya Kale <ganesh2583@gmail.com>
Tue, 20 Mar 2018 12:36:31 +0000
changeset 409577 82e4db446286ad1a387bc7ee3feeeadbaa9d0887
parent 409576 bcd284a1f312f79c4d3866975a6fcaaf17006664
child 409578 426e9698be8dd576382c04ffeed489ba3cf4e1df
push id101247
push usernerli@mozilla.com
push dateThu, 22 Mar 2018 23:00:51 +0000
treeherdermozilla-inbound@02e384bdf97d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak
bugs1282770
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1282770 - Convert uses of PU.asyncHistory.updatePlaces in browser/components/migration to PU.history.insertMany. r=mak Patch originally by Ganesh, updated by Standard8 MozReview-Commit-ID: AihTLo5OyK1
browser/components/migration/AutoMigrate.jsm
browser/components/migration/ChromeProfileMigrator.js
browser/components/migration/EdgeProfileMigrator.js
browser/components/migration/IEProfileMigrator.js
browser/components/migration/MigrationUtils.jsm
browser/components/migration/SafariProfileMigrator.js
browser/components/migration/tests/unit/test_automigration.js
--- a/browser/components/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -605,27 +605,29 @@ const AutoMigrate = {
             this._errorMap.logins++;
           }
         }
       }
     }
   },
 
   async _removeSomeVisits(visits) {
+    // It is necessary to recreate URL and date objects because the data
+    // can be serialized through JSON that destroys those objects.
     for (let urlVisits of visits) {
       let urlObj;
       try {
         urlObj = new URL(urlVisits.url);
       } catch (ex) {
         continue;
       }
       let visitData = {
         url: urlObj,
-        beginDate: PlacesUtils.toDate(urlVisits.first),
-        endDate: PlacesUtils.toDate(urlVisits.last),
+        beginDate: new Date(urlVisits.first),
+        endDate: new Date(urlVisits.last),
         limit: urlVisits.visitCount,
       };
       try {
         await PlacesUtils.history.removeVisitsByFilter(visitData);
       } catch (ex) {
         this._errorMap.visits++;
         try {
           visitData.url = visitData.url.href;
--- a/browser/components/migration/ChromeProfileMigrator.js
+++ b/browser/components/migration/ChromeProfileMigrator.js
@@ -268,53 +268,39 @@ async function GetHistoryResource(aProfi
           query += " AND last_visit_time > " + maxAge;
         }
         if (LIMIT) {
           query += " ORDER BY last_visit_time DESC LIMIT " + LIMIT;
         }
 
         let rows =
           await MigrationUtils.getRowsFromDBWithoutLocks(historyPath, "Chrome history", query);
-        let places = [];
+        let pageInfos = [];
         for (let row of rows) {
           try {
             // if having typed_count, we changes transition type to typed.
-            let transType = PlacesUtils.history.TRANSITION_LINK;
+            let transition = PlacesUtils.history.TRANSITIONS.LINK;
             if (row.getResultByName("typed_count") > 0)
-              transType = PlacesUtils.history.TRANSITION_TYPED;
+              transition = PlacesUtils.history.TRANSITIONS.TYPED;
 
-            places.push({
-              uri: NetUtil.newURI(row.getResultByName("url")),
+            pageInfos.push({
               title: row.getResultByName("title"),
+              url: new URL(row.getResultByName("url")),
               visits: [{
-                transitionType: transType,
-                visitDate: chromeTimeToDate(
-                             row.getResultByName(
-                               "last_visit_time")) * 1000,
+                transition,
+                date: chromeTimeToDate(row.getResultByName("last_visit_time")),
               }],
             });
           } catch (e) {
             Cu.reportError(e);
           }
         }
 
-        if (places.length > 0) {
-          await new Promise((resolve, reject) => {
-            MigrationUtils.insertVisitsWrapper(places, {
-              ignoreErrors: true,
-              ignoreResults: true,
-              handleCompletion(updatedCount) {
-                if (updatedCount > 0) {
-                  resolve();
-                } else {
-                  reject(new Error("Couldn't add visits"));
-                }
-              },
-            });
-          });
+        if (pageInfos.length > 0) {
+          await MigrationUtils.insertVisitsWrapper(pageInfos);
         }
       })().then(() => { aCallback(true); },
               ex => {
                 Cu.reportError(ex);
                 aCallback(false);
               });
     },
   };
--- a/browser/components/migration/EdgeProfileMigrator.js
+++ b/browser/components/migration/EdgeProfileMigrator.js
@@ -104,52 +104,46 @@ EdgeTypedURLMigrator.prototype = {
   },
 
   get exists() {
     return this._typedURLs.size > 0;
   },
 
   migrate(aCallback) {
     let typedURLs = this._typedURLs;
-    let places = [];
+    let pageInfos = [];
     for (let [urlString, time] of typedURLs) {
-      let uri;
+      let url;
       try {
-        uri = Services.io.newURI(urlString);
-        if (!["http", "https", "ftp"].includes(uri.scheme)) {
+        url = new URL(urlString);
+        if (!["http", "https", "ftp"].includes(url.scheme)) {
           continue;
         }
       } catch (ex) {
         Cu.reportError(ex);
         continue;
       }
 
-      // Note that the time will be in microseconds (PRTime),
-      // and Date.now() returns milliseconds. Places expects PRTime,
-      // so we multiply the Date.now return value to make up the difference.
-      let visitDate = time || (Date.now() * 1000);
-      places.push({
-        uri,
-        visits: [{ transitionType: Ci.nsINavHistoryService.TRANSITION_TYPED,
-                   visitDate}],
+      pageInfos.push({
+        url,
+        visits: [{
+          transition: PlacesUtils.history.TRANSITIONS.TYPED,
+          date: time ? PlacesUtils.toDate(time) : new Date(),
+        }],
       });
     }
 
-    if (places.length == 0) {
+    if (pageInfos.length == 0) {
       aCallback(typedURLs.size == 0);
       return;
     }
 
-    MigrationUtils.insertVisitsWrapper(places, {
-      ignoreErrors: true,
-      ignoreResults: true,
-      handleCompletion(updatedCount) {
-        aCallback(updatedCount > 0);
-      },
-    });
+    MigrationUtils.insertVisitsWrapper(pageInfos).then(
+      () => aCallback(true),
+      () => aCallback(false));
   },
 };
 
 function EdgeReadingListMigrator(dbOverride) {
   this.dbOverride = dbOverride;
 }
 
 EdgeReadingListMigrator.prototype = {
--- a/browser/components/migration/IEProfileMigrator.js
+++ b/browser/components/migration/IEProfileMigrator.js
@@ -33,68 +33,62 @@ function History() {
 History.prototype = {
   type: MigrationUtils.resourceTypes.HISTORY,
 
   get exists() {
     return true;
   },
 
   migrate: function H_migrate(aCallback) {
-    let places = [];
+    let pageInfos = [];
     let typedURLs = MSMigrationUtils.getTypedURLs("Software\\Microsoft\\Internet Explorer");
     let historyEnumerator = Cc["@mozilla.org/profile/migrator/iehistoryenumerator;1"].
                             createInstance(Ci.nsISimpleEnumerator);
     while (historyEnumerator.hasMoreElements()) {
       let entry = historyEnumerator.getNext().QueryInterface(Ci.nsIPropertyBag2);
-      let uri = entry.get("uri").QueryInterface(Ci.nsIURI);
+      let url = entry.get("uri").QueryInterface(Ci.nsIURI);
       // MSIE stores some types of URLs in its history that we don't handle,
       // like HTMLHelp and others.  Since we don't properly map handling for
       // all of them we just avoid importing them.
-      if (!["http", "https", "ftp", "file"].includes(uri.scheme)) {
+      if (!["http", "https", "ftp", "file"].includes(url.scheme)) {
         continue;
       }
 
       let title = entry.get("title");
       // Embed visits have no title and don't need to be imported.
       if (title.length == 0) {
         continue;
       }
 
       // The typed urls are already fixed-up, so we can use them for comparison.
-      let transitionType = typedURLs.has(uri.spec) ?
-                             Ci.nsINavHistoryService.TRANSITION_TYPED :
-                             Ci.nsINavHistoryService.TRANSITION_LINK;
+      let transition = typedURLs.has(url.spec) ?
+        PlacesUtils.history.TRANSITIONS.LINK :
+        PlacesUtils.history.TRANSITIONS.TYPED;
       // use the current date if we have no visits for this entry.
-      // Note that the entry will have a time in microseconds (PRTime),
-      // and Date.now() returns milliseconds. Places expects PRTime,
-      // so we multiply the Date.now return value to make up the difference.
-      let lastVisitTime = entry.get("time") || (Date.now() * 1000);
+      let time = entry.get("time");
 
-      places.push(
-        { uri,
-          title,
-          visits: [{ transitionType,
-                     visitDate: lastVisitTime }],
-        }
-      );
+      pageInfos.push({
+        url,
+        title,
+        visits: [{
+          transition,
+          date: time ? PlacesUtils.toDate(entry.get("time")) : new Date(),
+        }],
+      });
     }
 
     // Check whether there is any history to import.
-    if (places.length == 0) {
+    if (pageInfos.length == 0) {
       aCallback(true);
       return;
     }
 
-    MigrationUtils.insertVisitsWrapper(places, {
-      ignoreErrors: true,
-      ignoreResults: true,
-      handleCompletion(updatedCount) {
-        aCallback(updatedCount > 0);
-      },
-    });
+    MigrationUtils.insertVisitsWrapper(pageInfos).then(
+      () => aCallback(true),
+      () => aCallback(false));
   },
 };
 
 // IE form password migrator supporting windows from XP until 7 and IE from 7 until 11
 function IE7FormPasswords() {
   // used to distinguish between this migrator and other passwords migrators in tests.
   this.name = "IE7FormPasswords";
 }
--- a/browser/components/migration/MigrationUtils.jsm
+++ b/browser/components/migration/MigrationUtils.jsm
@@ -1037,22 +1037,22 @@ var MigrationUtils = Object.freeze({
         for (let bm of insertedItems) {
           let {parentGuid, guid, lastModified, type} = bm;
           bmData.push({parentGuid, guid, lastModified, type});
         }
       }
     }, ex => Cu.reportError(ex));
   },
 
-  insertVisitsWrapper(places, options) {
-    this._importQuantities.history += places.length;
+  insertVisitsWrapper(pageInfos) {
+    this._importQuantities.history += pageInfos.length;
     if (gKeepUndoData) {
-      this._updateHistoryUndo(places);
+      this._updateHistoryUndo(pageInfos);
     }
-    return PlacesUtils.asyncHistory.updatePlaces(places, options, true);
+    return PlacesUtils.history.insertMany(pageInfos);
   },
 
   async insertLoginsWrapper(logins) {
     this._importQuantities.logins += logins.length;
     let inserted = await LoginHelper.maybeImportLogins(logins);
     // Note that this means that if we import a login that has a newer password
     // than we know about, we will update the login, and an undo of the import
     // will not revert this. This seems preferable over removing the login
@@ -1096,30 +1096,36 @@ var MigrationUtils = Object.freeze({
 
   stopAndRetrieveUndoData() {
     let undoData = gUndoData;
     gUndoData = null;
     gKeepUndoData = false;
     return this._postProcessUndoData(undoData);
   },
 
-  _updateHistoryUndo(places) {
+  _updateHistoryUndo(pageInfos) {
     let visits = gUndoData.get("visits");
     let visitMap = new Map(visits.map(v => [v.url, v]));
-    for (let place of places) {
-      let visitCount = place.visits.length;
+    for (let pageInfo of pageInfos) {
+      let visitCount = pageInfo.visits.length;
       let first, last;
       if (visitCount > 1) {
-        let visitDates = place.visits.map(v => v.visitDate);
-        first = Math.min.apply(Math, visitDates);
-        last = Math.max.apply(Math, visitDates);
+        let dates = pageInfo.visits.map(v => v.date);
+        first = Math.min.apply(Math, dates);
+        last = Math.max.apply(Math, dates);
       } else {
-        first = last = place.visits[0].visitDate;
+        first = last = pageInfo.visits[0].date;
       }
-      let url = place.uri.spec;
+      let url = pageInfo.url;
+      if (url instanceof Ci.nsIURI) {
+        url = pageInfo.url.spec;
+      } else if (typeof url != "string") {
+        pageInfo.url.href;
+      }
+
       try {
         new URL(url);
       } catch (ex) {
         // This won't save and we won't need to 'undo' it, so ignore this URL.
         continue;
       }
       if (!visitMap.has(url)) {
         visitMap.set(url, {url, visitCount, first, last});
--- a/browser/components/migration/SafariProfileMigrator.js
+++ b/browser/components/migration/SafariProfileMigrator.js
@@ -12,18 +12,16 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource:///modules/MigrationUtils.jsm");
 
 ChromeUtils.defineModuleGetter(this, "Downloads",
                                "resource://gre/modules/Downloads.jsm");
 ChromeUtils.defineModuleGetter(this, "PropertyListUtils",
                                "resource://gre/modules/PropertyListUtils.jsm");
 ChromeUtils.defineModuleGetter(this, "PlacesUtils",
                                "resource://gre/modules/PlacesUtils.jsm");
-ChromeUtils.defineModuleGetter(this, "NetUtil",
-                               "resource://gre/modules/NetUtil.jsm");
 ChromeUtils.defineModuleGetter(this, "FormHistory",
                                "resource://gre/modules/FormHistory.jsm");
 
 Cu.importGlobalProperties(["URL"]);
 
 function Bookmarks(aBookmarksFile) {
   this._file = aBookmarksFile;
 }
@@ -188,61 +186,65 @@ History.prototype = {
   // The visit date is stored as a string, so it's not read as a Date
   // object by PropertyListUtils.
   _parseCocoaDate: function H___parseCocoaDate(aCocoaDateStr) {
     let asDouble = parseFloat(aCocoaDateStr);
     if (!isNaN(asDouble)) {
       // reference date of NSDate.
       let date = new Date("1 January 2001, GMT");
       date.setMilliseconds(asDouble * 1000);
-      return date * 1000;
+      return date;
     }
-    return 0;
+    return new Date();
   },
 
   migrate: function H_migrate(aCallback) {
     PropertyListUtils.read(this._file, aDict => {
       try {
         if (!aDict)
           throw new Error("Could not read history property list");
         if (!aDict.has("WebHistoryDates"))
           throw new Error("Unexpected history-property list format");
 
-        // Safari's History file contains only top-level urls.  It does not
-        // distinguish between typed urls and linked urls.
-        let transType = PlacesUtils.history.TRANSITION_LINK;
-
-        let places = [];
+        let pageInfos = [];
         let entries = aDict.get("WebHistoryDates");
+        let failedOnce = false;
         for (let entry of entries) {
           if (entry.has("lastVisitedDate")) {
-            let visitDate = this._parseCocoaDate(entry.get("lastVisitedDate"));
+            let date = this._parseCocoaDate(entry.get("lastVisitedDate"));
             try {
-              places.push({ uri: NetUtil.newURI(entry.get("")),
-                            title: entry.get("title"),
-                            visits: [{ transitionType: transType,
-                                       visitDate }] });
+              pageInfos.push({
+                url: new URL(entry.get("")),
+                title: entry.get("title"),
+                visits: [{
+                  // Safari's History file contains only top-level urls.  It does not
+                  // distinguish between typed urls and linked urls.
+                  transition: PlacesUtils.history.TRANSITIONS.LINK,
+                  date,
+                }],
+              });
             } catch (ex) {
               // Safari's History file may contain malformed URIs which
               // will be ignored.
               Cu.reportError(ex);
+              failedOnce = true;
             }
           }
         }
-        if (places.length > 0) {
-          MigrationUtils.insertVisitsWrapper(places, {
-            ignoreErrors: true,
-            ignoreResults: true,
-            handleCompletion(updatedCount) {
-              aCallback(updatedCount > 0);
-            },
-          });
-        } else {
-          aCallback(false);
+        if (pageInfos.length == 0) {
+          // If we failed at least once, then we didn't succeed in importing,
+          // otherwise we didn't actually have anything to import, so we'll
+          // report it as a success.
+          aCallback(!failedOnce);
+          return;
         }
+
+        MigrationUtils.insertVisitsWrapper(pageInfos).then(
+          () => aCallback(true),
+          () => aCallback(false));
       } catch (ex) {
         Cu.reportError(ex);
         aCallback(false);
       }
     });
   },
 };
 
--- a/browser/components/migration/tests/unit/test_automigration.js
+++ b/browser/components/migration/tests/unit/test_automigration.js
@@ -1,16 +1,16 @@
 "use strict";
 
 ChromeUtils.import("resource:///modules/AutoMigrate.jsm", this);
 
 let gShimmedMigratorKeyPicker = null;
 let gShimmedMigrator = null;
 
-const kUsecPerMin = 60 * 1000000;
+const kMsecPerMin = 60 * 1000;
 
 // This is really a proxy on MigrationUtils, but if we specify that directly,
 // we get in trouble because the object itself is frozen, and Proxies can't
 // return a different value to an object when directly proxying a frozen
 // object.
 let AutoMigrateBackstage = ChromeUtils.import("resource:///modules/AutoMigrate.jsm", {});
 
 AutoMigrateBackstage.MigrationUtils = new Proxy({}, {
@@ -256,37 +256,37 @@ add_task(async function checkUndoRemoval
     title: "Some example bookmark",
   });
 
   let bookmark = await PlacesUtils.bookmarks.fetch({url: "http://www.example.org/"});
   Assert.ok(bookmark, "Should have a bookmark before undo");
   Assert.equal(bookmark.title, "Some example bookmark", "Should have correct bookmark before undo.");
 
   // Insert 2 history visits
-  let now_uSec = Date.now() * 1000;
+  let now = new Date();
   let visitedURI = Services.io.newURI("http://www.example.com/");
   let frecencyUpdatePromise = new Promise(resolve => {
     let observer = {
       onManyFrecenciesChanged() {
         PlacesUtils.history.removeObserver(observer);
         resolve();
       },
     };
     PlacesUtils.history.addObserver(observer);
   });
   await MigrationUtils.insertVisitsWrapper([{
-    uri: visitedURI,
+    url: visitedURI,
     visits: [
       {
-        transitionType: PlacesUtils.history.TRANSITION_LINK,
-        visitDate: now_uSec,
+        transition: PlacesUtils.history.TRANSITION_LINK,
+        date: now,
       },
       {
-        transitionType: PlacesUtils.history.TRANSITION_LINK,
-        visitDate: now_uSec - 100 * kUsecPerMin,
+        transition: PlacesUtils.history.TRANSITION_LINK,
+        date: new Date(now - 100 * kMsecPerMin),
       },
     ],
   }]);
   await frecencyUpdatePromise;
 
   // Verify that both visits get reported.
   let opts = PlacesUtils.history.getNewQueryOptions();
   opts.resultType = opts.RESULTS_AS_VISIT;
@@ -491,103 +491,103 @@ add_task(async function testLoginsRemova
   Assert.equal(1, LoginHelper.searchLoginsWithObject({hostname: "https://example.org", formSubmitURL: "https://example.org/"}).length,
                    "changed example.org entry should have persisted.");
   Services.logins.removeAllLogins();
 });
 
 add_task(async function checkUndoVisitsState() {
   MigrationUtils.initializeUndoData();
   await MigrationUtils.insertVisitsWrapper([{
-    uri: NetUtil.newURI("http://www.example.com/"),
+    url: NetUtil.newURI("http://www.example.com/"),
     title: "Example",
     visits: [{
-      visitDate: new Date("2015-07-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-07-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }, {
-      visitDate: new Date("2015-09-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-09-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }, {
-      visitDate: new Date("2015-08-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-08-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }],
   }, {
-    uri: NetUtil.newURI("http://www.example.org/"),
+    url: Services.io.newURI("http://www.example.org/"),
     title: "Example",
     visits: [{
-      visitDate: new Date("2016-04-03").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2016-04-03"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }, {
-      visitDate: new Date("2015-08-03").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-08-03"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }],
   }, {
-    uri: NetUtil.newURI("http://www.example.com/"),
+    url: "http://www.example.com/",
     title: "Example",
     visits: [{
-      visitDate: new Date("2015-10-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-10-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }],
   }]);
   let undoVisitData = (await MigrationUtils.stopAndRetrieveUndoData()).get("visits");
   Assert.deepEqual(Array.from(undoVisitData.map(v => v.url)).sort(),
                    ["http://www.example.com/", "http://www.example.org/"]);
   Assert.deepEqual(undoVisitData.find(v => v.url == "http://www.example.com/"), {
     url: "http://www.example.com/",
     visitCount: 4,
-    first: new Date("2015-07-10").getTime() * 1000,
-    last: new Date("2015-10-10").getTime() * 1000,
+    first: new Date("2015-07-10").getTime(),
+    last: new Date("2015-10-10").getTime(),
   });
   Assert.deepEqual(undoVisitData.find(v => v.url == "http://www.example.org/"), {
     url: "http://www.example.org/",
     visitCount: 2,
-    first: new Date("2015-08-03").getTime() * 1000,
-    last: new Date("2016-04-03").getTime() * 1000,
+    first: new Date("2015-08-03").getTime(),
+    last: new Date("2016-04-03").getTime(),
   });
 
   await PlacesUtils.history.clear();
 });
 
 add_task(async function checkUndoVisitsState() {
   MigrationUtils.initializeUndoData();
   await MigrationUtils.insertVisitsWrapper([{
-    uri: NetUtil.newURI("http://www.example.com/"),
+    url: NetUtil.newURI("http://www.example.com/"),
     title: "Example",
     visits: [{
-      visitDate: new Date("2015-07-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-07-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }, {
-      visitDate: new Date("2015-09-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-09-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }, {
-      visitDate: new Date("2015-08-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-08-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }],
   }, {
-    uri: NetUtil.newURI("http://www.example.org/"),
+    url: NetUtil.newURI("http://www.example.org/"),
     title: "Example",
     visits: [{
-      visitDate: new Date("2016-04-03").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2016-04-03"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }, {
-      visitDate: new Date("2015-08-03").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-08-03"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }],
   }, {
-    uri: NetUtil.newURI("http://www.example.com/"),
+    url: NetUtil.newURI("http://www.example.com/"),
     title: "Example",
     visits: [{
-      visitDate: new Date("2015-10-10").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-10-10"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }],
   }, {
-    uri: NetUtil.newURI("http://www.mozilla.org/"),
+    url: NetUtil.newURI("http://www.mozilla.org/"),
     title: "Example",
     visits: [{
-      visitDate: new Date("2015-01-01").getTime() * 1000,
-      transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+      date: new Date("2015-01-01"),
+      transition: Ci.nsINavHistoryService.TRANSITION_LINK,
     }],
   }]);
 
   // We have to wait until frecency updates have been handled in order
   // to accurately determine whether we're doing the right thing.
   let frecencyUpdatesHandled = new Promise(resolve => {
     PlacesUtils.history.addObserver({
       onManyFrecenciesChanged() {