summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/browser
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/places/tests/browser')
-rw-r--r--toolkit/components/places/tests/browser/browser.toml12
-rw-r--r--toolkit/components/places/tests/browser/browser_visituri_restriction.js227
-rw-r--r--toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js92
-rw-r--r--toolkit/components/places/tests/browser/head.js77
4 files changed, 408 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/browser/browser.toml b/toolkit/components/places/tests/browser/browser.toml
index b7d688c980..aceee48f24 100644
--- a/toolkit/components/places/tests/browser/browser.toml
+++ b/toolkit/components/places/tests/browser/browser.toml
@@ -117,3 +117,15 @@ support-files = [
"favicon.html",
"final.html",
]
+
+["browser_visituri_restriction.js"]
+skip-if = [
+ "verify",
+ "os == 'linux' && (asan || tsan)", # Bug 1891145
+]
+
+["browser_visituri_restriction_origin.js"]
+skip-if = [
+ "verify",
+ "os == 'linux' && (asan || tsan)", # Bug 1891145
+]
diff --git a/toolkit/components/places/tests/browser/browser_visituri_restriction.js b/toolkit/components/places/tests/browser/browser_visituri_restriction.js
new file mode 100644
index 0000000000..2af41e6f51
--- /dev/null
+++ b/toolkit/components/places/tests/browser/browser_visituri_restriction.js
@@ -0,0 +1,227 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+"use strict";
+
+const TEST_PAGE = `data:text/html,
+ <a href="https://example.com/" target="_blank">https://example.com</a>
+ <a href="http://example.com/" target="_blank">http://example.com</a>
+ <a href="https://www.example.com/" target="_blank">https://www.example.com</a>
+ <a href="https://example.org/" target="_blank">https://example.org</a>`;
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ // Enable restriction feature.
+ ["places.history.floodingPrevention.enabled", true],
+ // Restrict from the second visit.
+ ["places.history.floodingPrevention.restrictionCount", 1],
+ ["places.history.floodingPrevention.restrictionExpireSeconds", 4],
+ // Not apply flooding prevention until some seconds elapse after user
+ // interaction begins.
+ [
+ "places.history.floodingPrevention.maxSecondsFromLastUserInteraction",
+ 4,
+ ],
+ // To enable UserActivation by EventUtils.synthesizeMouseAtCenter() in
+ // ContentTask.spawn() in synthesizeVisitByUser().
+ ["test.events.async.enabled", true],
+ ],
+ });
+ await clearHistoryAndHistoryCache();
+});
+
+add_task(async function basic() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: TEST_PAGE },
+ async browser => {
+ info("Sanity check");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ await assertLinkVisitedStatus(browser, "https://www.example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ await assertLinkVisitedStatus(browser, "https://example.org/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+
+ info("Visit https://example.com/ by user");
+ await synthesizeVisitByUser(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 1,
+ isVisited: true,
+ });
+
+ info(
+ "Visit https://example.com/ by script within maxSecondsFromLastUserInteraction"
+ );
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 3,
+ isVisited: true,
+ });
+
+ await waitForPrefSeconds("maxSecondsFromLastUserInteraction");
+
+ info(
+ "Visit https://example.com/ by script without maxSecondsFromLastUserInteraction"
+ );
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 4,
+ isVisited: true,
+ });
+
+ info("Visit again, but it should be restricted");
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 4,
+ isVisited: true,
+ });
+
+ info("Check other");
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ await assertLinkVisitedStatus(browser, "http://example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ await assertLinkVisitedStatus(browser, "https://www.example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ await assertLinkVisitedStatus(browser, "https://example.org/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ }
+ );
+
+ await clearHistoryAndHistoryCache();
+});
+
+add_task(async function expireRestriction() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: TEST_PAGE },
+ async browser => {
+ info("Visit https://example.com/ by user");
+ await synthesizeVisitByUser(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 1,
+ isVisited: true,
+ });
+
+ info(
+ "Visit https://example.com/ by script within maxSecondsFromLastUserInteraction"
+ );
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 3,
+ isVisited: true,
+ });
+
+ await waitForPrefSeconds("maxSecondsFromLastUserInteraction");
+
+ info(
+ "Visit https://example.com/ by script without maxSecondsFromLastUserInteraction"
+ );
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 4,
+ isVisited: true,
+ });
+
+ await waitForPrefSeconds("restrictionExpireSeconds");
+
+ info("Visit again, it should not be restricted");
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 5,
+ isVisited: true,
+ });
+ }
+ );
+
+ await clearHistoryAndHistoryCache();
+});
+
+add_task(async function userInputAlwaysAcceptable() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: TEST_PAGE },
+ async browser => {
+ info("Visit by user");
+ await synthesizeVisitByUser(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 1,
+ isVisited: true,
+ });
+ await synthesizeVisitByUser(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 2,
+ isVisited: true,
+ });
+
+ await waitForPrefSeconds("maxSecondsFromLastUserInteraction");
+
+ info("Visit by user input");
+ await synthesizeVisitByUser(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 3,
+ isVisited: true,
+ });
+ await synthesizeVisitByUser(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 4,
+ isVisited: true,
+ });
+ }
+ );
+
+ await clearHistoryAndHistoryCache();
+});
+
+add_task(async function disable() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["places.history.floodingPrevention.enabled", false]],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: TEST_PAGE },
+ async browser => {
+ info("Any visits are stored");
+ for (let i = 0; i < 3; i++) {
+ await synthesizeVisitByScript(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: i + 1,
+ isVisited: true,
+ });
+ }
+ }
+ );
+
+ await clearHistoryAndHistoryCache();
+});
+
+async function waitForPrefSeconds(pref) {
+ info(`Wait until elapsing ${pref}`);
+ return new Promise(r =>
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+ setTimeout(
+ r,
+ Services.prefs.getIntPref(`places.history.floodingPrevention.${pref}`) *
+ 1000 +
+ 100
+ )
+ );
+}
diff --git a/toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js b/toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js
new file mode 100644
index 0000000000..ee691c79e8
--- /dev/null
+++ b/toolkit/components/places/tests/browser/browser_visituri_restriction_origin.js
@@ -0,0 +1,92 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+"use strict";
+
+const TEST_PAGE = `data:text/html,
+ <a href="https://example.com/" target="_blank">https://example.com</a>
+ <a href="http://example.com/" target="_blank">http://example.com</a>
+ <a href="https://www.example.com/" target="_blank">https://www.example.com</a>
+ <a href="https://example.org/" target="_blank">https://example.org</a>`;
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ // Enable restriction feature.
+ ["places.history.floodingPrevention.enabled", true],
+ // Restrict from the second visit.
+ ["places.history.floodingPrevention.restrictionCount", 1],
+ // Stop expiring.
+ ["places.history.floodingPrevention.restrictionExpireSeconds", 100],
+ // Always appply flooding preveition.
+ [
+ "places.history.floodingPrevention.maxSecondsFromLastUserInteraction",
+ 0,
+ ],
+ // To enable UserActivation by EventUtils.synthesizeMouseAtCenter() in ContentTask.spawn() in synthesizeVisitByUser().
+ ["test.events.async.enabled", true],
+ ],
+ });
+});
+
+add_task(async function same_origin_but_other() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: TEST_PAGE },
+ async browser => {
+ info("Sanity check");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ await assertLinkVisitedStatus(browser, "http://example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ await assertLinkVisitedStatus(browser, "https://www.example.com/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+ await assertLinkVisitedStatus(browser, "https://example.org/", {
+ visitCount: 0,
+ isVisited: false,
+ });
+
+ info("Visit https://example.com/ by user");
+ await synthesizeVisitByUser(browser, "https://example.com/");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 1,
+ isVisited: true,
+ });
+
+ info("Visit others by Scripts");
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ await synthesizeVisitByScript(browser, "http://example.com/");
+ await synthesizeVisitByScript(browser, "https://www.example.com/");
+ await synthesizeVisitByScript(browser, "https://example.org/");
+
+ info("Check the status");
+ await assertLinkVisitedStatus(browser, "https://example.com/", {
+ visitCount: 1,
+ isVisited: true,
+ });
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ await assertLinkVisitedStatus(browser, "http://example.com/", {
+ visitCount: 0,
+ isVisited: true,
+ });
+ await assertLinkVisitedStatus(browser, "https://www.example.com/", {
+ visitCount: 0,
+ isVisited: true,
+ });
+ await assertLinkVisitedStatus(browser, "https://example.org/", {
+ visitCount: 1,
+ isVisited: true,
+ });
+ }
+ );
+
+ await clearHistoryAndHistoryCache();
+});
diff --git a/toolkit/components/places/tests/browser/head.js b/toolkit/components/places/tests/browser/head.js
index b1b916ee29..da40a832c6 100644
--- a/toolkit/components/places/tests/browser/head.js
+++ b/toolkit/components/places/tests/browser/head.js
@@ -17,3 +17,80 @@ function whenNewWindowLoaded(aOptions, aCallback) {
BrowserTestUtils.waitForNewWindow().then(aCallback);
OpenBrowserWindow(aOptions);
}
+
+async function clearHistoryAndHistoryCache() {
+ await PlacesUtils.history.clear();
+ // Clear HistoryRestiction cache as well.
+ Cc["@mozilla.org/browser/history;1"]
+ .getService(Ci.mozIAsyncHistory)
+ .clearCache();
+}
+
+async function synthesizeVisitByUser(browser, url) {
+ let onNewTab = BrowserTestUtils.waitForNewTab(browser.ownerGlobal.gBrowser);
+ // We intentionally turn off this a11y check, because the following click is
+ // purposefully sent on an arbitrary web content that is not expected to be
+ // tested by itself with the browser mochitests, therefore this rule check
+ // shall be ignored by a11y_checks suite.
+ AccessibilityUtils.setEnv({ mustHaveAccessibleRule: false });
+ await ContentTask.spawn(browser, [url], async ([href]) => {
+ EventUtils.synthesizeMouseAtCenter(
+ content.document.querySelector(`a[href='${href}'`),
+ {},
+ content
+ );
+ });
+ AccessibilityUtils.resetEnv();
+ let tab = await onNewTab;
+ BrowserTestUtils.removeTab(tab);
+}
+
+async function synthesizeVisitByScript(browser, url) {
+ let onNewTab = BrowserTestUtils.waitForNewTab(browser.ownerGlobal.gBrowser);
+ AccessibilityUtils.setEnv({ mustHaveAccessibleRule: false });
+ await ContentTask.spawn(browser, [url], async ([href]) => {
+ let a = content.document.querySelector(`a[href='${href}'`);
+ a.click();
+ });
+ AccessibilityUtils.resetEnv();
+ let tab = await onNewTab;
+ BrowserTestUtils.removeTab(tab);
+}
+
+async function assertLinkVisitedStatus(
+ browser,
+ url,
+ { visitCount: expectedVisitCount, isVisited: expectedVisited }
+) {
+ await BrowserTestUtils.waitForCondition(async () => {
+ let visitCount =
+ (await PlacesTestUtils.getDatabaseValue("moz_places", "visit_count", {
+ url,
+ })) ?? 0;
+
+ if (visitCount != expectedVisitCount) {
+ return false;
+ }
+
+ Assert.equal(visitCount, expectedVisitCount, "The visit count is correct");
+ return true;
+ });
+
+ await ContentTask.spawn(
+ browser,
+ [url, expectedVisited],
+ async ([href, visited]) => {
+ // ElementState::VISITED
+ const VISITED_STATE = 1 << 18;
+ await ContentTaskUtils.waitForCondition(() => {
+ let isVisited = !!(
+ content.InspectorUtils.getContentState(
+ content.document.querySelector(`a[href='${href}']`)
+ ) & VISITED_STATE
+ );
+ return isVisited == visited;
+ });
+ }
+ );
+ Assert.ok(true, "The visited state is corerct");
+}