summaryrefslogtreecommitdiffstats
path: root/browser/components/urlbar/tests/browser/browser_clipboard.js
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/urlbar/tests/browser/browser_clipboard.js')
-rw-r--r--browser/components/urlbar/tests/browser/browser_clipboard.js349
1 files changed, 349 insertions, 0 deletions
diff --git a/browser/components/urlbar/tests/browser/browser_clipboard.js b/browser/components/urlbar/tests/browser/browser_clipboard.js
new file mode 100644
index 0000000000..f6127ef8d9
--- /dev/null
+++ b/browser/components/urlbar/tests/browser/browser_clipboard.js
@@ -0,0 +1,349 @@
+/* Any copyright is dedicated to the Public Domain.
+ * https://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Browser test for clipboard suggestion.
+ */
+
+"use strict";
+
+const { UrlbarProviderClipboard, CLIPBOARD_IMPRESSION_LIMIT } =
+ ChromeUtils.importESModule(
+ "resource:///modules/UrlbarProviderClipboard.sys.mjs"
+ );
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.urlbar.clipboard.featureGate", true],
+ ["browser.urlbar.suggest.clipboard", true],
+ ],
+ });
+ registerCleanupFunction(() => {
+ SpecialPowers.clipboardCopyString("");
+ });
+});
+
+async function searchEmptyStringAndGetFirstRow() {
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ });
+ Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
+ return UrlbarTestUtils.getRowAt(window, 0);
+}
+
+async function checkClipboardSuggestionAbsent(startIdx) {
+ for (let i = startIdx; i < UrlbarTestUtils.getResultCount(window); i++) {
+ const row = await UrlbarTestUtils.getRowAt(window, i);
+ Assert.notEqual(
+ row.result.providerName,
+ UrlbarProviderClipboard.name,
+ `Clipboard suggestion should be absent (checking index ${i})`
+ );
+ }
+}
+
+add_task(async function testFormattingOfClipboardSuggestion() {
+ let unicodeURL = "https://пример.com/";
+ let punycodeURL = "https://xn--e1afmkfd.com/";
+
+ SpecialPowers.clipboardCopyString(unicodeURL);
+
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async browser => {
+ let { result } = await searchEmptyStringAndGetFirstRow();
+
+ Assert.equal(
+ result.providerName,
+ UrlbarProviderClipboard.name,
+ "The first result is a clipboard valid url suggestion."
+ );
+ Assert.equal(
+ result.payload.url,
+ punycodeURL,
+ "The Clipboard suggestion URL should not be decoded."
+ );
+ Assert.equal(
+ result.payload.fallbackTitle,
+ unicodeURL,
+ "The Clipboard suggestion fallback title should be decoded."
+ );
+ }
+ );
+});
+// Verifies that a valid URL copied to the clipboard results in the
+// display of a corresponding suggestion in the URL bar as the first
+// suggestion with accurate URL and icon. Also ensures that engaging
+// with a clipboard suggestion leads to navigation to the copied URL
+// and subsequent absence of the suggestion upon refocusing the URL bar.
+add_task(async function testUserEngagementWithClipboardSuggestion() {
+ const validURL = "https://example.com/";
+ SpecialPowers.clipboardCopyString(validURL);
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async browser => {
+ let { result } = await searchEmptyStringAndGetFirstRow();
+ let onLoad = BrowserTestUtils.browserLoaded(browser, false);
+
+ Assert.equal(
+ result.providerName,
+ UrlbarProviderClipboard.name,
+ "The first result is a clipboard valid url suggestion."
+ );
+ Assert.equal(
+ result.payload.url,
+ validURL,
+ "The Clipboard suggestion URL and the valid URL should match."
+ );
+ Assert.equal(
+ result.icon,
+ "chrome://global/skin/icons/clipboard.svg",
+ "Clipboard suggestion icon"
+ );
+ await checkClipboardSuggestionAbsent(1);
+
+ // Focus and select the clipbaord result.
+ EventUtils.synthesizeKey("KEY_ArrowDown");
+ EventUtils.synthesizeKey("KEY_Enter");
+ await onLoad;
+
+ Assert.equal(
+ gBrowser.selectedBrowser.currentURI.spec,
+ validURL,
+ "Navigated to the validURL webpage after selecting the clipboard result."
+ );
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ });
+ await checkClipboardSuggestionAbsent(0);
+ }
+ );
+});
+
+// This test confirms that dismissing the result from the result menu
+// button after copying a valid URL dismisses the clipboard suggestion,
+// and the suggestion does not reappear upon refocusing the URL bar.
+add_task(async function testDismissClipboardSuggestion() {
+ SpecialPowers.clipboardCopyString("https://example.com/2");
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async () => {
+ const resultIndex = 0;
+ const command = "dismiss";
+ let row = await searchEmptyStringAndGetFirstRow();
+
+ Assert.equal(
+ row.result.providerName,
+ UrlbarProviderClipboard.name,
+ "Clipboard suggestion should be present"
+ );
+ await checkClipboardSuggestionAbsent(1);
+ await UrlbarTestUtils.openResultMenuAndClickItem(window, command, {
+ resultIndex,
+ });
+ Assert.ok(
+ gURLBar.view.isOpen,
+ "The view should remain open after clicking the command"
+ );
+ Assert.ok(
+ !row.hasAttribute("feedback-acknowledgement"),
+ "Row should not have feedback acknowledgement after clicking command"
+ );
+ await UrlbarTestUtils.promisePopupClose(window, () => {
+ gURLBar.blur();
+ });
+
+ // Do the same search again. The suggestion should not appear.
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ });
+ await checkClipboardSuggestionAbsent(0);
+ }
+ );
+});
+
+// The test validates that the clipboard suggestion is displayed for
+// the first two URL bar openings after copying a valid URL, but is
+// suppressed on the third opening of URL bar.
+add_task(async function testClipboardSuggestionLimit() {
+ SpecialPowers.clipboardCopyString("https://example.com/3");
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async () => {
+ for (let i = 0; i < CLIPBOARD_IMPRESSION_LIMIT; i++) {
+ const { result } = await searchEmptyStringAndGetFirstRow();
+ Assert.equal(
+ result.providerName,
+ UrlbarProviderClipboard.name,
+ "Clipboard suggestion should be present as the first suggestion."
+ );
+ await checkClipboardSuggestionAbsent(1);
+ await UrlbarTestUtils.promisePopupClose(window, () => {
+ gURLBar.blur();
+ });
+ }
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ });
+ await checkClipboardSuggestionAbsent(0);
+ }
+ );
+});
+
+// This test ensures that copying non-URL content to the clipboard
+// results in the absence of a clipboard suggestion when opening
+// the URL bar.
+add_task(async function testNonUrlClipboardSuggestion() {
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async () => {
+ const malformedURLs = [
+ "plain text",
+ "ftp://example.com",
+ "https://example.com[invalid]",
+ // Testing http because it is considered as a valid URL.
+ // eslint-disable-next-line @microsoft/sdl/no-insecure-url
+ "http://",
+ "https://example.com some text",
+ "https://example.com/ some text",
+ ];
+ for (let i = 0; i < malformedURLs.length; i++) {
+ SpecialPowers.clipboardCopyString(malformedURLs[i]);
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ });
+ Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
+ await checkClipboardSuggestionAbsent(0);
+ await UrlbarTestUtils.promisePopupClose(window, () => {
+ gURLBar.blur();
+ });
+ }
+ }
+ );
+});
+
+// This test verifies that clipboard suggestions are displayed
+// based on the toggled state of the 'clipboard.featureGate' preference.
+add_task(async function testClipboardFeatureGateToggle() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.urlbar.clipboard.featureGate", false],
+ ["browser.urlbar.suggest.clipboard", true],
+ ],
+ });
+ SpecialPowers.clipboardCopyString("https://example.com/4");
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async () => {
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ });
+ await checkClipboardSuggestionAbsent(0);
+ await UrlbarTestUtils.promisePopupClose(window, () => {
+ gURLBar.blur();
+ });
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.urlbar.clipboard.featureGate", true]],
+ });
+ const { result } = await searchEmptyStringAndGetFirstRow();
+ Assert.equal(
+ result.providerName,
+ UrlbarProviderClipboard.name,
+ "Clipboard suggestion should be present as the first suggestion."
+ );
+ await checkClipboardSuggestionAbsent(1);
+ }
+ );
+});
+
+// This test confirms that clipboard suggestions are presented based on
+// the state of the 'suggest.clipboard' preference toggle.
+add_task(async function testClipboardSuggestToggle() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.urlbar.clipboard.featureGate", true],
+ ["browser.urlbar.suggest.clipboard", false],
+ ],
+ });
+ SpecialPowers.clipboardCopyString("https://example.com/5");
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async () => {
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ });
+ await checkClipboardSuggestionAbsent(0);
+ await UrlbarTestUtils.promisePopupClose(window, () => {
+ gURLBar.blur();
+ });
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.urlbar.suggest.clipboard", true]],
+ });
+ const { result } = await searchEmptyStringAndGetFirstRow();
+ Assert.equal(
+ result.providerName,
+ UrlbarProviderClipboard.name,
+ "Clipboard suggestion should be present as the first suggestion."
+ );
+ await checkClipboardSuggestionAbsent(1);
+ }
+ );
+});
+
+add_task(async function testScalarAndStopWatchTelemetry() {
+ SpecialPowers.clipboardCopyString("https://example.com/6");
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:home" },
+ async () => {
+ Services.telemetry.clearScalars();
+ let histogram = Services.telemetry.getHistogramById(
+ "FX_URLBAR_PROVIDER_CLIPBOARD_READ_TIME_MS"
+ );
+ histogram.clear();
+ Assert.equal(
+ Object.values(histogram.snapshot().values).length,
+ 0,
+ "histogram is empty before search"
+ );
+
+ await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "",
+ waitForFocus,
+ fireInputEvent: true,
+ });
+
+ await UrlbarTestUtils.promisePopupClose(window, () => {
+ EventUtils.synthesizeKey("KEY_ArrowDown");
+ EventUtils.synthesizeKey("KEY_Enter");
+ });
+
+ const scalars = TelemetryTestUtils.getProcessScalars(
+ "parent",
+ true,
+ true
+ );
+
+ TelemetryTestUtils.assertKeyedScalar(
+ scalars,
+ `urlbar.picked.clipboard`,
+ 0,
+ 1
+ );
+
+ Assert.greater(
+ Object.values(histogram.snapshot().values).length,
+ 0,
+ "histogram updated after search"
+ );
+ }
+ );
+});