/** * One-time observer callback. */ function promiseObserve(name, checkFn) { return new Promise(resolve => { Services.obs.addObserver(function observer(subject) { if (checkFn(subject)) { Services.obs.removeObserver(observer, name); resolve(); } }, name); }); } var conn = PlacesUtils.history.DBConnection; /** * Gets a single column value from either the places or historyvisits table. */ function getColumn(table, column, fromColumnName, fromColumnValue) { let sql = `SELECT ${column} FROM ${table} WHERE ${fromColumnName} = :val ${fromColumnName == "url" ? "AND url_hash = hash(:val)" : ""} LIMIT 1`; let stmt = conn.createStatement(sql); try { stmt.params.val = fromColumnValue; ok(stmt.executeStep(), "Expect to get a row"); return stmt.row[column]; } finally { stmt.reset(); } } add_task(async function() { // Make sure places visit chains are saved correctly with a redirect // transitions. // Part 1: observe history events that fire when a visit occurs. // Make sure visits appear in order, and that the visit chain is correct. var expectedUrls = [ "http://example.com/tests/toolkit/components/places/tests/browser/begin.html", "http://example.com/tests/toolkit/components/places/tests/browser/redirect_twice.sjs", "http://example.com/tests/toolkit/components/places/tests/browser/redirect_once.sjs", "http://test1.example.com/tests/toolkit/components/places/tests/browser/final.html", ]; var currentIndex = 0; function checkObserver(subject) { var uri = subject.QueryInterface(Ci.nsIURI); var expected = expectedUrls[currentIndex]; is(uri.spec, expected, "Saved URL visit " + uri.spec); var placeId = getColumn("moz_places", "id", "url", uri.spec); var fromVisitId = getColumn( "moz_historyvisits", "from_visit", "place_id", placeId ); if (currentIndex == 0) { is(fromVisitId, 0, "First visit has no from visit"); } else { var lastVisitId = getColumn( "moz_historyvisits", "place_id", "id", fromVisitId ); var fromVisitUrl = getColumn("moz_places", "url", "id", lastVisitId); is( fromVisitUrl, expectedUrls[currentIndex - 1], "From visit was " + expectedUrls[currentIndex - 1] ); } currentIndex++; return currentIndex >= expectedUrls.length; } let visitUriPromise = promiseObserve("uri-visit-saved", checkObserver); const testUrl = "http://example.com/tests/toolkit/components/places/tests/browser/begin.html"; await BrowserTestUtils.openNewForegroundTab(gBrowser, testUrl); // Load begin page, click link on page to record visits. await BrowserTestUtils.synthesizeMouseAtCenter( "#clickme", {}, gBrowser.selectedBrowser ); await visitUriPromise; await PlacesUtils.history.clear(); gBrowser.removeCurrentTab(); });