tor-browser

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

browser_top_sites.js (17656B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 ChromeUtils.defineESModuleGetters(this, {
      7  AboutNewTab: "resource:///modules/AboutNewTab.sys.mjs",
      8  NewTabUtils: "resource://gre/modules/NewTabUtils.sys.mjs",
      9  TopSites: "resource:///modules/topsites/TopSites.sys.mjs",
     10 });
     11 
     12 const EN_US_TOPSITES =
     13  "https://www.youtube.com/,https://www.facebook.com/,https://www.amazon.com/,https://www.reddit.com/,about:robots,https://twitter.com/";
     14 
     15 async function addTestVisits() {
     16  // Add some visits to a URL.
     17  for (let i = 0; i < 5; i++) {
     18    await PlacesTestUtils.addVisits("http://example.com/");
     19  }
     20 
     21  // Wait for example.com to be listed first.
     22  await updateTopSites(sites => {
     23    return sites && sites[0] && sites[0].url == "http://example.com/";
     24  });
     25 
     26  await PlacesUtils.bookmarks.insert({
     27    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
     28    url: "https://www.youtube.com/",
     29    title: "YouTube",
     30  });
     31 
     32  // Adding a bookmark will refresh the TopSites feed.
     33  if (Services.prefs.getBoolPref("browser.topsites.component.enabled")) {
     34    await TestUtils.topicObserved("topsites-refreshed");
     35  }
     36 }
     37 
     38 async function getTopSites() {
     39  if (Services.prefs.getBoolPref("browser.topsites.component.enabled")) {
     40    return await TopSites.getSites();
     41  }
     42  return AboutNewTab.getTopSites();
     43 }
     44 
     45 async function checkDoesNotOpenOnFocus(win = window) {
     46  // The view should not open when the input is focused programmatically.
     47  win.gURLBar.blur();
     48  win.gURLBar.focus();
     49  Assert.ok(!win.gURLBar.view.isOpen, "check urlbar panel is not open");
     50  win.gURLBar.blur();
     51 
     52  // Check the keyboard shortcut.
     53  win.document.getElementById("Browser:OpenLocation").doCommand();
     54  // Because the panel opening may not be immediate, we must wait a bit.
     55  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
     56  await new Promise(resolve => setTimeout(resolve, 500));
     57  Assert.ok(!win.gURLBar.view.isOpen, "check urlbar panel is not open");
     58  win.gURLBar.blur();
     59 
     60  // Focus with the mouse.
     61  EventUtils.synthesizeMouseAtCenter(win.gURLBar.inputField, {}, win);
     62  // Because the panel opening may not be immediate, we must wait a bit.
     63  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
     64  await new Promise(resolve => setTimeout(resolve, 500));
     65  Assert.ok(!win.gURLBar.view.isOpen, "check urlbar panel is not open");
     66  win.gURLBar.blur();
     67 }
     68 
     69 add_setup(async function () {
     70  await SpecialPowers.pushPrefEnv({
     71    set: [
     72      ["browser.urlbar.suggest.topsites", true],
     73      ["browser.urlbar.suggest.quickactions", false],
     74      ["browser.newtabpage.activity-stream.default.sites", EN_US_TOPSITES],
     75    ],
     76  });
     77 
     78  await updateTopSites(
     79    sites => sites && sites.length == EN_US_TOPSITES.split(",").length
     80  );
     81 
     82  let tab = await BrowserTestUtils.openNewForegroundTab(
     83    gBrowser,
     84    "http://example.com/"
     85  );
     86 
     87  registerCleanupFunction(() => {
     88    BrowserTestUtils.removeTab(tab);
     89  });
     90 });
     91 
     92 add_task(async function topSitesShown() {
     93  let sites = await getTopSites();
     94 
     95  for (let prefVal of [true, false]) {
     96    // This test should work regardless of whether Top Sites are enabled on
     97    // about:newtab.
     98    await SpecialPowers.pushPrefEnv({
     99      set: [["browser.newtabpage.activity-stream.feeds.topsites", prefVal]],
    100    });
    101    // We don't expect this to change, but we run updateTopSites just in case
    102    // feeds.topsites were to have an effect on the composition of Top Sites.
    103    await updateTopSites(siteList => siteList.length == 6);
    104 
    105    await UrlbarTestUtils.promisePopupOpen(window, () => {
    106      if (gURLBar.getAttribute("pageproxystate") == "invalid") {
    107        gURLBar.handleRevert();
    108      }
    109      EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    110    });
    111    Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    112    await UrlbarTestUtils.promiseSearchComplete(window);
    113    Assert.equal(
    114      UrlbarTestUtils.getResultCount(window),
    115      sites.length,
    116      "The number of results should be the same as the number of Top Sites (6)."
    117    );
    118 
    119    for (let i = 0; i < sites.length; i++) {
    120      let site = sites[i];
    121      let result = await UrlbarTestUtils.getDetailsOfResultAt(window, i);
    122      if (site.searchTopSite) {
    123        Assert.equal(
    124          result.searchParams.keyword,
    125          site.label,
    126          "The search Top Site should have an alias."
    127        );
    128        continue;
    129      }
    130 
    131      Assert.equal(
    132        site.url,
    133        result.url,
    134        "The Top Site URL and the result URL shoud match."
    135      );
    136      Assert.equal(
    137        site.label || site.title || site.hostname,
    138        result.title,
    139        "The Top Site title and the result title shoud match."
    140      );
    141    }
    142    await UrlbarTestUtils.promisePopupClose(window, () => {
    143      gURLBar.blur();
    144    });
    145    // This pops updateTopSites changes.
    146    await SpecialPowers.popPrefEnv();
    147    await SpecialPowers.popPrefEnv();
    148  }
    149 });
    150 
    151 add_task(async function selectSearchTopSite() {
    152  await updateTopSites(
    153    sites => sites && sites[0] && sites[0].searchTopSite,
    154    true
    155  );
    156  await UrlbarTestUtils.promisePopupOpen(window, () => {
    157    if (gURLBar.getAttribute("pageproxystate") == "invalid") {
    158      gURLBar.handleRevert();
    159    }
    160    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    161  });
    162  await UrlbarTestUtils.promiseSearchComplete(window);
    163 
    164  let amazonSearch = await UrlbarTestUtils.waitForAutocompleteResultAt(
    165    window,
    166    0
    167  );
    168 
    169  Assert.equal(
    170    amazonSearch.result.type,
    171    UrlbarUtils.RESULT_TYPE.SEARCH,
    172    "First result should have SEARCH type."
    173  );
    174 
    175  Assert.equal(
    176    amazonSearch.result.payload.keyword,
    177    "@amazon",
    178    "First result should have the Amazon keyword."
    179  );
    180 
    181  let searchPromise = UrlbarTestUtils.promiseSearchComplete(window);
    182  EventUtils.synthesizeMouseAtCenter(amazonSearch, {});
    183  await searchPromise;
    184  await UrlbarTestUtils.assertSearchMode(window, {
    185    engineName: amazonSearch.result.payload.engine,
    186    entry: "topsites_urlbar",
    187  });
    188  await UrlbarTestUtils.exitSearchMode(window, { backspace: true });
    189 
    190  await UrlbarTestUtils.promisePopupClose(window, () => {
    191    gURLBar.blur();
    192  });
    193 });
    194 
    195 add_task(async function topSitesBookmarksAndTabs() {
    196  await addTestVisits();
    197  let sites = await getTopSites();
    198  Assert.equal(
    199    sites.length,
    200    7,
    201    "The test suite browser should have 7 Top Sites."
    202  );
    203 
    204  await UrlbarTestUtils.promisePopupOpen(window, () => {
    205    if (gURLBar.getAttribute("pageproxystate") == "invalid") {
    206      gURLBar.handleRevert();
    207    }
    208    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    209  });
    210  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    211  await UrlbarTestUtils.promiseSearchComplete(window);
    212 
    213  Assert.equal(
    214    UrlbarTestUtils.getResultCount(window),
    215    7,
    216    "The number of results should be the same as the number of Top Sites (7)."
    217  );
    218 
    219  let exampleResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
    220  Assert.equal(
    221    exampleResult.url,
    222    "http://example.com/",
    223    "The example.com Top Site should be the first result."
    224  );
    225 
    226  Assert.equal(
    227    exampleResult.source,
    228    UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    229    "The example.com Top Site should not appear in the view as an open tab result since it is the current tab."
    230  );
    231 
    232  let youtubeResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
    233  Assert.equal(
    234    youtubeResult.url,
    235    "https://www.youtube.com/",
    236    "The YouTube Top Site should be the second result."
    237  );
    238  Assert.equal(
    239    youtubeResult.source,
    240    UrlbarUtils.RESULT_SOURCE.BOOKMARKS,
    241    "The YouTube Top Site should appear in the view as a bookmark result."
    242  );
    243  await UrlbarTestUtils.promisePopupClose(window, () => {
    244    gURLBar.blur();
    245  });
    246 
    247  await PlacesUtils.bookmarks.eraseEverything();
    248  await PlacesUtils.history.clear();
    249 });
    250 
    251 add_task(async function topSitesKeywordNavigationPageproxystate() {
    252  await addTestVisits();
    253  Assert.equal(
    254    gURLBar.getAttribute("pageproxystate"),
    255    "valid",
    256    "Sanity check initial state"
    257  );
    258 
    259  await UrlbarTestUtils.promisePopupOpen(window, () => {
    260    if (gURLBar.getAttribute("pageproxystate") == "invalid") {
    261      gURLBar.handleRevert();
    262    }
    263    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    264  });
    265  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    266  await UrlbarTestUtils.promiseSearchComplete(window);
    267 
    268  let count = UrlbarTestUtils.getResultCount(window);
    269  Assert.equal(count, 7, "The number of results should be the expected one.");
    270 
    271  for (let i = 0; i < count; ++i) {
    272    EventUtils.synthesizeKey("KEY_ArrowDown");
    273    Assert.equal(
    274      gURLBar.getAttribute("pageproxystate"),
    275      "invalid",
    276      "Moving through results"
    277    );
    278  }
    279  for (let i = 0; i < count; ++i) {
    280    EventUtils.synthesizeKey("KEY_ArrowUp");
    281    Assert.equal(
    282      gURLBar.getAttribute("pageproxystate"),
    283      "invalid",
    284      "Moving through results"
    285    );
    286  }
    287 
    288  // Double ESC should restore state.
    289  await UrlbarTestUtils.promisePopupClose(window, () => {
    290    EventUtils.synthesizeKey("KEY_Escape");
    291  });
    292  EventUtils.synthesizeKey("KEY_Escape");
    293  Assert.equal(
    294    gURLBar.getAttribute("pageproxystate"),
    295    "valid",
    296    "Double ESC should restore state"
    297  );
    298  await PlacesUtils.bookmarks.eraseEverything();
    299  await PlacesUtils.history.clear();
    300 });
    301 
    302 add_task(async function topSitesPinned() {
    303  await addTestVisits();
    304  let info = { url: "http://example.com/" };
    305  NewTabUtils.pinnedLinks.pin(info, 0);
    306 
    307  await updateTopSites(sites => sites && sites[0] && sites[0].isPinned);
    308 
    309  let sites = await getTopSites();
    310  Assert.equal(
    311    sites.length,
    312    7,
    313    "The test suite browser should have 7 Top Sites."
    314  );
    315 
    316  await UrlbarTestUtils.promisePopupOpen(window, () => {
    317    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    318  });
    319  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    320  await UrlbarTestUtils.promiseSearchComplete(window);
    321 
    322  Assert.equal(
    323    UrlbarTestUtils.getResultCount(window),
    324    7,
    325    "The number of results should be the same as the number of Top Sites (7)."
    326  );
    327 
    328  let exampleResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
    329  Assert.equal(
    330    exampleResult.url,
    331    "http://example.com/",
    332    "The example.com Top Site should be the first result."
    333  );
    334 
    335  Assert.equal(
    336    exampleResult.source,
    337    UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    338    "The example.com Top Site should not appear in the view as an open tab result since it is the current tab."
    339  );
    340 
    341  Assert.ok(
    342    exampleResult.element.row.hasAttribute("pinned"),
    343    "The example.com Top Site should have the pinned property."
    344  );
    345 
    346  await UrlbarTestUtils.promisePopupClose(window, () => {
    347    gURLBar.blur();
    348  });
    349  NewTabUtils.pinnedLinks.unpin(info);
    350 
    351  await PlacesUtils.bookmarks.eraseEverything();
    352  await PlacesUtils.history.clear();
    353 });
    354 
    355 add_task(async function topSitesBookmarksAndTabsDisabled() {
    356  await addTestVisits();
    357  await SpecialPowers.pushPrefEnv({
    358    set: [
    359      ["browser.urlbar.suggest.openpage", false],
    360      ["browser.urlbar.suggest.bookmark", false],
    361    ],
    362  });
    363 
    364  let sites = await getTopSites();
    365  Assert.equal(
    366    sites.length,
    367    7,
    368    "The test suite browser should have 7 Top Sites."
    369  );
    370 
    371  await UrlbarTestUtils.promisePopupOpen(window, () => {
    372    if (gURLBar.getAttribute("pageproxystate") == "invalid") {
    373      gURLBar.handleRevert();
    374    }
    375    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    376  });
    377  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    378  await UrlbarTestUtils.promiseSearchComplete(window);
    379 
    380  Assert.equal(
    381    UrlbarTestUtils.getResultCount(window),
    382    7,
    383    "The number of results should be the same as the number of Top Sites (7)."
    384  );
    385 
    386  let exampleResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 0);
    387  Assert.equal(
    388    exampleResult.url,
    389    "http://example.com/",
    390    "The example.com Top Site should be the second result."
    391  );
    392  Assert.equal(
    393    exampleResult.source,
    394    UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    395    "The example.com Top Site should appear as a normal result even though it's open in a tab."
    396  );
    397 
    398  let youtubeResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 1);
    399  Assert.equal(
    400    youtubeResult.url,
    401    "https://www.youtube.com/",
    402    "The YouTube Top Site should be the third result."
    403  );
    404  Assert.equal(
    405    youtubeResult.source,
    406    UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    407    "The YouTube Top Site should appear as a normal result even though it's bookmarked."
    408  );
    409  await UrlbarTestUtils.promisePopupClose(window, () => {
    410    gURLBar.blur();
    411  });
    412 
    413  await PlacesUtils.bookmarks.eraseEverything();
    414  await PlacesUtils.history.clear();
    415  await SpecialPowers.popPrefEnv();
    416 });
    417 
    418 add_task(async function topSitesDisabled() {
    419  // Disable Top Sites feed.
    420  await SpecialPowers.pushPrefEnv({
    421    set: [["browser.newtabpage.activity-stream.feeds.system.topsites", false]],
    422  });
    423  await checkDoesNotOpenOnFocus();
    424  await SpecialPowers.popPrefEnv();
    425 
    426  // Top Sites should also not be shown when Urlbar Top Sites are disabled.
    427  await SpecialPowers.pushPrefEnv({
    428    set: [["browser.urlbar.suggest.topsites", false]],
    429  });
    430  await checkDoesNotOpenOnFocus();
    431  await SpecialPowers.popPrefEnv();
    432 });
    433 
    434 add_task(async function topSitesNumber() {
    435  // Add some visits
    436  for (let i = 0; i < 5; i++) {
    437    await PlacesTestUtils.addVisits([
    438      "http://example-a.com/",
    439      "http://example-b.com/",
    440      "http://example-c.com/",
    441      "http://example-d.com/",
    442      "http://example-e.com/",
    443    ]);
    444  }
    445 
    446  // Wait for the expected number of Top sites.
    447  await updateTopSites(sites => sites && sites.length == 8);
    448  Assert.equal(
    449    (await getTopSites()).length,
    450    8,
    451    "The test suite browser should have 8 Top Sites."
    452  );
    453 
    454  await UrlbarTestUtils.promisePopupOpen(window, () => {
    455    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    456  });
    457  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    458  await UrlbarTestUtils.promiseSearchComplete(window);
    459  Assert.equal(
    460    UrlbarTestUtils.getResultCount(window),
    461    8,
    462    "The number of results should be the default (8)."
    463  );
    464  await UrlbarTestUtils.promisePopupClose(window);
    465 
    466  await SpecialPowers.pushPrefEnv({
    467    set: [["browser.newtabpage.activity-stream.topSitesRows", 2]],
    468  });
    469  // Wait for the expected number of Top sites.
    470  await updateTopSites(sites => sites && sites.length == 11);
    471  Assert.equal(
    472    (await getTopSites()).length,
    473    11,
    474    "The test suite browser should have 11 Top Sites."
    475  );
    476 
    477  await UrlbarTestUtils.promisePopupOpen(window, () => {
    478    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    479  });
    480  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    481  await UrlbarTestUtils.promiseSearchComplete(window);
    482 
    483  Assert.equal(
    484    UrlbarTestUtils.getResultCount(window),
    485    10,
    486    "The number of results should be maxRichResults (10)."
    487  );
    488  await UrlbarTestUtils.promisePopupClose(window);
    489 
    490  await SpecialPowers.popPrefEnv();
    491  await PlacesUtils.history.clear();
    492 });
    493 
    494 add_task(async function tabSwitchBehavior() {
    495  let exampleTab = gBrowser.selectedTab;
    496  let aboutRobotsTab = await BrowserTestUtils.openNewForegroundTab(
    497    gBrowser,
    498    "about:robots"
    499  );
    500 
    501  registerCleanupFunction(() => {
    502    BrowserTestUtils.removeTab(aboutRobotsTab);
    503  });
    504 
    505  await BrowserTestUtils.switchTab(gBrowser, exampleTab);
    506 
    507  let sites = AboutNewTab.getTopSites();
    508  Assert.equal(
    509    sites.length,
    510    6,
    511    "The test suite browser should have 6 Top Sites."
    512  );
    513 
    514  await UrlbarTestUtils.promisePopupOpen(window, () => {
    515    if (gURLBar.getAttribute("pageproxystate") == "invalid") {
    516      gURLBar.handleRevert();
    517    }
    518    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    519  });
    520  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    521  await UrlbarTestUtils.promiseSearchComplete(window);
    522 
    523  Assert.equal(
    524    UrlbarTestUtils.getResultCount(window),
    525    6,
    526    "The number of results should be the same as the number of Top Sites (6)."
    527  );
    528 
    529  let aboutRobotsResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 4);
    530  Assert.equal(
    531    aboutRobotsResult.url,
    532    "about:robots",
    533    "The about:robots Top Site should be the 5th result."
    534  );
    535  Assert.equal(
    536    aboutRobotsResult.source,
    537    UrlbarUtils.RESULT_SOURCE.TABS,
    538    "The about:robots Top Site should appear as an open tab result."
    539  );
    540 
    541  await UrlbarTestUtils.promisePopupClose(window, () => {
    542    gURLBar.blur();
    543  });
    544 
    545  await BrowserTestUtils.switchTab(gBrowser, aboutRobotsTab);
    546 
    547  sites = AboutNewTab.getTopSites();
    548  Assert.equal(
    549    sites.length,
    550    6,
    551    "The test suite browser should have 6 Top Sites."
    552  );
    553 
    554  await UrlbarTestUtils.promisePopupOpen(window, () => {
    555    if (gURLBar.getAttribute("pageproxystate") == "invalid") {
    556      gURLBar.handleRevert();
    557    }
    558    EventUtils.synthesizeMouseAtCenter(gURLBar.inputField, {});
    559  });
    560  Assert.ok(gURLBar.view.isOpen, "UrlbarView should be open.");
    561  await UrlbarTestUtils.promiseSearchComplete(window);
    562 
    563  Assert.equal(
    564    UrlbarTestUtils.getResultCount(window),
    565    6,
    566    "The number of results should be the same as the number of Top Sites (6)."
    567  );
    568 
    569  aboutRobotsResult = await UrlbarTestUtils.getDetailsOfResultAt(window, 4);
    570  Assert.equal(
    571    aboutRobotsResult.url,
    572    "about:robots",
    573    "The about:robots Top Site should be the 5th result."
    574  );
    575  Assert.equal(
    576    aboutRobotsResult.source,
    577    UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    578    "The about:robots Top Site should appear as a regular result."
    579  );
    580 
    581  await UrlbarTestUtils.promisePopupClose(window, () => {
    582    gURLBar.blur();
    583  });
    584 
    585  await PlacesUtils.history.clear();
    586 });