diff options
Diffstat (limited to 'toolkit/components/places/tests/browser')
51 files changed, 1939 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/browser/1601563-1.html b/toolkit/components/places/tests/browser/1601563-1.html new file mode 100644 index 0000000000..4f92778561 --- /dev/null +++ b/toolkit/components/places/tests/browser/1601563-1.html @@ -0,0 +1,20 @@ +<!doctype html> +<title>First title</title> +<iframe srcdoc=""></iframe> +<script> +onload = function() { + // This iframe doc shouldn't override our title. + let doc = document.querySelector("iframe").contentDocument; + doc.open(); + doc.write("<title>This is not your title</title>Hello"); + doc.close(); + + if (doc.title == "This is not your title") { + // Now navigate away so that the test has something to wait for to ensure the + // relevant code has run. + let link = document.createElement("a"); + link.href = window.location.href.replace("-1.html", "-2.html"); + link.click(); + } +} +</script> diff --git a/toolkit/components/places/tests/browser/1601563-2.html b/toolkit/components/places/tests/browser/1601563-2.html new file mode 100644 index 0000000000..b1c000cd5a --- /dev/null +++ b/toolkit/components/places/tests/browser/1601563-2.html @@ -0,0 +1,3 @@ +<!doctype html> +<title>Second title</title> +Nothing to see here. diff --git a/toolkit/components/places/tests/browser/399606-history.go-0.html b/toolkit/components/places/tests/browser/399606-history.go-0.html new file mode 100644 index 0000000000..6e36aa23de --- /dev/null +++ b/toolkit/components/places/tests/browser/399606-history.go-0.html @@ -0,0 +1,13 @@ +<html> +<head> +<title>history.go(0)</title> +<script> +setTimeout(function() { + history.go(0); +}, 1000); +</script> +</head> +<body> +Testing history.go(0) +</body> +</html> diff --git a/toolkit/components/places/tests/browser/399606-httprefresh.html b/toolkit/components/places/tests/browser/399606-httprefresh.html new file mode 100644 index 0000000000..e43455ee05 --- /dev/null +++ b/toolkit/components/places/tests/browser/399606-httprefresh.html @@ -0,0 +1,8 @@ +<html><head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> + +<meta http-equiv="refresh" content="1"> +<title>httprefresh</title> +</head><body> +Testing httprefresh +</body></html> diff --git a/toolkit/components/places/tests/browser/399606-location.reload.html b/toolkit/components/places/tests/browser/399606-location.reload.html new file mode 100644 index 0000000000..54eefab1c3 --- /dev/null +++ b/toolkit/components/places/tests/browser/399606-location.reload.html @@ -0,0 +1,13 @@ +<html> +<head> +<title>location.reload()</title> +<script> +setTimeout(function() { + location.reload(); +}, 100); +</script> +</head> +<body> +Testing location.reload(); +</body> +</html> diff --git a/toolkit/components/places/tests/browser/399606-location.replace.html b/toolkit/components/places/tests/browser/399606-location.replace.html new file mode 100644 index 0000000000..8a72c96722 --- /dev/null +++ b/toolkit/components/places/tests/browser/399606-location.replace.html @@ -0,0 +1,13 @@ +<html> +<head> +<title>location.replace</title> +<script> +setTimeout(function() { + location.replace(window.location.href); +}, 1000); +</script> +</head> +<body> +Testing location.replace +</body> +</html> diff --git a/toolkit/components/places/tests/browser/399606-window.location.href.html b/toolkit/components/places/tests/browser/399606-window.location.href.html new file mode 100644 index 0000000000..490b08e40c --- /dev/null +++ b/toolkit/components/places/tests/browser/399606-window.location.href.html @@ -0,0 +1,14 @@ +<html> +<head> +<title>window.location.href</title> +<script> +setTimeout(function() { + // eslint-disable-next-line no-self-assign + window.location.href = window.location.href; +}, 1000); +</script> +</head> +<body> +Testing window.location.href +</body> +</html> diff --git a/toolkit/components/places/tests/browser/399606-window.location.html b/toolkit/components/places/tests/browser/399606-window.location.html new file mode 100644 index 0000000000..b84366cf8d --- /dev/null +++ b/toolkit/components/places/tests/browser/399606-window.location.html @@ -0,0 +1,14 @@ +<html> +<head> +<title>window.location</title> +<script> +setTimeout(function() { + // eslint-disable-next-line no-self-assign + window.location = window.location; +}, 1000); +</script> +</head> +<body> +Testing window.location +</body> +</html> diff --git a/toolkit/components/places/tests/browser/461710_link_page-2.html b/toolkit/components/places/tests/browser/461710_link_page-2.html new file mode 100644 index 0000000000..726373f83e --- /dev/null +++ b/toolkit/components/places/tests/browser/461710_link_page-2.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>Link page 2</title> + <style type="text/css"> + a:link { color: #0000ff; } + a:visited { color: #ff0000; } + </style> + </head> + <body> + <p><a href="461710_visited_page.html" id="link">Link to the second visited page</a></p> + </body> +</html> diff --git a/toolkit/components/places/tests/browser/461710_link_page-3.html b/toolkit/components/places/tests/browser/461710_link_page-3.html new file mode 100644 index 0000000000..d465cf79c6 --- /dev/null +++ b/toolkit/components/places/tests/browser/461710_link_page-3.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>Link page 3</title> + <style type="text/css"> + a:link { color: #0000ff; } + a:visited { color: #ff0000; } + </style> + </head> + <body> + <p><a href="461710_visited_page.html" id="link">Link to the third visited page</a></p> + </body> +</html> diff --git a/toolkit/components/places/tests/browser/461710_link_page.html b/toolkit/components/places/tests/browser/461710_link_page.html new file mode 100644 index 0000000000..05189fa41b --- /dev/null +++ b/toolkit/components/places/tests/browser/461710_link_page.html @@ -0,0 +1,13 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>Link page</title> + <style type="text/css"> + a:link { color: #0000ff; } + a:visited { color: #ff0000; } + </style> + </head> + <body> + <p><a href="461710_visited_page.html" id="link">Link to the visited page</a></p> + </body> +</html> diff --git a/toolkit/components/places/tests/browser/461710_visited_page.html b/toolkit/components/places/tests/browser/461710_visited_page.html new file mode 100644 index 0000000000..3ff52f69c8 --- /dev/null +++ b/toolkit/components/places/tests/browser/461710_visited_page.html @@ -0,0 +1,9 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>Visited page</title> + </head> + <body> + <p>This page is marked as visited</p> + </body> +</html> diff --git a/toolkit/components/places/tests/browser/begin.html b/toolkit/components/places/tests/browser/begin.html new file mode 100644 index 0000000000..da4c16dd25 --- /dev/null +++ b/toolkit/components/places/tests/browser/begin.html @@ -0,0 +1,10 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<html> + <body> + <a id="clickme" href="redirect_twice.sjs">Redirect twice</a> + </body> +</html> diff --git a/toolkit/components/places/tests/browser/browser.ini b/toolkit/components/places/tests/browser/browser.ini new file mode 100644 index 0000000000..33526ebb20 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser.ini @@ -0,0 +1,88 @@ +[DEFAULT] +support-files = + head.js + +[browser_bug399606.js] +https_first_disabled = true +support-files = + 399606-history.go-0.html + 399606-httprefresh.html + 399606-location.reload.html + 399606-location.replace.html + 399606-window.location.html + 399606-window.location.href.html +[browser_bug461710.js] +https_first_disabled = true +support-files = + 461710_link_page-2.html + 461710_link_page-3.html + 461710_link_page.html + 461710_visited_page.html +[browser_bug646422.js] +https_first_disabled = true +[browser_bug680727.js] +https_first_disabled = true +skip-if = verify +[browser_bug1601563.js] +https_first_disabled = true +support-files = + 1601563-1.html + 1601563-2.html +[browser_double_redirect.js] +https_first_disabled = true +support-files = + begin.html + final.html + redirect_once.sjs + redirect_twice.sjs +[browser_favicon_privatebrowsing_perwindowpb.js] +[browser_history_post.js] +https_first_disabled = true +support-files = + history_post.html + history_post.sjs +[browser_notfound.js] +[browser_onvisit_title_null_for_navigation.js] +https_first_disabled = true +skip-if = verify +support-files = + empty_page.html +[browser_redirect.js] +support-files = + redirect.sjs + redirect-target.html +[browser_redirect_self.js] +support-files = + redirect_self.sjs +[browser_multi_redirect_frecency.js] +https_first_disabled = true +support-files = + final.html + redirect_once.sjs + redirect_thrice.sjs + redirect_twice.sjs + redirect_twice_perma.sjs +[browser_settitle.js] +https_first_disabled = true +support-files = + title1.html + title2.html +[browser_visited_notfound.js] +[browser_visituri.js] +https_first_disabled = true +support-files = + begin.html + final.html + redirect_once.sjs + redirect_twice.sjs +[browser_visituri_nohistory.js] +support-files = + begin.html + final.html + favicon-normal16.png + favicon-normal32.png +[browser_visituri_privatebrowsing_perwindowpb.js] +support-files = + begin.html + favicon.html + final.html diff --git a/toolkit/components/places/tests/browser/browser_bug1601563.js b/toolkit/components/places/tests/browser/browser_bug1601563.js new file mode 100644 index 0000000000..41e278ee54 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_bug1601563.js @@ -0,0 +1,40 @@ +const PREFIX = + "http://example.com/tests/toolkit/components/places/tests/browser/1601563"; + +function titleUpdate(pageUrl) { + let lastTitle = null; + return PlacesTestUtils.waitForNotification("page-title-changed", events => { + if (pageUrl != events[0].url) { + return false; + } + lastTitle = events[0].title; + return true; + }).then(() => { + return lastTitle; + }); +} + +add_task(async function () { + registerCleanupFunction(PlacesUtils.history.clear); + const FIRST_URL = PREFIX + "-1.html"; + const SECOND_URL = PREFIX + "-2.html"; + let firstTitlePromise = titleUpdate(FIRST_URL); + let secondTitlePromise = titleUpdate(SECOND_URL); + + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, FIRST_URL); + + let firstTitle = await firstTitlePromise; + is(firstTitle, "First title", "First title should match the page"); + + let secondTitle = await secondTitlePromise; + is(secondTitle, "Second title", "Second title should match the page"); + + let entry = await PlacesUtils.history.fetch(FIRST_URL); + is( + entry.title, + firstTitle, + "Should not override first title with document.open()ed frame" + ); + + await BrowserTestUtils.removeTab(tab); +}); diff --git a/toolkit/components/places/tests/browser/browser_bug399606.js b/toolkit/components/places/tests/browser/browser_bug399606.js new file mode 100644 index 0000000000..f593d68528 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_bug399606.js @@ -0,0 +1,50 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function () { + registerCleanupFunction(PlacesUtils.history.clear); + + const URIS = [ + "http://example.com/tests/toolkit/components/places/tests/browser/399606-window.location.href.html", + "http://example.com/tests/toolkit/components/places/tests/browser/399606-history.go-0.html", + "http://example.com/tests/toolkit/components/places/tests/browser/399606-location.replace.html", + "http://example.com/tests/toolkit/components/places/tests/browser/399606-location.reload.html", + "http://example.com/tests/toolkit/components/places/tests/browser/399606-httprefresh.html", + "http://example.com/tests/toolkit/components/places/tests/browser/399606-window.location.html", + ]; + + // Create and add history observer. + let count = 0; + let expectedURI = null; + function onVisitsListener(aEvents) { + for (let event of aEvents) { + info("Received onVisits: " + event.url); + if (event.url == expectedURI) { + count++; + } + } + } + + async function promiseLoadedThreeTimes(uri) { + count = 0; + expectedURI = uri; + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + PlacesObservers.addListener(["page-visited"], onVisitsListener); + BrowserTestUtils.loadURIString(gBrowser, uri); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri); + await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser, false, uri); + PlacesObservers.removeListener(["page-visited"], onVisitsListener); + BrowserTestUtils.removeTab(tab); + } + + for (let uri of URIS) { + await promiseLoadedThreeTimes(uri); + is( + count, + 1, + "'page-visited' has been received right number of times for " + uri + ); + } +}); diff --git a/toolkit/components/places/tests/browser/browser_bug461710.js b/toolkit/components/places/tests/browser/browser_bug461710.js new file mode 100644 index 0000000000..6815860929 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_bug461710.js @@ -0,0 +1,89 @@ +const kRed = "rgb(255, 0, 0)"; +const kBlue = "rgb(0, 0, 255)"; + +const prefix = + "http://example.com/tests/toolkit/components/places/tests/browser/461710_"; + +add_task(async function () { + registerCleanupFunction(PlacesUtils.history.clear); + let normalWindow = await BrowserTestUtils.openNewBrowserWindow(); + let privateWindow = await BrowserTestUtils.openNewBrowserWindow({ + private: true, + }); + let tests = [ + { + private: false, + topic: "uri-visit-saved", + subtest: "visited_page.html", + }, + { + private: false, + subtest: "link_page.html", + color: kRed, + message: "Visited link coloring should work outside of private mode", + }, + { + private: true, + subtest: "link_page-2.html", + color: kBlue, + message: "Visited link coloring should not work inside of private mode", + }, + { + private: false, + subtest: "link_page-3.html", + color: kRed, + message: "Visited link coloring should work outside of private mode", + }, + ]; + + let uri = Services.io.newURI(prefix + tests[0].subtest); + for (let test of tests) { + info(test.subtest); + let promise = null; + if (test.topic) { + promise = TestUtils.topicObserved(test.topic, subject => + uri.equals(subject.QueryInterface(Ci.nsIURI)) + ); + } + await BrowserTestUtils.withNewTab( + { + gBrowser: test.private ? privateWindow.gBrowser : normalWindow.gBrowser, + url: prefix + test.subtest, + }, + async function (browser) { + if (promise) { + await promise; + } + + if (test.color) { + // In e10s waiting for visited-status-resolution is not enough to ensure links + // have been updated, because it only tells us that messages to update links + // have been dispatched. We must still wait for the actual links to update. + await TestUtils.waitForCondition(async function () { + let color = await SpecialPowers.spawn( + browser, + [], + async function () { + let elem = content.document.getElementById("link"); + return content.windowUtils.getVisitedDependentComputedStyle( + elem, + "", + "color" + ); + } + ); + return color == test.color; + }, test.message); + // The harness will consider the test as failed overall if there were no + // passes or failures, so record it as a pass. + ok(true, test.message); + } + } + ); + } + + let promisePBExit = TestUtils.topicObserved("last-pb-context-exited"); + await BrowserTestUtils.closeWindow(privateWindow); + await promisePBExit; + await BrowserTestUtils.closeWindow(normalWindow); +}); diff --git a/toolkit/components/places/tests/browser/browser_bug646422.js b/toolkit/components/places/tests/browser/browser_bug646422.js new file mode 100644 index 0000000000..cb6512ed4e --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_bug646422.js @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test for Bug 646224. Make sure that after changing the URI via + * history.pushState, the history service has a title stored for the new URI. + **/ + +add_task(async function () { + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "http://example.com" + ); + + const newTitlePromise = PlacesTestUtils.waitForNotification( + "page-title-changed", + events => /new_page$/.test(events[0].url) + ); + + await SpecialPowers.spawn(tab.linkedBrowser, [], async function () { + let title = content.document.title; + content.history.pushState("", "", "new_page"); + Assert.ok(title, "Content window should initially have a title."); + }); + + const events = await newTitlePromise; + const newtitle = events[0].title; + + await SpecialPowers.spawn( + tab.linkedBrowser, + [{ newtitle }], + async function (args) { + Assert.equal( + args.newtitle, + content.document.title, + "Title after pushstate." + ); + } + ); + + await PlacesUtils.history.clear(); + gBrowser.removeTab(tab); +}); diff --git a/toolkit/components/places/tests/browser/browser_bug680727.js b/toolkit/components/places/tests/browser/browser_bug680727.js new file mode 100644 index 0000000000..2fe2377d34 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_bug680727.js @@ -0,0 +1,127 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* Ensure that clicking the button in the Offline mode neterror page updates + global history. See bug 680727. */ +/* TEST_PATH=toolkit/components/places/tests/browser/browser_bug680727.js make -C $(OBJDIR) mochitest-browser-chrome */ + +const kUniqueURI = Services.io.newURI("http://mochi.test:8888/#bug_680727"); +var proxyPrefValue; +var ourTab; + +function test() { + waitForExplicitFinish(); + + // Tests always connect to localhost, and per bug 87717, localhost is now + // reachable in offline mode. To avoid this, disable any proxy. + proxyPrefValue = Services.prefs.getIntPref("network.proxy.type"); + Services.prefs.setIntPref("network.proxy.type", 0); + + // Clear network cache. + Services.cache2.clear(); + + // Go offline, expecting the error page. + Services.io.offline = true; + + BrowserTestUtils.openNewForegroundTab(gBrowser).then(tab => { + ourTab = tab; + BrowserTestUtils.browserLoaded( + ourTab.linkedBrowser, + false, + null, + true + ).then(errorListener); + BrowserTestUtils.loadURIString(ourTab.linkedBrowser, kUniqueURI.spec); + }); +} + +// ------------------------------------------------------------------------------ +// listen to loading the neterror page. (offline mode) +function errorListener() { + ok(Services.io.offline, "Services.io.offline is true."); + + // This is an error page. + SpecialPowers.spawn(ourTab.linkedBrowser, [kUniqueURI.spec], function (uri) { + Assert.equal( + content.document.documentURI.substring(0, 27), + "about:neterror?e=netOffline", + "Document URI is the error page." + ); + + // But location bar should show the original request. + Assert.equal( + content.location.href, + uri, + "Docshell URI is the original URI." + ); + }).then(() => { + // Global history does not record URI of a failed request. + PlacesTestUtils.promiseAsyncUpdates().then(() => { + PlacesUtils.history.hasVisits(kUniqueURI).then(isVisited => { + errorAsyncListener(kUniqueURI, isVisited); + }); + }); + }); +} + +function errorAsyncListener(aURI, aIsVisited) { + ok( + kUniqueURI.equals(aURI) && !aIsVisited, + "The neterror page is not listed in global history." + ); + + Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); + + // Now press the "Try Again" button, with offline mode off. + Services.io.offline = false; + + BrowserTestUtils.browserLoaded(ourTab.linkedBrowser, false, null, true).then( + reloadListener + ); + + SpecialPowers.spawn(ourTab.linkedBrowser, [], function () { + Assert.ok( + content.document.querySelector("#netErrorButtonContainer > .try-again"), + "The error page has got a .try-again element" + ); + content.document + .querySelector("#netErrorButtonContainer > .try-again") + .click(); + }); +} + +// ------------------------------------------------------------------------------ +// listen to reload of neterror. +function reloadListener() { + // This listener catches "DOMContentLoaded" on being called + // nsIWPL::onLocationChange(...). That is right *AFTER* + // IHistory::VisitURI(...) is called. + ok(!Services.io.offline, "Services.io.offline is false."); + + SpecialPowers.spawn(ourTab.linkedBrowser, [kUniqueURI.spec], function (uri) { + // This is not an error page. + Assert.equal( + content.document.documentURI, + uri, + "Document URI is not the offline-error page, but the original URI." + ); + }).then(() => { + // Check if global history remembers the successfully-requested URI. + PlacesTestUtils.promiseAsyncUpdates().then(() => { + PlacesUtils.history.hasVisits(kUniqueURI).then(isVisited => { + reloadAsyncListener(kUniqueURI, isVisited); + }); + }); + }); +} + +function reloadAsyncListener(aURI, aIsVisited) { + ok(kUniqueURI.equals(aURI) && aIsVisited, "We have visited the URI."); + PlacesUtils.history.clear().then(finish); +} + +registerCleanupFunction(async function () { + Services.prefs.setIntPref("network.proxy.type", proxyPrefValue); + Services.io.offline = false; + BrowserTestUtils.removeTab(ourTab); +}); diff --git a/toolkit/components/places/tests/browser/browser_double_redirect.js b/toolkit/components/places/tests/browser/browser_double_redirect.js new file mode 100644 index 0000000000..435bd86f19 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_double_redirect.js @@ -0,0 +1,83 @@ +// Test for bug 411966. +// When a page redirects multiple times, from_visit should point to the +// previous visit in the chain, not to the first visit in the chain. + +add_task(async function () { + await PlacesUtils.history.clear(); + + const BASE_URL = + "http://example.com/tests/toolkit/components/places/tests/browser/"; + const TEST_URI = NetUtil.newURI(BASE_URL + "begin.html"); + const FIRST_REDIRECTING_URI = NetUtil.newURI(BASE_URL + "redirect_twice.sjs"); + const FINAL_URI = NetUtil.newURI( + "http://test1.example.com/tests/toolkit/components/places/tests/browser/final.html" + ); + + let promiseVisits = new Promise(resolve => { + let observer = { + _notified: [], + onVisit(uri, id, time, referrerId, transition) { + info("Received onVisit: " + uri); + this._notified.push(uri); + + if (uri != FINAL_URI.spec) { + return; + } + + is(this._notified.length, 4); + PlacesObservers.removeListener(["page-visited"], this.handleEvents); + + (async function () { + // Get all pages visited from the original typed one + let db = await PlacesUtils.promiseDBConnection(); + let rows = await db.execute( + `SELECT url FROM moz_historyvisits + JOIN moz_places h ON h.id = place_id + WHERE from_visit IN + (SELECT v.id FROM moz_historyvisits v + JOIN moz_places p ON p.id = v.place_id + WHERE p.url_hash = hash(:url) AND p.url = :url) + `, + { url: TEST_URI.spec } + ); + + is(rows.length, 1, "Found right number of visits"); + let visitedUrl = rows[0].getResultByName("url"); + // Check that redirect from_visit is not from the original typed one + is( + visitedUrl, + FIRST_REDIRECTING_URI.spec, + "Check referrer for " + visitedUrl + ); + + resolve(); + })(); + }, + handleEvents(events) { + is(events.length, 1, "Right number of visits notified"); + is(events[0].type, "page-visited"); + let { url, visitId, visitTime, referringVisitId, transitionType } = + events[0]; + this.onVisit(url, visitId, visitTime, referringVisitId, transitionType); + }, + }; + observer.handleEvents = observer.handleEvents.bind(observer); + PlacesObservers.addListener(["page-visited"], observer.handleEvents); + }); + + PlacesUtils.history.markPageAsTyped(TEST_URI); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: TEST_URI.spec, + }, + async function (browser) { + // Load begin page, click link on page to record visits. + await BrowserTestUtils.synthesizeMouseAtCenter("#clickme", {}, browser); + + await promiseVisits; + } + ); + + await PlacesUtils.history.clear(); +}); diff --git a/toolkit/components/places/tests/browser/browser_favicon_privatebrowsing_perwindowpb.js b/toolkit/components/places/tests/browser/browser_favicon_privatebrowsing_perwindowpb.js new file mode 100644 index 0000000000..35450f0be6 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_favicon_privatebrowsing_perwindowpb.js @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function test() { + waitForExplicitFinish(); + + const pageURI = + "http://example.org/tests/toolkit/components/places/tests/browser/favicon.html"; + let windowsToClose = []; + + registerCleanupFunction(function () { + windowsToClose.forEach(function (aWin) { + aWin.close(); + }); + }); + + function testOnWindow(aIsPrivate, aCallback) { + whenNewWindowLoaded({ private: aIsPrivate }, function (aWin) { + windowsToClose.push(aWin); + executeSoon(() => aCallback(aWin)); + }); + } + + function waitForTabLoad(aWin, aCallback) { + BrowserTestUtils.browserLoaded(aWin.gBrowser.selectedBrowser).then( + aCallback + ); + BrowserTestUtils.loadURIString(aWin.gBrowser.selectedBrowser, pageURI); + } + + testOnWindow(true, function (win) { + waitForTabLoad(win, function () { + PlacesUtils.favicons.getFaviconURLForPage( + NetUtil.newURI(pageURI), + function (uri, dataLen, data, mimeType) { + is(uri, null, "No result should be found"); + finish(); + } + ); + }); + }); +} diff --git a/toolkit/components/places/tests/browser/browser_history_post.js b/toolkit/components/places/tests/browser/browser_history_post.js new file mode 100644 index 0000000000..a62592516f --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_history_post.js @@ -0,0 +1,35 @@ +const PAGE_URI = + "http://example.com/tests/toolkit/components/places/tests/browser/history_post.html"; +const SJS_URI = NetUtil.newURI( + "http://example.com/tests/toolkit/components/places/tests/browser/history_post.sjs" +); + +add_task(async function () { + await BrowserTestUtils.withNewTab( + { gBrowser, url: PAGE_URI }, + async function (aBrowser) { + await SpecialPowers.spawn(aBrowser, [], async function () { + let doc = content.document; + let submit = doc.getElementById("submit"); + let iframe = doc.getElementById("post_iframe"); + let p = new Promise((resolve, reject) => { + iframe.addEventListener( + "load", + function () { + resolve(); + }, + { once: true } + ); + }); + submit.click(); + await p; + }); + let visited = await PlacesUtils.history.hasVisits(SJS_URI); + ok(!visited, "The POST page should not be added to history"); + ok( + !(await PlacesTestUtils.isPageInDB(SJS_URI.spec)), + "The page should not be in the database" + ); + } + ); +}); diff --git a/toolkit/components/places/tests/browser/browser_multi_redirect_frecency.js b/toolkit/components/places/tests/browser/browser_multi_redirect_frecency.js new file mode 100644 index 0000000000..a406422a2f --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_multi_redirect_frecency.js @@ -0,0 +1,177 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const ROOT_URI = + "http://mochi.test:8888/tests/toolkit/components/places/tests/browser/"; +const REDIRECT_URI = Services.io.newURI(ROOT_URI + "redirect_thrice.sjs"); +const INTERMEDIATE_URI_1 = Services.io.newURI( + ROOT_URI + "redirect_twice_perma.sjs" +); +const INTERMEDIATE_URI_2 = Services.io.newURI(ROOT_URI + "redirect_once.sjs"); +const TARGET_URI = Services.io.newURI( + "http://test1.example.com/tests/toolkit/components/places/tests/browser/final.html" +); + +const REDIRECT_SOURCE_VISIT_BONUS = Services.prefs.getIntPref( + "places.frecency.redirectSourceVisitBonus" +); +const PERM_REDIRECT_VISIT_BONUS = Services.prefs.getIntPref( + "places.frecency.permRedirectVisitBonus" +); +const TYPED_VISIT_BONUS = Services.prefs.getIntPref( + "places.frecency.typedVisitBonus" +); + +// Ensure that decay frecency doesn't kick in during tests (as a result +// of idle-daily). +Services.prefs.setCharPref("places.frecency.decayRate", "1.0"); + +registerCleanupFunction(async function () { + Services.prefs.clearUserPref("places.frecency.decayRate"); + await PlacesUtils.history.clear(); +}); + +async function check_uri(uri, frecency, hidden) { + is( + await PlacesTestUtils.getDatabaseValue("moz_places", "frecency", { + url: uri, + }), + frecency, + "Frecency of the page is the expected one" + ); + is( + await PlacesTestUtils.getDatabaseValue("moz_places", "hidden", { + url: uri, + }), + hidden, + "Hidden value of the page is the expected one" + ); +} + +async function waitVisitedNotifications() { + let redirectNotified = false; + await PlacesTestUtils.waitForNotification("page-visited", visits => { + is(visits.length, 1, "Was notified for the right number of visits."); + let { url } = visits[0]; + info("Received 'page-visited': " + url); + if (url == REDIRECT_URI.spec) { + redirectNotified = true; + } + return url == TARGET_URI.spec; + }); + return redirectNotified; +} + +let firstRedirectBonus = 0; +let nextRedirectBonus = 0; +let targetBonus = 0; + +add_task(async function test_multiple_redirect() { + // The redirect source bonus overrides the link bonus. + let visitedPromise = waitVisitedNotifications(); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: REDIRECT_URI.spec, + }, + async function () { + info("Waiting for onVisits"); + let redirectNotified = await visitedPromise; + ok(redirectNotified, "The redirect should have been notified"); + + firstRedirectBonus += REDIRECT_SOURCE_VISIT_BONUS; + await check_uri(REDIRECT_URI, firstRedirectBonus, 1); + nextRedirectBonus += REDIRECT_SOURCE_VISIT_BONUS; + await check_uri(INTERMEDIATE_URI_1, nextRedirectBonus, 1); + await check_uri(INTERMEDIATE_URI_2, nextRedirectBonus, 1); + // TODO Bug 487813 - This should be TYPED_VISIT_BONUS, however as we don't + // currently track redirects across multiple redirects, we fallback to the + // PERM_REDIRECT_VISIT_BONUS. + targetBonus += PERM_REDIRECT_VISIT_BONUS; + await check_uri(TARGET_URI, targetBonus, 0); + } + ); +}); + +add_task(async function test_multiple_redirect_typed() { + // The typed bonus wins because the redirect is permanent. + PlacesUtils.history.markPageAsTyped(REDIRECT_URI); + let visitedPromise = waitVisitedNotifications(); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: REDIRECT_URI.spec, + }, + async function () { + info("Waiting for onVisits"); + let redirectNotified = await visitedPromise; + ok(redirectNotified, "The redirect should have been notified"); + + firstRedirectBonus += TYPED_VISIT_BONUS; + await check_uri(REDIRECT_URI, firstRedirectBonus, 1); + nextRedirectBonus += REDIRECT_SOURCE_VISIT_BONUS; + await check_uri(INTERMEDIATE_URI_1, nextRedirectBonus, 1); + await check_uri(INTERMEDIATE_URI_2, nextRedirectBonus, 1); + // TODO Bug 487813 - This should be TYPED_VISIT_BONUS, however as we don't + // currently track redirects across multiple redirects, we fallback to the + // PERM_REDIRECT_VISIT_BONUS. + targetBonus += PERM_REDIRECT_VISIT_BONUS; + await check_uri(TARGET_URI, targetBonus, 0); + } + ); +}); + +add_task(async function test_second_typed_visit() { + // The typed bonus wins because the redirect is permanent. + PlacesUtils.history.markPageAsTyped(REDIRECT_URI); + let visitedPromise = waitVisitedNotifications(); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: REDIRECT_URI.spec, + }, + async function () { + info("Waiting for onVisits"); + let redirectNotified = await visitedPromise; + ok(redirectNotified, "The redirect should have been notified"); + + firstRedirectBonus += TYPED_VISIT_BONUS; + await check_uri(REDIRECT_URI, firstRedirectBonus, 1); + nextRedirectBonus += REDIRECT_SOURCE_VISIT_BONUS; + await check_uri(INTERMEDIATE_URI_1, nextRedirectBonus, 1); + await check_uri(INTERMEDIATE_URI_2, nextRedirectBonus, 1); + // TODO Bug 487813 - This should be TYPED_VISIT_BONUS, however as we don't + // currently track redirects across multiple redirects, we fallback to the + // PERM_REDIRECT_VISIT_BONUS. + targetBonus += PERM_REDIRECT_VISIT_BONUS; + await check_uri(TARGET_URI, targetBonus, 0); + } + ); +}); + +add_task(async function test_subsequent_link_visit() { + // Another non typed visit. + let visitedPromise = waitVisitedNotifications(); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: REDIRECT_URI.spec, + }, + async function () { + info("Waiting for onVisits"); + let redirectNotified = await visitedPromise; + ok(redirectNotified, "The redirect should have been notified"); + + firstRedirectBonus += REDIRECT_SOURCE_VISIT_BONUS; + await check_uri(REDIRECT_URI, firstRedirectBonus, 1); + nextRedirectBonus += REDIRECT_SOURCE_VISIT_BONUS; + await check_uri(INTERMEDIATE_URI_1, nextRedirectBonus, 1); + await check_uri(INTERMEDIATE_URI_2, nextRedirectBonus, 1); + // TODO Bug 487813 - This should be TYPED_VISIT_BONUS, however as we don't + // currently track redirects across multiple redirects, we fallback to the + // PERM_REDIRECT_VISIT_BONUS. + targetBonus += PERM_REDIRECT_VISIT_BONUS; + await check_uri(TARGET_URI, targetBonus, 0); + } + ); +}); diff --git a/toolkit/components/places/tests/browser/browser_notfound.js b/toolkit/components/places/tests/browser/browser_notfound.js new file mode 100644 index 0000000000..6f53866018 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_notfound.js @@ -0,0 +1,38 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function () { + const TEST_URL = "http://mochi.test:8888/notFoundPage.html"; + + // Used to verify errors are not marked as typed. + PlacesUtils.history.markPageAsTyped(NetUtil.newURI(TEST_URL)); + + // Create and add history observer. + let visitedPromise = new Promise(resolve => { + function listener(aEvents) { + is(aEvents.length, 1, "Right number of visits notified"); + is(aEvents[0].type, "page-visited"); + let uri = NetUtil.newURI(aEvents[0].url); + PlacesObservers.removeListener(["page-visited"], listener); + info("Received 'page-visited': " + uri.spec); + fieldForUrl(uri, "frecency", function (aFrecency) { + is(aFrecency, 0, "Frecency should be 0"); + fieldForUrl(uri, "hidden", function (aHidden) { + is(aHidden, 0, "Page should not be hidden"); + fieldForUrl(uri, "typed", function (aTyped) { + is(aTyped, 0, "page should not be marked as typed"); + resolve(); + }); + }); + }); + } + PlacesObservers.addListener(["page-visited"], listener); + }); + + let newTabPromise = BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL); + await Promise.all([visitedPromise, newTabPromise]); + + await PlacesUtils.history.clear(); + gBrowser.removeCurrentTab(); +}); diff --git a/toolkit/components/places/tests/browser/browser_onvisit_title_null_for_navigation.js b/toolkit/components/places/tests/browser/browser_onvisit_title_null_for_navigation.js new file mode 100644 index 0000000000..a7c583975a --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_onvisit_title_null_for_navigation.js @@ -0,0 +1,41 @@ +const TEST_PATH = getRootDirectory(gTestPath).replace( + "chrome://mochitests/content", + "http://example.com" +); + +add_task(async function checkTitleNotificationForNavigation() { + const EXPECTED_URL = Services.io.newURI(TEST_PATH + "empty_page.html"); + + const promiseVisit = PlacesTestUtils.waitForNotification( + "page-visited", + events => events[0].url === EXPECTED_URL.spec + ); + + const promiseTitle = PlacesTestUtils.waitForNotification( + "page-title-changed", + events => events[0].url === EXPECTED_URL.spec + ); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + EXPECTED_URL.spec + ); + + const visitEvents = await promiseVisit; + Assert.equal(visitEvents.length, 1, "Right number of visits notified"); + Assert.equal(visitEvents[0].type, "page-visited"); + info("'page-visited': " + visitEvents[0].url); + Assert.equal(visitEvents[0].lastKnownTitle, null, "Should not have a title"); + + const titleEvents = await promiseTitle; + Assert.equal(titleEvents.length, 1, "Right number of title changed notified"); + Assert.equal(titleEvents[0].type, "page-title-changed"); + info("'page-title-changed': " + titleEvents[0].url); + Assert.equal( + titleEvents[0].title, + "I am an empty page", + "Should have correct title in titlechanged notification" + ); + + BrowserTestUtils.removeTab(tab); +}); diff --git a/toolkit/components/places/tests/browser/browser_redirect.js b/toolkit/components/places/tests/browser/browser_redirect.js new file mode 100644 index 0000000000..912b817ad1 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_redirect.js @@ -0,0 +1,149 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const ROOT_URI = + "http://mochi.test:8888/tests/toolkit/components/places/tests/browser/"; +const REDIRECT_URI = Services.io.newURI(ROOT_URI + "redirect.sjs"); +const TARGET_URI = Services.io.newURI(ROOT_URI + "redirect-target.html"); + +const REDIRECT_SOURCE_VISIT_BONUS = Services.prefs.getIntPref( + "places.frecency.redirectSourceVisitBonus" +); +const LINK_VISIT_BONUS = Services.prefs.getIntPref( + "places.frecency.linkVisitBonus" +); +const TYPED_VISIT_BONUS = Services.prefs.getIntPref( + "places.frecency.typedVisitBonus" +); + +// Ensure that decay frecency doesn't kick in during tests (as a result +// of idle-daily). +Services.prefs.setCharPref("places.frecency.decayRate", "1.0"); + +registerCleanupFunction(async function () { + Services.prefs.clearUserPref("places.frecency.decayRate"); + await PlacesUtils.history.clear(); +}); + +let redirectSourceFrecency = 0; +let redirectTargetFrecency = 0; + +async function check_uri(uri, frecency, hidden) { + is( + await PlacesTestUtils.getDatabaseValue("moz_places", "frecency", { + url: uri, + }), + frecency, + "Frecency of the page is the expected one" + ); + is( + await PlacesTestUtils.getDatabaseValue("moz_places", "hidden", { + url: uri, + }), + hidden, + "Hidden value of the page is the expected one" + ); +} + +add_task(async function redirect_check_new_typed_visit() { + // Used to verify the redirect bonus overrides the typed bonus. + PlacesUtils.history.markPageAsTyped(REDIRECT_URI); + + redirectSourceFrecency += REDIRECT_SOURCE_VISIT_BONUS; + redirectTargetFrecency += TYPED_VISIT_BONUS; + let redirectNotified = false; + + let visitedPromise = PlacesTestUtils.waitForNotification( + "page-visited", + visits => { + is(visits.length, 1, "Was notified for the right number of visits."); + let { url } = visits[0]; + info("Received 'page-visited': " + url); + if (url == REDIRECT_URI.spec) { + redirectNotified = true; + } + return url == TARGET_URI.spec; + } + ); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + REDIRECT_URI.spec + ); + info("Waiting for onVisits"); + await visitedPromise; + ok(redirectNotified, "The redirect should have been notified"); + + await check_uri(REDIRECT_URI, redirectSourceFrecency, 1); + await check_uri(TARGET_URI, redirectTargetFrecency, 0); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function redirect_check_second_typed_visit() { + // A second visit with a typed url. + PlacesUtils.history.markPageAsTyped(REDIRECT_URI); + + redirectSourceFrecency += REDIRECT_SOURCE_VISIT_BONUS; + redirectTargetFrecency += TYPED_VISIT_BONUS; + let redirectNotified = false; + + let visitedPromise = PlacesTestUtils.waitForNotification( + "page-visited", + visits => { + is(visits.length, 1, "Was notified for the right number of visits."); + let { url } = visits[0]; + info("Received 'page-visited': " + url); + if (url == REDIRECT_URI.spec) { + redirectNotified = true; + } + return url == TARGET_URI.spec; + } + ); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + REDIRECT_URI.spec + ); + info("Waiting for onVisits"); + await visitedPromise; + ok(redirectNotified, "The redirect should have been notified"); + + await check_uri(REDIRECT_URI, redirectSourceFrecency, 1); + await check_uri(TARGET_URI, redirectTargetFrecency, 0); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function redirect_check_subsequent_link_visit() { + // Another visit, but this time as a visited url. + redirectSourceFrecency += REDIRECT_SOURCE_VISIT_BONUS; + redirectTargetFrecency += LINK_VISIT_BONUS; + let redirectNotified = false; + + let visitedPromise = PlacesTestUtils.waitForNotification( + "page-visited", + visits => { + is(visits.length, 1, "Was notified for the right number of visits."); + let { url } = visits[0]; + info("Received 'page-visited': " + url); + if (url == REDIRECT_URI.spec) { + redirectNotified = true; + } + return url == TARGET_URI.spec; + } + ); + + let tab = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + REDIRECT_URI.spec + ); + info("Waiting for onVisits"); + await visitedPromise; + ok(redirectNotified, "The redirect should have been notified"); + + await check_uri(REDIRECT_URI, redirectSourceFrecency, 1); + await check_uri(TARGET_URI, redirectTargetFrecency, 0); + + BrowserTestUtils.removeTab(tab); +}); diff --git a/toolkit/components/places/tests/browser/browser_redirect_self.js b/toolkit/components/places/tests/browser/browser_redirect_self.js new file mode 100644 index 0000000000..7ed7ee0af0 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_redirect_self.js @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Tests a page that redirects to itself. On the initial visit the page should + * be marked as hidden, but then the second visit should unhide it. + * This ensures that that the history anti-flooding system doesn't skip the + * second visit. + */ + +add_task(async function () { + await PlacesUtils.history.clear(); + Cc["@mozilla.org/browser/history;1"] + .getService(Ci.mozIAsyncHistory) + .clearCache(); + const url = + "http://mochi.test:8888/tests/toolkit/components/places/tests/browser/redirect_self.sjs"; + let visitCount = 0; + function onVisitsListener(events) { + visitCount++; + Assert.equal(events.length, 1, "Right number of visits notified"); + Assert.equal(events[0].url, url, "Got a visit for the expected url"); + if (visitCount == 1) { + Assert.ok(events[0].hidden, "The visit should be hidden"); + } else { + Assert.ok(!events[0].hidden, "The visit should not be hidden"); + } + } + PlacesObservers.addListener(["page-visited"], onVisitsListener); + registerCleanupFunction(async function () { + PlacesObservers.removeListener(["page-visited"], onVisitsListener); + await PlacesUtils.history.clear(); + }); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url, + }, + async browser => { + await TestUtils.waitForCondition(() => visitCount == 2); + // Check that the visit is not hidden in the database. + Assert.ok( + !(await PlacesTestUtils.getDatabaseValue("moz_places", "hidden", { + url, + })), + "The url should not be hidden in the database" + ); + } + ); +}); diff --git a/toolkit/components/places/tests/browser/browser_settitle.js b/toolkit/components/places/tests/browser/browser_settitle.js new file mode 100644 index 0000000000..3519891bbe --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_settitle.js @@ -0,0 +1,48 @@ +var conn = PlacesUtils.history.DBConnection; + +/** + * Gets a single column value from either the places or historyvisits table. + */ +function getColumn(table, column, url) { + var stmt = conn.createStatement( + `SELECT ${column} FROM ${table} WHERE url_hash = hash(:val) AND url = :val` + ); + try { + stmt.params.val = url; + stmt.executeStep(); + return stmt.row[column]; + } finally { + stmt.finalize(); + } +} + +add_task(async function () { + // Make sure titles are correctly saved for a URI with the proper + // notifications. + const titleChangedPromise = + PlacesTestUtils.waitForNotification("page-title-changed"); + + const url1 = + "http://example.com/tests/toolkit/components/places/tests/browser/title1.html"; + await BrowserTestUtils.openNewForegroundTab(gBrowser, url1); + + const url2 = + "http://example.com/tests/toolkit/components/places/tests/browser/title2.html"; + let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); + BrowserTestUtils.loadURIString(gBrowser.selectedBrowser, url2); + await loadPromise; + + const events = await titleChangedPromise; + is( + events[0].url, + "http://example.com/tests/toolkit/components/places/tests/browser/title2.html" + ); + is(events[0].title, "Some title"); + is(events[0].pageGuid, getColumn("moz_places", "guid", events[0].url)); + + const title = getColumn("moz_places", "title", events[0].url); + is(title, events[0].title); + + gBrowser.removeCurrentTab(); + await PlacesUtils.history.clear(); +}); diff --git a/toolkit/components/places/tests/browser/browser_visited_notfound.js b/toolkit/components/places/tests/browser/browser_visited_notfound.js new file mode 100644 index 0000000000..1b97c307e2 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_visited_notfound.js @@ -0,0 +1,60 @@ +add_task(async function test() { + const TEST_URL = "http://mochi.test:8888/notFoundPage.html"; + // Ensure that decay frecency doesn't kick in during tests (as a result + // of idle-daily). + Services.prefs.setCharPref("places.frecency.decayRate", "1.0"); + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser); + registerCleanupFunction(async function () { + Services.prefs.clearUserPref("places.frecency.decayRate"); + BrowserTestUtils.removeTab(tab); + await PlacesUtils.history.clear(); + }); + + // First add a visit to the page, this will ensure that later we skip + // updating the frecency for a newly not-found page. + await PlacesTestUtils.addVisits({ uri: TEST_URL }); + let frecency = await PlacesTestUtils.getDatabaseValue( + "moz_places", + "frecency", + { url: TEST_URL } + ); + is(frecency, 100, "Check initial frecency"); + + // Used to verify errors are not marked as typed. + PlacesUtils.history.markPageAsTyped(NetUtil.newURI(TEST_URL)); + + let promiseVisit = new Promise(resolve => { + function onVisits(events) { + PlacesObservers.removeListener(["page-visited"], onVisits); + is(events.length, 1, "Right number of visits"); + is(events[0].type, "page-visited"); + is(events[0].url, TEST_URL, "Check visited url"); + resolve(); + } + PlacesObservers.addListener(["page-visited"], onVisits); + }); + BrowserTestUtils.loadURIString(gBrowser.selectedBrowser, TEST_URL); + await promiseVisit; + + is( + await PlacesTestUtils.getDatabaseValue("moz_places", "frecency", { + url: TEST_URL, + }), + frecency, + "Frecency should be unchanged" + ); + is( + await PlacesTestUtils.getDatabaseValue("moz_places", "hidden", { + url: TEST_URL, + }), + 0, + "Page should not be hidden" + ); + is( + await PlacesTestUtils.getDatabaseValue("moz_places", "typed", { + url: TEST_URL, + }), + 0, + "page should not be marked as typed" + ); +}); diff --git a/toolkit/components/places/tests/browser/browser_visituri.js b/toolkit/components/places/tests/browser/browser_visituri.js new file mode 100644 index 0000000000..6633ac188b --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_visituri.js @@ -0,0 +1,100 @@ +/** + * 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(); +}); diff --git a/toolkit/components/places/tests/browser/browser_visituri_nohistory.js b/toolkit/components/places/tests/browser/browser_visituri_nohistory.js new file mode 100644 index 0000000000..3708b388e5 --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_visituri_nohistory.js @@ -0,0 +1,44 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +const INITIAL_URL = + "http://example.com/tests/toolkit/components/places/tests/browser/begin.html"; +const FINAL_URL = + "http://test1.example.com/tests/toolkit/components/places/tests/browser/final.html"; + +/** + * One-time observer callback. + */ +function promiseObserve(name) { + return new Promise(resolve => { + Services.obs.addObserver(function observer(subject) { + Services.obs.removeObserver(observer, name); + resolve(subject); + }, name); + }); +} + +add_task(async function () { + await SpecialPowers.pushPrefEnv({ set: [["places.history.enabled", false]] }); + + let visitUriPromise = promiseObserve("uri-visit-saved"); + + await BrowserTestUtils.openNewForegroundTab(gBrowser, INITIAL_URL); + + await SpecialPowers.popPrefEnv(); + + let browserLoadedPromise = BrowserTestUtils.browserLoaded( + gBrowser.selectedBrowser + ); + BrowserTestUtils.loadURIString(gBrowser, FINAL_URL); + await browserLoadedPromise; + + let subject = await visitUriPromise; + let uri = subject.QueryInterface(Ci.nsIURI); + is(uri.spec, FINAL_URL, "received expected visit"); + + await PlacesUtils.history.clear(); + gBrowser.removeCurrentTab(); +}); diff --git a/toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js b/toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js new file mode 100644 index 0000000000..75fd2aa46d --- /dev/null +++ b/toolkit/components/places/tests/browser/browser_visituri_privatebrowsing_perwindowpb.js @@ -0,0 +1,63 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const initialURL = + "http://example.com/tests/toolkit/components/places/tests/browser/begin.html"; +const finalURL = + "http://test1.example.com/tests/toolkit/components/places/tests/browser/final.html"; + +var observer; +var visitSavedPromise; + +add_setup(async function () { + visitSavedPromise = new Promise(resolve => { + observer = { + observe(subject, topic, data) { + // The uri-visit-saved topic should only work when on normal mode. + if (topic == "uri-visit-saved") { + Services.obs.removeObserver(observer, "uri-visit-saved"); + + // The expected visit should be the finalURL because private mode + // should not register a visit with the initialURL. + let uri = subject.QueryInterface(Ci.nsIURI); + resolve(uri.spec); + } + }, + }; + }); + + Services.obs.addObserver(observer, "uri-visit-saved"); + + registerCleanupFunction(async function () { + await PlacesUtils.history.clear(); + }); +}); + +// Note: The private window test must be the first one to run, since we'll listen +// to the first uri-visit-saved notification, and we expect this test to not +// fire any, so we'll just find the non-private window test notification. +add_task(async function test_private_browsing_window() { + await testLoadInWindow({ private: true }, initialURL); +}); + +add_task(async function test_normal_window() { + await testLoadInWindow({ private: false }, finalURL); + + let url = await visitSavedPromise; + Assert.equal(url, finalURL, "Check received expected visit"); +}); + +async function testLoadInWindow(options, url) { + let win = await BrowserTestUtils.openNewBrowserWindow(options); + + registerCleanupFunction(async function () { + await BrowserTestUtils.closeWindow(win); + }); + + let loadedPromise = BrowserTestUtils.browserLoaded( + win.gBrowser.selectedBrowser + ); + BrowserTestUtils.loadURIString(win.gBrowser.selectedBrowser, url); + await loadedPromise; +} diff --git a/toolkit/components/places/tests/browser/empty_page.html b/toolkit/components/places/tests/browser/empty_page.html new file mode 100644 index 0000000000..ac9d144cb4 --- /dev/null +++ b/toolkit/components/places/tests/browser/empty_page.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>I am an empty page</title> + </head> + <body>Empty</body> +</html> diff --git a/toolkit/components/places/tests/browser/favicon-normal16.png b/toolkit/components/places/tests/browser/favicon-normal16.png Binary files differnew file mode 100644 index 0000000000..62b69a3d03 --- /dev/null +++ b/toolkit/components/places/tests/browser/favicon-normal16.png diff --git a/toolkit/components/places/tests/browser/favicon-normal32.png b/toolkit/components/places/tests/browser/favicon-normal32.png Binary files differnew file mode 100644 index 0000000000..5535363c94 --- /dev/null +++ b/toolkit/components/places/tests/browser/favicon-normal32.png diff --git a/toolkit/components/places/tests/browser/favicon.html b/toolkit/components/places/tests/browser/favicon.html new file mode 100644 index 0000000000..a0f5ea9594 --- /dev/null +++ b/toolkit/components/places/tests/browser/favicon.html @@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<html> + <head> + <link rel="shortcut icon" href="http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png"> + </head> + <body> + OK we're done! + </body> +</html> diff --git a/toolkit/components/places/tests/browser/final.html b/toolkit/components/places/tests/browser/final.html new file mode 100644 index 0000000000..ccd5819181 --- /dev/null +++ b/toolkit/components/places/tests/browser/final.html @@ -0,0 +1,10 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<html> + <body> + OK we're done! + </body> +</html> diff --git a/toolkit/components/places/tests/browser/head.js b/toolkit/components/places/tests/browser/head.js new file mode 100644 index 0000000000..e4d0b5566b --- /dev/null +++ b/toolkit/components/places/tests/browser/head.js @@ -0,0 +1,74 @@ +ChromeUtils.defineESModuleGetters(this, { + PlacesTestUtils: "resource://testing-common/PlacesTestUtils.sys.mjs", +}); + +const TRANSITION_LINK = PlacesUtils.history.TRANSITION_LINK; +const TRANSITION_TYPED = PlacesUtils.history.TRANSITION_TYPED; +const TRANSITION_BOOKMARK = PlacesUtils.history.TRANSITION_BOOKMARK; +const TRANSITION_REDIRECT_PERMANENT = + PlacesUtils.history.TRANSITION_REDIRECT_PERMANENT; +const TRANSITION_REDIRECT_TEMPORARY = + PlacesUtils.history.TRANSITION_REDIRECT_TEMPORARY; +const TRANSITION_EMBED = PlacesUtils.history.TRANSITION_EMBED; +const TRANSITION_FRAMED_LINK = PlacesUtils.history.TRANSITION_FRAMED_LINK; +const TRANSITION_DOWNLOAD = PlacesUtils.history.TRANSITION_DOWNLOAD; + +/** + * Returns a moz_places field value for a url. + * + * @param {nsIURI|String} aURI + * The URI or spec to get field for. + * @param {String} aFieldName + * The field name to get the value of. + * @param {Function} aCallback + * Callback function that will get the property value. + */ +function fieldForUrl(aURI, aFieldName, aCallback) { + let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI; + let stmt = PlacesUtils.history.DBConnection.createAsyncStatement( + `SELECT ${aFieldName} FROM moz_places WHERE url_hash = hash(:page_url) AND url = :page_url` + ); + stmt.params.page_url = url; + stmt.executeAsync({ + _value: -1, + handleResult(aResultSet) { + let row = aResultSet.getNextRow(); + if (!row) { + ok(false, "The page should exist in the database"); + } + this._value = row.getResultByName(aFieldName); + }, + handleError() {}, + handleCompletion(aReason) { + if (aReason != Ci.mozIStorageStatementCallback.REASON_FINISHED) { + ok(false, "The statement should properly succeed"); + } + aCallback(this._value); + }, + }); + stmt.finalize(); +} + +/** + * Promise wrapper for fieldForUrl. + * + * @param {nsIURI|String} aURI + * The URI or spec to get field for. + * @param {String} aFieldName + * The field name to get the value of. + * @return {Promise} + * A promise that is resolved with the value of the field. + */ +function promiseFieldForUrl(aURI, aFieldName) { + return new Promise(resolve => { + function callback(result) { + resolve(result); + } + fieldForUrl(aURI, aFieldName, callback); + }); +} + +function whenNewWindowLoaded(aOptions, aCallback) { + BrowserTestUtils.waitForNewWindow().then(aCallback); + OpenBrowserWindow(aOptions); +} diff --git a/toolkit/components/places/tests/browser/history_post.html b/toolkit/components/places/tests/browser/history_post.html new file mode 100644 index 0000000000..a579a9b8ae --- /dev/null +++ b/toolkit/components/places/tests/browser/history_post.html @@ -0,0 +1,12 @@ +<!DOCTYPE HTML> +<html> + <head> + <title>Test post pages are not added to history</title> + </head> + <body> + <iframe name="post_iframe" id="post_iframe"></iframe> + <form method="post" action="http://example.com/tests/toolkit/components/places/tests/browser/history_post.sjs" target="post_iframe"> + <input type="submit" id="submit"/> + </form> + </body> +</html> diff --git a/toolkit/components/places/tests/browser/history_post.sjs b/toolkit/components/places/tests/browser/history_post.sjs new file mode 100644 index 0000000000..08c1afe853 --- /dev/null +++ b/toolkit/components/places/tests/browser/history_post.sjs @@ -0,0 +1,5 @@ +function handleRequest(request, response) { + response.setStatusLine("1.0", 200, "OK"); + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + response.write("Ciao"); +} diff --git a/toolkit/components/places/tests/browser/previews/browser.ini b/toolkit/components/places/tests/browser/previews/browser.ini new file mode 100644 index 0000000000..dd77faa323 --- /dev/null +++ b/toolkit/components/places/tests/browser/previews/browser.ini @@ -0,0 +1,11 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +[DEFAULT] +prefs = + browser.pagethumbnails.capturing_disabled=false + places.previews.enabled=true + places.previews.log=true + +[browser_thumbnails.js] diff --git a/toolkit/components/places/tests/browser/previews/browser_thumbnails.js b/toolkit/components/places/tests/browser/previews/browser_thumbnails.js new file mode 100644 index 0000000000..ef776694c2 --- /dev/null +++ b/toolkit/components/places/tests/browser/previews/browser_thumbnails.js @@ -0,0 +1,174 @@ +/* Any copyright is dedicated to the Public Domain. + * https://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests PlacesPreviews.jsm + */ +const { PlacesPreviews } = ChromeUtils.importESModule( + "resource://gre/modules/PlacesPreviews.sys.mjs" +); +const { PlacesTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PlacesTestUtils.sys.mjs" +); + +const TEST_URL1 = "http://example.com/"; +const TEST_URL2 = "http://example.org/"; + +/** + * Counts tombstone entries. + * @returns {integer} number of tombstone entries. + */ +async function countTombstones() { + await PlacesTestUtils.promiseAsyncUpdates(); + let db = await PlacesUtils.promiseDBConnection(); + return ( + await db.execute("SELECT count(*) FROM moz_previews_tombstones") + )[0].getResultByIndex(0); +} + +add_task(async function test_thumbnail() { + registerCleanupFunction(async () => { + await PlacesUtils.history.clear(); + // Ensure tombstones table has been emptied. + await TestUtils.waitForCondition(async () => { + return (await countTombstones()) == 0; + }); + PlacesPreviews.testSetDeletionTimeout(null); + }); + // Sanity check initial state. + Assert.equal(await countTombstones(), 0, "There's no tombstone entries"); + + info("Test preview creation and storage."); + await BrowserTestUtils.withNewTab(TEST_URL1, async browser => { + await retryUpdatePreview(browser.currentURI.spec); + let filePath = PlacesPreviews.getPathForUrl(TEST_URL1); + Assert.ok(await IOUtils.exists(filePath), "The screenshot exists"); + Assert.equal( + filePath.substring(filePath.lastIndexOf(".")), + PlacesPreviews.fileExtension, + "Check extension" + ); + await testImageFile(filePath); + await testMozPageThumb(TEST_URL1); + }); +}); + +add_task(async function test_page_removal() { + info("Store another preview and test page removal."); + await BrowserTestUtils.withNewTab(TEST_URL2, async browser => { + await retryUpdatePreview(browser.currentURI.spec); + let filePath = PlacesPreviews.getPathForUrl(TEST_URL2); + Assert.ok(await IOUtils.exists(filePath), "The screenshot exists"); + }); + + // Set deletion time to a small value so it runs immediately. + PlacesPreviews.testSetDeletionTimeout(0); + info("Wait for deletion, check one preview is removed, not the other one."); + let promiseDeleted = new Promise(resolve => { + PlacesPreviews.once("places-preview-deleted", (topic, filePath) => { + resolve(filePath); + }); + }); + await PlacesUtils.history.remove(TEST_URL1); + + let deletedFilePath = await promiseDeleted; + Assert.ok( + !(await IOUtils.exists(deletedFilePath)), + "Check deleted file has been removed" + ); + + info("Check tombstones table has been emptied."); + Assert.equal(await countTombstones(), 0, "There's no tombstone entries"); + + info("Check the other thumbnail has not been removed."); + let path = PlacesPreviews.getPathForUrl(TEST_URL2); + Assert.ok(await IOUtils.exists(path), "Check non-deleted url is still there"); + await testImageFile(path); + await testMozPageThumb(TEST_URL2); +}); + +add_task(async function async_test_deleteOrphans() { + let path = PlacesPreviews.getPathForUrl(TEST_URL2); + Assert.ok(await IOUtils.exists(path), "Sanity check one preview exists"); + // Create a file in the given path that doesn't have an entry in Places. + let fakePath = PathUtils.join( + PlacesPreviews.getPath(), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + PlacesPreviews.fileExtension + ); + // File contents don't matter. + await IOUtils.writeJSON(fakePath, { test: true }); + let promiseDeleted = new Promise(resolve => { + PlacesPreviews.once("places-preview-deleted", (topic, filePath) => { + resolve(filePath); + }); + }); + + await PlacesPreviews.deleteOrphans(); + let deletedFilePath = await promiseDeleted; + Assert.equal(deletedFilePath, fakePath, "Check orphan has been deleted"); + Assert.equal(await countTombstones(), 0, "There's no tombstone entries left"); + Assert.ok( + !(await IOUtils.exists(fakePath)), + "Ensure orphan has been deleted" + ); + + Assert.ok(await IOUtils.exists(path), "Ensure valid preview is still there"); +}); + +async function testImageFile(path) { + info("Load the file and check its content type."); + const buffer = await IOUtils.read(path); + const fourcc = new TextDecoder("utf-8").decode(buffer.slice(8, 12)); + Assert.equal(fourcc, "WEBP", "Check the stored preview is webp"); +} + +async function testMozPageThumb(url) { + info("Check moz-page-thumb protocol: " + PlacesPreviews.getPageThumbURL(url)); + let { data, contentType } = await fetchImage( + PlacesPreviews.getPageThumbURL(url) + ); + Assert.equal( + contentType, + PlacesPreviews.fileContentType, + "Check the content type" + ); + const fourcc = data.slice(8, 12); + Assert.equal(fourcc, "WEBP", "Check the returned preview is webp"); +} + +function fetchImage(url) { + return new Promise((resolve, reject) => { + NetUtil.asyncFetch( + { + uri: NetUtil.newURI(url), + loadUsingSystemPrincipal: true, + contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE, + }, + (input, status, request) => { + if (!Components.isSuccessCode(status)) { + reject(new Error("unable to load image")); + return; + } + + try { + let data = NetUtil.readInputStreamToString(input, input.available()); + let contentType = request.QueryInterface(Ci.nsIChannel).contentType; + input.close(); + resolve({ data, contentType }); + } catch (ex) { + reject(ex); + } + } + ); + }); +} + +/** + * Sometimes on macOS fetching the preview fails for timeout/network reasons, + * this retries so the test doesn't intermittently fail over it. + * @param {string} url The url to store a preview for. + * @returns {Promise} resolved once a preview has been captured. + */ +function retryUpdatePreview(url) { + return TestUtils.waitForCondition(() => PlacesPreviews.update(url)); +} diff --git a/toolkit/components/places/tests/browser/redirect-target.html b/toolkit/components/places/tests/browser/redirect-target.html new file mode 100644 index 0000000000..3700263385 --- /dev/null +++ b/toolkit/components/places/tests/browser/redirect-target.html @@ -0,0 +1 @@ +<!DOCTYPE html><html><body><p>Ciao!</p></body></html> diff --git a/toolkit/components/places/tests/browser/redirect.sjs b/toolkit/components/places/tests/browser/redirect.sjs new file mode 100644 index 0000000000..ab47335ffe --- /dev/null +++ b/toolkit/components/places/tests/browser/redirect.sjs @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function handleRequest(request, response) { + let page = "<!DOCTYPE html><html><body><p>Redirecting...</p></body></html>"; + + response.setStatusLine(request.httpVersion, "301", "Moved Permanently"); + response.setHeader("Content-Type", "text/html", false); + response.setHeader("Content-Length", page.length + "", false); + response.setHeader("Location", "redirect-target.html", false); + response.write(page); +} diff --git a/toolkit/components/places/tests/browser/redirect_once.sjs b/toolkit/components/places/tests/browser/redirect_once.sjs new file mode 100644 index 0000000000..b9ccd0829a --- /dev/null +++ b/toolkit/components/places/tests/browser/redirect_once.sjs @@ -0,0 +1,13 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function handleRequest(request, response) { + response.setStatusLine("1.1", 301, "Found"); + response.setHeader( + "Location", + "http://test1.example.com/tests/toolkit/components/places/tests/browser/final.html", + false + ); +} diff --git a/toolkit/components/places/tests/browser/redirect_self.sjs b/toolkit/components/places/tests/browser/redirect_self.sjs new file mode 100644 index 0000000000..953afe5f26 --- /dev/null +++ b/toolkit/components/places/tests/browser/redirect_self.sjs @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Script that redirects to itself once. + +function handleRequest(request, response) { + if ( + request.hasHeader("Cookie") && + request.getHeader("Cookie").includes("redirect-self") + ) { + response.setStatusLine("1.0", 200, "OK"); + // Expire the cookie. + response.setHeader( + "Set-Cookie", + "redirect-self=true; expires=Thu, 01 Jan 1970 00:00:00 GMT", + true + ); + response.setHeader("Content-Type", "text/plain; charset=utf-8", false); + response.write("OK"); + } else { + response.setStatusLine(request.httpVersion, 302, "Moved Temporarily"); + response.setHeader("Set-Cookie", "redirect-self=true", true); + response.setHeader("Location", "redirect_self.sjs"); + response.write("Moved Temporarily"); + } +} diff --git a/toolkit/components/places/tests/browser/redirect_thrice.sjs b/toolkit/components/places/tests/browser/redirect_thrice.sjs new file mode 100644 index 0000000000..55154a736e --- /dev/null +++ b/toolkit/components/places/tests/browser/redirect_thrice.sjs @@ -0,0 +1,9 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function handleRequest(request, response) { + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", "redirect_twice_perma.sjs", false); +} diff --git a/toolkit/components/places/tests/browser/redirect_twice.sjs b/toolkit/components/places/tests/browser/redirect_twice.sjs new file mode 100644 index 0000000000..099d20022e --- /dev/null +++ b/toolkit/components/places/tests/browser/redirect_twice.sjs @@ -0,0 +1,9 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function handleRequest(request, response) { + response.setStatusLine("1.1", 302, "Found"); + response.setHeader("Location", "redirect_once.sjs", false); +} diff --git a/toolkit/components/places/tests/browser/redirect_twice_perma.sjs b/toolkit/components/places/tests/browser/redirect_twice_perma.sjs new file mode 100644 index 0000000000..a40abd4170 --- /dev/null +++ b/toolkit/components/places/tests/browser/redirect_twice_perma.sjs @@ -0,0 +1,9 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +function handleRequest(request, response) { + response.setStatusLine("1.1", 301, "Found"); + response.setHeader("Location", "redirect_once.sjs", false); +} diff --git a/toolkit/components/places/tests/browser/title1.html b/toolkit/components/places/tests/browser/title1.html new file mode 100644 index 0000000000..3c98d693ec --- /dev/null +++ b/toolkit/components/places/tests/browser/title1.html @@ -0,0 +1,12 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<html> + <head> + </head> + <body> + title1.html + </body> +</html> diff --git a/toolkit/components/places/tests/browser/title2.html b/toolkit/components/places/tests/browser/title2.html new file mode 100644 index 0000000000..8830328796 --- /dev/null +++ b/toolkit/components/places/tests/browser/title2.html @@ -0,0 +1,13 @@ +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> + +<html> + <head> + <title>Some title</title> + </head> + <body> + title2.html + </body> +</html> |