tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_searchTips_interaction.js (15973B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 // Tests the Search Tips feature, which displays a prompt to use the Urlbar on
      5 // the newtab page and on the user's default search engine's homepage.
      6 // Specifically, it tests that the Tips appear when they should be appearing.
      7 // This doesn't test the max-shown-count limit because it requires restarting
      8 // the browser.
      9 
     10 "use strict";
     11 
     12 ChromeUtils.defineESModuleGetters(this, {
     13  AppMenuNotifications: "resource://gre/modules/AppMenuNotifications.sys.mjs",
     14  HttpServer: "resource://testing-common/httpd.sys.mjs",
     15  UrlbarPrefs: "moz-src:///browser/components/urlbar/UrlbarPrefs.sys.mjs",
     16  UrlbarProviderSearchTips:
     17    "moz-src:///browser/components/urlbar/UrlbarProviderSearchTips.sys.mjs",
     18  UrlbarUtils: "moz-src:///browser/components/urlbar/UrlbarUtils.sys.mjs",
     19 });
     20 
     21 XPCOMUtils.defineLazyServiceGetter(
     22  this,
     23  "clipboardHelper",
     24  "@mozilla.org/widget/clipboardhelper;1",
     25  Ci.nsIClipboardHelper
     26 );
     27 
     28 // These should match the same consts in UrlbarProviderSearchTips.sys.mjs.
     29 const MAX_SHOWN_COUNT = 4;
     30 const LAST_UPDATE_THRESHOLD_MS = 24 * 60 * 60 * 1000;
     31 
     32 // We test some of the bigger Google domains.
     33 const GOOGLE_DOMAINS = [
     34  "www.google.com",
     35  "www.google.ca",
     36  "www.google.co.uk",
     37  "www.google.com.au",
     38  "www.google.co.nz",
     39 ];
     40 let tipsProviderInstance = UrlbarProvidersManager.getProvider(
     41  "UrlbarProviderSearchTips"
     42 );
     43 
     44 add_setup(async function () {
     45  await PlacesUtils.history.clear();
     46  await PlacesUtils.bookmarks.eraseEverything();
     47 
     48  await SpecialPowers.pushPrefEnv({
     49    set: [
     50      [
     51        `browser.urlbar.tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.ONBOARD}`,
     52        0,
     53      ],
     54      [
     55        `browser.urlbar.tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.REDIRECT}`,
     56        0,
     57      ],
     58      // Set following prefs so tips are actually shown.
     59      ["browser.laterrun.bookkeeping.profileCreationTime", 0],
     60      ["browser.laterrun.bookkeeping.updateAppliedTime", 0],
     61    ],
     62  });
     63 
     64  // Remove update history and the current active update so tips are shown.
     65  let updateRootDir = Services.dirsvc.get("UpdRootD", Ci.nsIFile);
     66  let updatesFile = updateRootDir.clone();
     67  updatesFile.append("updates.xml");
     68  let activeUpdateFile = updateRootDir.clone();
     69  activeUpdateFile.append("active-update.xml");
     70  try {
     71    updatesFile.remove(false);
     72  } catch (e) {}
     73  try {
     74    activeUpdateFile.remove(false);
     75  } catch (e) {}
     76 
     77  let defaultEngine = await Services.search.getDefault();
     78  let defaultEngineName = defaultEngine.name;
     79  Assert.equal(defaultEngineName, "Google", "Default engine should be Google.");
     80 
     81  // Add a mock engine so we don't hit the network loading the SERP.
     82  await SearchTestUtils.installSearchExtension();
     83 
     84  registerCleanupFunction(async () => {
     85    await setDefaultEngine(defaultEngineName);
     86    resetSearchTipsProvider();
     87  });
     88 });
     89 
     90 // Picking the tip's button should cause the Urlbar to blank out and the tip to
     91 // be not to be shown again in any session.
     92 add_task(async function pickButton_onboard() {
     93  tipsProviderInstance.disableTipsForCurrentSession = false;
     94  let tab = await BrowserTestUtils.openNewForegroundTab({
     95    gBrowser,
     96    url: "about:newtab",
     97    waitForLoad: false,
     98  });
     99  await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.ONBOARD, false);
    100 
    101  // Click the tip button.
    102  let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
    103  let button = result.element.row._buttons.get("0");
    104  await UrlbarTestUtils.promisePopupClose(window, () => {
    105    EventUtils.synthesizeMouseAtCenter(button, {});
    106  });
    107  gURLBar.blur();
    108 
    109  Assert.equal(
    110    UrlbarPrefs.get(
    111      `tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.ONBOARD}`
    112    ),
    113    MAX_SHOWN_COUNT,
    114    "Onboarding tips are disabled after tip button is picked."
    115  );
    116  Assert.equal(gURLBar.value, "", "The Urlbar should be empty.");
    117  resetSearchTipsProvider();
    118 
    119  BrowserTestUtils.removeTab(tab);
    120 });
    121 
    122 // Picking the tip's button should cause the Urlbar to blank out and the tip to
    123 // be not to be shown again in any session.
    124 add_task(async function pickButton_redirect() {
    125  tipsProviderInstance.disableTipsForCurrentSession = false;
    126  await setDefaultEngine("Google");
    127  await BrowserTestUtils.withNewTab("about:blank", async () => {
    128    await withDNSRedirect("www.google.com", "/", async url => {
    129      BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
    130      await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    131      await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.REDIRECT, false);
    132 
    133      // Click the tip button.
    134      let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
    135      let button = result.element.row._buttons.get("0");
    136      await UrlbarTestUtils.promisePopupClose(window, () => {
    137        EventUtils.synthesizeMouseAtCenter(button, {});
    138      });
    139      gURLBar.blur();
    140    });
    141  });
    142 
    143  Assert.equal(
    144    UrlbarPrefs.get(
    145      `tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.REDIRECT}`
    146    ),
    147    MAX_SHOWN_COUNT,
    148    "Redirect tips are disabled after tip button is picked."
    149  );
    150  Assert.equal(gURLBar.value, "", "The Urlbar should be empty.");
    151  resetSearchTipsProvider();
    152 });
    153 
    154 // Clicking in the input while the onboard tip is showing should have the same
    155 // effect as picking the tip.
    156 add_task(async function clickInInput_onboard() {
    157  tipsProviderInstance.disableTipsForCurrentSession = false;
    158  await setDefaultEngine("Google");
    159  let tab = await BrowserTestUtils.openNewForegroundTab({
    160    gBrowser,
    161    url: "about:newtab",
    162    waitForLoad: false,
    163  });
    164  await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.ONBOARD, false);
    165 
    166  // Click in the input.
    167  await UrlbarTestUtils.promisePopupClose(window, () => {
    168    EventUtils.synthesizeMouseAtCenter(gURLBar.parentNode, {});
    169  });
    170  gURLBar.blur();
    171 
    172  Assert.equal(
    173    UrlbarPrefs.get(
    174      `tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.ONBOARD}`
    175    ),
    176    MAX_SHOWN_COUNT,
    177    "Onboarding tips are disabled after tip button is picked."
    178  );
    179  Assert.equal(gURLBar.value, "", "The Urlbar should be empty.");
    180  resetSearchTipsProvider();
    181  BrowserTestUtils.removeTab(tab);
    182 });
    183 
    184 // Pressing Ctrl+L (the open location command) while the onboard tip is showing
    185 // should have the same effect as picking the tip.
    186 add_task(async function openLocation_onboard() {
    187  tipsProviderInstance.disableTipsForCurrentSession = false;
    188  await setDefaultEngine("Google");
    189  let tab = await BrowserTestUtils.openNewForegroundTab({
    190    gBrowser,
    191    url: "about:newtab",
    192    waitForLoad: false,
    193  });
    194  await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.ONBOARD, false);
    195 
    196  // Trigger the open location command.
    197  await UrlbarTestUtils.promisePopupClose(window, () => {
    198    document.getElementById("Browser:OpenLocation").doCommand();
    199  });
    200  gURLBar.blur();
    201 
    202  Assert.equal(
    203    UrlbarPrefs.get(
    204      `tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.ONBOARD}`
    205    ),
    206    MAX_SHOWN_COUNT,
    207    "Onboarding tips are disabled after tip button is picked."
    208  );
    209  Assert.equal(gURLBar.value, "", "The Urlbar should be empty.");
    210  resetSearchTipsProvider();
    211  BrowserTestUtils.removeTab(tab);
    212 });
    213 
    214 // Clicking in the input while the redirect tip is showing should have the same
    215 // effect as picking the tip.
    216 add_task(async function clickInInput_redirect() {
    217  tipsProviderInstance.disableTipsForCurrentSession = false;
    218  await setDefaultEngine("Google");
    219  await BrowserTestUtils.withNewTab("about:blank", async () => {
    220    await withDNSRedirect("www.google.com", "/", async url => {
    221      BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
    222      await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    223      await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.REDIRECT, false);
    224 
    225      // Click in the input.
    226      await UrlbarTestUtils.promisePopupClose(window, () => {
    227        EventUtils.synthesizeMouseAtCenter(gURLBar.parentNode, {});
    228      });
    229      gURLBar.blur();
    230    });
    231  });
    232 
    233  Assert.equal(
    234    UrlbarPrefs.get(
    235      `tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.REDIRECT}`
    236    ),
    237    MAX_SHOWN_COUNT,
    238    "Redirect tips are disabled after tip button is picked."
    239  );
    240  Assert.equal(gURLBar.value, "", "The Urlbar should be empty.");
    241  resetSearchTipsProvider();
    242 });
    243 
    244 // Pressing Ctrl+L (the open location command) while the redirect tip is showing
    245 // should have the same effect as picking the tip.
    246 add_task(async function openLocation_redirect() {
    247  tipsProviderInstance.disableTipsForCurrentSession = false;
    248  await setDefaultEngine("Google");
    249  await BrowserTestUtils.withNewTab("about:blank", async () => {
    250    await withDNSRedirect("www.google.com", "/", async url => {
    251      BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
    252      await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    253      await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.REDIRECT, false);
    254 
    255      // Trigger the open location command.
    256      await UrlbarTestUtils.promisePopupClose(window, () => {
    257        document.getElementById("Browser:OpenLocation").doCommand();
    258      });
    259      gURLBar.blur();
    260    });
    261  });
    262 
    263  Assert.equal(
    264    UrlbarPrefs.get(
    265      `tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.REDIRECT}`
    266    ),
    267    MAX_SHOWN_COUNT,
    268    "Redirect tips are disabled after tip button is picked."
    269  );
    270  Assert.equal(gURLBar.value, "", "The Urlbar should be empty.");
    271  resetSearchTipsProvider();
    272 });
    273 
    274 add_task(async function pickingTipDoesNotDisableOtherKinds() {
    275  tipsProviderInstance.disableTipsForCurrentSession = false;
    276  await setDefaultEngine("Google");
    277  let tab = await BrowserTestUtils.openNewForegroundTab({
    278    gBrowser,
    279    url: "about:newtab",
    280    waitForLoad: false,
    281  });
    282  await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.ONBOARD, false);
    283 
    284  // Click the tip button.
    285  let result = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
    286  let button = result.element.row._buttons.get("0");
    287  await UrlbarTestUtils.promisePopupClose(window, () => {
    288    EventUtils.synthesizeMouseAtCenter(button, {});
    289  });
    290 
    291  gURLBar.blur();
    292  Assert.equal(
    293    UrlbarPrefs.get(
    294      `tipShownCount.${UrlbarProviderSearchTips.TIP_TYPE.ONBOARD}`
    295    ),
    296    MAX_SHOWN_COUNT,
    297    "Onboarding tips are disabled after tip button is picked."
    298  );
    299 
    300  BrowserTestUtils.removeTab(tab);
    301 
    302  // Simulate a new session.
    303  tipsProviderInstance.disableTipsForCurrentSession = false;
    304 
    305  // Onboarding tips should no longer be shown.
    306  let tab2 = await BrowserTestUtils.openNewForegroundTab({
    307    gBrowser,
    308    url: "about:newtab",
    309    waitForLoad: false,
    310  });
    311  await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.NONE);
    312 
    313  // We should still show redirect tips.
    314  await withDNSRedirect("www.google.com", "/", async url => {
    315    await checkTab(window, url, UrlbarProviderSearchTips.TIP_TYPE.REDIRECT);
    316  });
    317 
    318  BrowserTestUtils.removeTab(tab2);
    319  resetSearchTipsProvider();
    320 });
    321 
    322 // The tip shouldn't be shown when there's another notification present.
    323 add_task(async function notification() {
    324  await BrowserTestUtils.withNewTab("about:blank", async () => {
    325    let box = gBrowser.getNotificationBox();
    326    let note = await box.appendNotification("urlbar-test", {
    327      label: "Test",
    328      priority: box.PRIORITY_INFO_HIGH,
    329    });
    330    // Give it a big persistence so it doesn't go away on page load.
    331    note.persistence = 100;
    332    await withDNSRedirect("www.google.com", "/", async url => {
    333      BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
    334      await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    335      await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.NONE);
    336      box.removeNotification(note, true);
    337    });
    338  });
    339  resetSearchTipsProvider();
    340 });
    341 
    342 // The tip should be shown when switching to a tab where it should be shown.
    343 add_task(async function tabSwitch() {
    344  let tab = BrowserTestUtils.addTab(gBrowser, "about:newtab");
    345  tipsProviderInstance.disableTipsForCurrentSession = false;
    346  await BrowserTestUtils.switchTab(gBrowser, tab);
    347  await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.ONBOARD);
    348  BrowserTestUtils.removeTab(tab);
    349  resetSearchTipsProvider();
    350 });
    351 
    352 // The engagement event should be ended if the user ignores a tip.
    353 // See bug 1610024.
    354 add_task(async function ignoreEndsEngagement() {
    355  await setDefaultEngine("Google");
    356  await BrowserTestUtils.withNewTab("about:blank", async () => {
    357    await withDNSRedirect("www.google.com", "/", async url => {
    358      BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, url);
    359      await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
    360      await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.REDIRECT, false);
    361      // We're just looking for any target outside the Urlbar.
    362      let spring = gURLBar.inputField
    363        .closest("#nav-bar")
    364        .querySelector("toolbarspring");
    365      await UrlbarTestUtils.promisePopupClose(window, async () => {
    366        // We intentionally turn off this a11y check, because the following
    367        // click is purposefully targeting a non-interactive element to dismiss
    368        // the opened URL Bar with a mouse which can be done by assistive
    369        // technology and keyboard by pressing `Esc` key, this rule check shall
    370        // be ignored by a11y_checks suite.
    371        AccessibilityUtils.setEnv({ mustHaveAccessibleRule: false });
    372        await EventUtils.synthesizeMouseAtCenter(spring, {});
    373        AccessibilityUtils.resetEnv();
    374      });
    375      Assert.equal(
    376        tipsProviderInstance.showedTipTypeInCurrentEngagement,
    377        UrlbarProviderSearchTips.TIP_TYPE.NONE,
    378        "The engagement should have ended after the tip was ignored."
    379      );
    380    });
    381  });
    382  resetSearchTipsProvider();
    383 });
    384 
    385 add_task(async function pasteAndGo_url() {
    386  await doPasteAndGoTest("http://example.com/", "http://example.com/");
    387 });
    388 
    389 add_task(async function pasteAndGo_nonURL() {
    390  await setDefaultEngine("Example");
    391  await doPasteAndGoTest(
    392    "pasteAndGo_nonURL",
    393    "https://example.com/?q=pasteAndGo_nonURL"
    394  );
    395  await setDefaultEngine("Google");
    396 });
    397 
    398 async function doPasteAndGoTest(searchString, expectedURL) {
    399  tipsProviderInstance.disableTipsForCurrentSession = false;
    400  let tab = await BrowserTestUtils.openNewForegroundTab({
    401    gBrowser,
    402    url: "about:newtab",
    403    waitForLoad: false,
    404  });
    405  await checkTip(window, UrlbarProviderSearchTips.TIP_TYPE.ONBOARD, false);
    406 
    407  await SimpleTest.promiseClipboardChange(searchString, () => {
    408    clipboardHelper.copyString(searchString);
    409  });
    410 
    411  let textBox = gURLBar.querySelector("moz-input-box");
    412  let cxmenu = textBox.menupopup;
    413  let cxmenuPromise = BrowserTestUtils.waitForEvent(cxmenu, "popupshown");
    414  EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {
    415    type: "contextmenu",
    416    button: 2,
    417  });
    418  await cxmenuPromise;
    419  let menuitem = textBox.getMenuItem("paste-and-go");
    420 
    421  let browserLoadedPromise = BrowserTestUtils.browserLoaded(
    422    gBrowser.selectedBrowser,
    423    false,
    424    expectedURL
    425  );
    426  cxmenu.activateItem(menuitem);
    427  await browserLoadedPromise;
    428  BrowserTestUtils.removeTab(tab);
    429  resetSearchTipsProvider();
    430 }
    431 
    432 // Since we coupled the logic that decides whether to show the tip with our
    433 // gURLBar.search call, we should make sure search isn't called when
    434 // the conditions for a tip are met but the provider is disabled.
    435 add_task(async function noActionWhenDisabled() {
    436  await setDefaultEngine("Bing");
    437  await withDNSRedirect("www.bing.com", "/", async url => {
    438    await checkTab(window, url, UrlbarProviderSearchTips.TIP_TYPE.REDIRECT);
    439  });
    440 
    441  await SpecialPowers.pushPrefEnv({
    442    set: [
    443      [
    444        "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
    445        false,
    446      ],
    447    ],
    448  });
    449 
    450  await withDNSRedirect("www.bing.com", "/", async () => {
    451    Assert.ok(
    452      !UrlbarTestUtils.isPopupOpen(window),
    453      "The UrlbarView should not be open."
    454    );
    455  });
    456 
    457  await SpecialPowers.popPrefEnv();
    458 });