michael@0: /** michael@0: * Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ michael@0: */ michael@0: michael@0: gBrowser.selectedTab = gBrowser.addTab(); michael@0: michael@0: function finishAndCleanUp() michael@0: { michael@0: gBrowser.removeCurrentTab(); michael@0: promiseClearHistory().then(finish); michael@0: } michael@0: michael@0: /** michael@0: * One-time observer callback. michael@0: */ michael@0: function waitForObserve(name, callback) michael@0: { michael@0: var observerService = Cc["@mozilla.org/observer-service;1"] michael@0: .getService(Ci.nsIObserverService); michael@0: var observer = { michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]), michael@0: observe: function(subject, topic, data) { michael@0: observerService.removeObserver(observer, name); michael@0: observer = null; michael@0: callback(subject, topic, data); michael@0: } michael@0: }; michael@0: michael@0: observerService.addObserver(observer, name, false); michael@0: } michael@0: michael@0: /** michael@0: * One-time DOMContentLoaded callback. michael@0: */ michael@0: function waitForLoad(callback) michael@0: { michael@0: gBrowser.addEventListener("DOMContentLoaded", function() { michael@0: gBrowser.removeEventListener("DOMContentLoaded", arguments.callee, true); michael@0: callback(); michael@0: }, true); michael@0: } michael@0: michael@0: var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection; michael@0: michael@0: /** michael@0: * Gets a single column value from either the places or historyvisits table. michael@0: */ michael@0: function getColumn(table, column, fromColumnName, fromColumnValue) michael@0: { michael@0: let sql = "SELECT " + column + " " + michael@0: "FROM " + table + " " + michael@0: "WHERE " + fromColumnName + " = :val " + michael@0: "LIMIT 1"; michael@0: let stmt = conn.createStatement(sql); michael@0: try { michael@0: stmt.params.val = fromColumnValue; michael@0: ok(stmt.executeStep(), "Expect to get a row"); michael@0: return stmt.row[column]; michael@0: } michael@0: finally { michael@0: stmt.reset(); michael@0: } michael@0: } michael@0: michael@0: function test() michael@0: { michael@0: // Make sure places visit chains are saved correctly with a redirect michael@0: // transitions. michael@0: michael@0: waitForExplicitFinish(); michael@0: michael@0: // Part 1: observe history events that fire when a visit occurs. michael@0: // Make sure visits appear in order, and that the visit chain is correct. michael@0: var expectedUrls = [ michael@0: "http://example.com/tests/toolkit/components/places/tests/browser/begin.html", michael@0: "http://example.com/tests/toolkit/components/places/tests/browser/redirect_twice.sjs", michael@0: "http://example.com/tests/toolkit/components/places/tests/browser/redirect_once.sjs", michael@0: "http://example.com/tests/toolkit/components/places/tests/browser/final.html" michael@0: ]; michael@0: var currentIndex = 0; michael@0: michael@0: waitForObserve("uri-visit-saved", function(subject, topic, data) { michael@0: var uri = subject.QueryInterface(Ci.nsIURI); michael@0: var expected = expectedUrls[currentIndex]; michael@0: is(uri.spec, expected, "Saved URL visit " + uri.spec); michael@0: michael@0: var placeId = getColumn("moz_places", "id", "url", uri.spec); michael@0: var fromVisitId = getColumn("moz_historyvisits", "from_visit", "place_id", placeId); michael@0: michael@0: if (currentIndex == 0) { michael@0: is(fromVisitId, 0, "First visit has no from visit"); michael@0: } michael@0: else { michael@0: var lastVisitId = getColumn("moz_historyvisits", "place_id", "id", fromVisitId); michael@0: var fromVisitUrl = getColumn("moz_places", "url", "id", lastVisitId); michael@0: is(fromVisitUrl, expectedUrls[currentIndex - 1], michael@0: "From visit was " + expectedUrls[currentIndex - 1]); michael@0: } michael@0: michael@0: currentIndex++; michael@0: if (currentIndex < expectedUrls.length) { michael@0: waitForObserve("uri-visit-saved", arguments.callee); michael@0: } michael@0: else { michael@0: finishAndCleanUp(); michael@0: } michael@0: }); michael@0: michael@0: // Load begin page, click link on page to record visits. michael@0: content.location.href = "http://example.com/tests/toolkit/components/places/tests/browser/begin.html"; michael@0: waitForLoad(function() { michael@0: EventUtils.sendMouseEvent({type: 'click'}, 'clickme', content.window); michael@0: waitForLoad(function() { michael@0: content.location.href = "about:blank"; michael@0: }); michael@0: }); michael@0: }