tor-browser

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

test_providerHeuristicFallback.js (23514B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 /**
      5 * Tests that visit-url and search engine heuristic results are returned by
      6 * UrlbarProviderHeuristicFallback.
      7 */
      8 
      9 const QUICKACTIONS_PREF = "browser.urlbar.suggest.quickactions";
     10 const SUGGEST_ENABLED_PREF = "browser.search.suggest.enabled";
     11 const PRIVATE_SEARCH_PREF = "browser.search.separatePrivateDefault.ui.enabled";
     12 
     13 // We make sure that restriction tokens and search terms are correctly
     14 // recognized when they are separated by each of these different types of spaces
     15 // and combinations of spaces.  U+3000 is the ideographic space in CJK and is
     16 // commonly used by CJK speakers.
     17 const TEST_SPACES = [" ", "\u3000", " \u3000", "\u3000 "];
     18 
     19 testEngine_setup();
     20 
     21 add_setup(async function () {
     22  registerCleanupFunction(async () => {
     23    Services.prefs.clearUserPref(QUICKACTIONS_PREF);
     24    Services.prefs.clearUserPref(SUGGEST_ENABLED_PREF);
     25    Services.prefs.clearUserPref(PRIVATE_SEARCH_PREF);
     26    Services.prefs.clearUserPref("keyword.enabled");
     27  });
     28  Services.prefs.setBoolPref(QUICKACTIONS_PREF, false);
     29  Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, false);
     30  Services.prefs.setBoolPref(PRIVATE_SEARCH_PREF, false);
     31 });
     32 
     33 add_task(async function () {
     34  info("visit url, no protocol");
     35  let query = "mozilla.org";
     36  let context = createContext(query, { isPrivate: false });
     37  await check_results({
     38    context,
     39    matches: [
     40      makeVisitResult(context, {
     41        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
     42        uri: `http://${query}/`,
     43        title: `${query}/`,
     44        heuristic: true,
     45      }),
     46      makeSearchResult(context, {
     47        engineName: SUGGESTIONS_ENGINE_NAME,
     48      }),
     49    ],
     50  });
     51 
     52  info("visit url, no protocol but with 2 dots");
     53  query = "www.mozilla.org";
     54  context = createContext(query, { isPrivate: false });
     55  await check_results({
     56    context,
     57    matches: [
     58      makeVisitResult(context, {
     59        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
     60        uri: `http://${query}/`,
     61        title: `${query}/`,
     62        heuristic: true,
     63      }),
     64      makeSearchResult(context, {
     65        engineName: SUGGESTIONS_ENGINE_NAME,
     66      }),
     67    ],
     68  });
     69 
     70  info("visit url, no protocol, e-mail like");
     71  query = "a@b.com";
     72  context = createContext(query, { isPrivate: false });
     73  await check_results({
     74    context,
     75    matches: [
     76      makeVisitResult(context, {
     77        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
     78        uri: `http://${query}/`,
     79        title: `${query}/`,
     80        heuristic: true,
     81      }),
     82      makeSearchResult(context, {
     83        engineName: SUGGESTIONS_ENGINE_NAME,
     84      }),
     85    ],
     86  });
     87 
     88  info("visit url, with protocol but with 2 dots");
     89  query = "https://www.mozilla.org";
     90  context = createContext(query, { isPrivate: false });
     91  await check_results({
     92    context,
     93    matches: [
     94      makeVisitResult(context, {
     95        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
     96        uri: `${query}/`,
     97        title: `${query}/`,
     98        heuristic: true,
     99      }),
    100    ],
    101  });
    102 
    103  // info("visit url, with protocol but with 3 dots");
    104  query = "https://www.mozilla.org.tw";
    105  context = createContext(query, { isPrivate: false });
    106  await check_results({
    107    context,
    108    matches: [
    109      makeVisitResult(context, {
    110        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    111        uri: `${query}/`,
    112        title: `${query}/`,
    113        heuristic: true,
    114      }),
    115    ],
    116  });
    117 
    118  info("visit url, with protocol");
    119  query = "https://mozilla.org";
    120  context = createContext(query, { isPrivate: false });
    121  await check_results({
    122    context,
    123    matches: [
    124      makeVisitResult(context, {
    125        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    126        uri: `${query}/`,
    127        title: `${query}/`,
    128        heuristic: true,
    129      }),
    130    ],
    131  });
    132 
    133  info("visit url on searchbar (should search)");
    134  query = "https://mozilla.org";
    135  context = createContext(query, {
    136    isPrivate: false,
    137    sapName: "searchbar",
    138  });
    139  await check_results({
    140    context,
    141    matches: [
    142      makeSearchResult(context, {
    143        engineName: SUGGESTIONS_ENGINE_NAME,
    144        heuristic: true,
    145        query,
    146      }),
    147    ],
    148  });
    149 
    150  info("visit url, about: protocol (no host)");
    151  query = "about:nonexistent";
    152  context = createContext(query, { isPrivate: false });
    153  await check_results({
    154    context,
    155    matches: [
    156      makeVisitResult(context, {
    157        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    158        uri: query,
    159        title: query,
    160        heuristic: true,
    161      }),
    162    ],
    163  });
    164 
    165  info("visit url, with non-standard whitespace");
    166  query = "https://mozilla.org";
    167  context = createContext(`${query}\u2028`, { isPrivate: false });
    168  await check_results({
    169    context,
    170    matches: [
    171      makeVisitResult(context, {
    172        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    173        uri: `${query}/`,
    174        title: `${query}/`,
    175        heuristic: true,
    176      }),
    177    ],
    178  });
    179 
    180  // This is distinct because of how we predict being able to url autofill via
    181  // host lookups.
    182  info("visit url, host matching visited host but not visited url");
    183  await PlacesTestUtils.addVisits([
    184    {
    185      uri: Services.io.newURI("http://mozilla.org/wine/"),
    186      title: "Mozilla Wine",
    187      transition: PlacesUtils.history.TRANSITION_TYPED,
    188    },
    189  ]);
    190  query = "mozilla.org/rum";
    191  context = createContext(`${query}\u2028`, { isPrivate: false });
    192  await check_results({
    193    context,
    194    matches: [
    195      makeVisitResult(context, {
    196        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    197        uri: `http://${query}`,
    198        title: `${query}`,
    199        iconUri: "page-icon:http://mozilla.org/",
    200        heuristic: true,
    201      }),
    202    ],
    203  });
    204  await PlacesUtils.history.clear();
    205 
    206  // And hosts with no dot in them are special, due to requiring safelisting.
    207  info("unknown host");
    208  query = "firefox";
    209  context = createContext(query, { isPrivate: false });
    210  await check_results({
    211    context,
    212    matches: [
    213      makeSearchResult(context, {
    214        engineName: SUGGESTIONS_ENGINE_NAME,
    215        heuristic: true,
    216      }),
    217    ],
    218  });
    219 
    220  info("string with known host");
    221  query = "firefox/get";
    222  context = createContext(query, { isPrivate: false });
    223  await check_results({
    224    context,
    225    matches: [
    226      makeSearchResult(context, {
    227        engineName: SUGGESTIONS_ENGINE_NAME,
    228        heuristic: true,
    229      }),
    230    ],
    231  });
    232 
    233  Services.prefs.setBoolPref("browser.fixup.domainwhitelist.firefox", true);
    234  registerCleanupFunction(() => {
    235    Services.prefs.clearUserPref("browser.fixup.domainwhitelist.firefox");
    236  });
    237 
    238  info("known host");
    239  query = "firefox";
    240  context = createContext(query, { isPrivate: false });
    241  await check_results({
    242    context,
    243    matches: [
    244      makeVisitResult(context, {
    245        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    246        uri: `http://${query}/`,
    247        title: `${query}/`,
    248        heuristic: true,
    249      }),
    250      makeSearchResult(context, {
    251        engineName: SUGGESTIONS_ENGINE_NAME,
    252      }),
    253    ],
    254  });
    255 
    256  info("url with known host");
    257  query = "firefox/get";
    258  context = createContext(query, { isPrivate: false });
    259  await check_results({
    260    context,
    261    matches: [
    262      makeVisitResult(context, {
    263        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    264        uri: `http://${query}`,
    265        title: `${query}`,
    266        iconUri: "page-icon:http://firefox/",
    267        heuristic: true,
    268      }),
    269    ],
    270  });
    271 
    272  info("visit url, host matching visited host but not visited url, known host");
    273  Services.prefs.setBoolPref("browser.fixup.domainwhitelist.mozilla", true);
    274  registerCleanupFunction(() => {
    275    Services.prefs.clearUserPref("browser.fixup.domainwhitelist.mozilla");
    276  });
    277  query = "mozilla/rum";
    278  context = createContext(query, { isPrivate: false });
    279  await check_results({
    280    context,
    281    matches: [
    282      makeVisitResult(context, {
    283        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    284        uri: `http://${query}`,
    285        title: `${query}`,
    286        iconUri: "page-icon:http://mozilla/",
    287        heuristic: true,
    288      }),
    289    ],
    290  });
    291 
    292  // ipv4 and ipv6 literal addresses should offer to visit.
    293  info("visit url, ipv4 literal");
    294  query = "127.0.0.1";
    295  context = createContext(query, { isPrivate: false });
    296  await check_results({
    297    context,
    298    matches: [
    299      makeVisitResult(context, {
    300        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    301        uri: `http://${query}/`,
    302        title: `${query}/`,
    303        heuristic: true,
    304      }),
    305    ],
    306  });
    307 
    308  info("visit url, ipv6 literal");
    309  query = "[2001:db8::1]";
    310  context = createContext(query, { isPrivate: false });
    311  await check_results({
    312    context,
    313    matches: [
    314      makeVisitResult(context, {
    315        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    316        uri: `http://${query}/`,
    317        title: `${query}/`,
    318        heuristic: true,
    319      }),
    320    ],
    321  });
    322 
    323  // Setting keyword.enabled to false should always try to visit.
    324  let keywordEnabled = Services.prefs.getBoolPref("keyword.enabled");
    325  Services.prefs.setBoolPref("keyword.enabled", false);
    326  registerCleanupFunction(() => {
    327    Services.prefs.clearUserPref("keyword.enabled");
    328  });
    329  info("visit url, keyword.enabled = false");
    330  query = "bacon";
    331  context = createContext(query, { isPrivate: false });
    332  await check_results({
    333    context,
    334    matches: [
    335      makeVisitResult(context, {
    336        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    337        uri: `http://${query}/`,
    338        title: `${query}/`,
    339        heuristic: true,
    340      }),
    341    ],
    342  });
    343 
    344  info("visit two word query, keyword.enabled = false");
    345  query = "bacon lovers";
    346  context = createContext(query, { isPrivate: false });
    347  await check_results({
    348    context,
    349    matches: [
    350      makeVisitResult(context, {
    351        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    352        uri: query,
    353        title: query,
    354        heuristic: true,
    355      }),
    356    ],
    357  });
    358 
    359  info("Forced search through a restriction token, keyword.enabled = false");
    360  query = "?bacon";
    361  context = createContext(query, { isPrivate: false });
    362  await check_results({
    363    context,
    364    matches: [
    365      makeSearchResult(context, {
    366        engineName: SUGGESTIONS_ENGINE_NAME,
    367        heuristic: true,
    368        query: "bacon",
    369      }),
    370    ],
    371  });
    372 
    373  info("Forced search through search mode, keyword.enabled = false");
    374  query = "bacon";
    375  context = createContext(query, {
    376    isPrivate: false,
    377    searchMode: {
    378      engineName: SUGGESTIONS_ENGINE_NAME,
    379      isGeneralPurposeEngine: false,
    380    },
    381  });
    382  await check_results({
    383    context,
    384    matches: [
    385      makeSearchResult(context, {
    386        engineName: SUGGESTIONS_ENGINE_NAME,
    387        heuristic: true,
    388        query: "bacon",
    389      }),
    390    ],
    391  });
    392 
    393  info("Forced search through searchbar, keyword.enabled = false");
    394  query = "bacon";
    395  context = createContext(query, {
    396    isPrivate: false,
    397    sapName: "searchbar",
    398  });
    399  await check_results({
    400    context,
    401    matches: [
    402      makeSearchResult(context, {
    403        engineName: SUGGESTIONS_ENGINE_NAME,
    404        heuristic: true,
    405        query: "bacon",
    406      }),
    407    ],
    408  });
    409 
    410  info("Non-search restriction token and invalid URL, keyword.enabled = false");
    411  query = "bacon *";
    412  context = createContext(query, { isPrivate: false });
    413  await check_results({
    414    context,
    415    matches: [],
    416  });
    417 
    418  Services.prefs.setBoolPref("keyword.enabled", true);
    419  info("visit two word query, keyword.enabled = true");
    420  query = "bacon lovers";
    421  context = createContext(query, { isPrivate: false });
    422  await check_results({
    423    context,
    424    matches: [
    425      makeSearchResult(context, {
    426        engineName: SUGGESTIONS_ENGINE_NAME,
    427        heuristic: true,
    428      }),
    429    ],
    430  });
    431 
    432  Services.prefs.setBoolPref("keyword.enabled", keywordEnabled);
    433 
    434  info("visit url, scheme+host");
    435  query = "http://example";
    436  context = createContext(query, { isPrivate: false });
    437  await check_results({
    438    context,
    439    matches: [
    440      makeVisitResult(context, {
    441        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    442        uri: `${query}/`,
    443        title: `${query}/`,
    444        heuristic: true,
    445      }),
    446    ],
    447  });
    448 
    449  info("visit url, scheme+host");
    450  query = "ftp://example";
    451  context = createContext(query, { isPrivate: false });
    452  await check_results({
    453    context,
    454    matches: [
    455      makeVisitResult(context, {
    456        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    457        uri: `${query}/`,
    458        title: `${query}/`,
    459        heuristic: true,
    460      }),
    461    ],
    462  });
    463 
    464  info("visit url, host+port");
    465  query = "example:8080";
    466  context = createContext(query, { isPrivate: false });
    467  await check_results({
    468    context,
    469    matches: [
    470      makeVisitResult(context, {
    471        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    472        uri: `http://${query}/`,
    473        title: `${query}/`,
    474        heuristic: true,
    475      }),
    476    ],
    477  });
    478 
    479  info("numerical operations that look like urls should search");
    480  query = "123/12";
    481  context = createContext(query, { isPrivate: false });
    482  await check_results({
    483    context,
    484    matches: [
    485      makeSearchResult(context, {
    486        engineName: SUGGESTIONS_ENGINE_NAME,
    487        heuristic: true,
    488      }),
    489      makeCalculatorResult(context, {
    490        value: Number((123 / 12).toFixed(8)).toString(),
    491      }),
    492    ],
    493  });
    494 
    495  info("numerical operations that look like urls should search");
    496  query = "123.12/12.1";
    497  context = createContext(query, { isPrivate: false });
    498  await check_results({
    499    context,
    500    matches: [
    501      makeSearchResult(context, {
    502        engineName: SUGGESTIONS_ENGINE_NAME,
    503        heuristic: true,
    504      }),
    505      makeCalculatorResult(context, {
    506        value: Number((123.12 / 12.1).toFixed(8)).toString(),
    507      }),
    508    ],
    509  });
    510 
    511  query = "resource:///modules";
    512  context = createContext(query, { isPrivate: false });
    513  await check_results({
    514    context,
    515    matches: [
    516      makeVisitResult(context, {
    517        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    518        uri: query,
    519        title: query,
    520        heuristic: true,
    521      }),
    522    ],
    523  });
    524 
    525  info("access resource://app/modules");
    526  query = "resource://app/modules";
    527  context = createContext(query, { isPrivate: false });
    528  await check_results({
    529    context,
    530    matches: [
    531      makeVisitResult(context, {
    532        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    533        uri: query,
    534        title: query,
    535        heuristic: true,
    536      }),
    537    ],
    538  });
    539 
    540  info("protocol with an extra slash");
    541  query = "http:///";
    542  context = createContext(query, { isPrivate: false });
    543  await check_results({
    544    context,
    545    matches: [
    546      makeSearchResult(context, {
    547        engineName: SUGGESTIONS_ENGINE_NAME,
    548        heuristic: true,
    549      }),
    550    ],
    551  });
    552 
    553  info("change default engine");
    554  let originalTestEngine = Services.search.getEngineByName(
    555    SUGGESTIONS_ENGINE_NAME
    556  );
    557  await SearchTestUtils.installSearchExtension({
    558    name: "AliasEngine",
    559    keyword: "alias",
    560  });
    561  let engine2 = Services.search.getEngineByName("AliasEngine");
    562  Assert.notEqual(
    563    Services.search.defaultEngine,
    564    engine2,
    565    "New engine shouldn't be the current engine yet"
    566  );
    567  await Services.search.setDefault(
    568    engine2,
    569    Ci.nsISearchService.CHANGE_REASON_UNKNOWN
    570  );
    571  query = "toronto";
    572  context = createContext(query, { isPrivate: false });
    573  await check_results({
    574    context,
    575    matches: [
    576      makeSearchResult(context, {
    577        engineName: "AliasEngine",
    578        heuristic: true,
    579      }),
    580    ],
    581  });
    582  await Services.search.setDefault(
    583    originalTestEngine,
    584    Ci.nsISearchService.CHANGE_REASON_UNKNOWN
    585  );
    586 
    587  info(
    588    "Leading search-mode restriction tokens are removed from the search result."
    589  );
    590  for (let token of UrlbarTokenizer.SEARCH_MODE_RESTRICT) {
    591    for (let spaces of TEST_SPACES) {
    592      query = token + spaces + "query";
    593      info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) }));
    594      let expectedQuery = query.substring(1).trimStart();
    595      context = createContext(query, { isPrivate: false });
    596      info(`Searching for "${query}", expecting "${expectedQuery}"`);
    597      let payload = {
    598        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    599        heuristic: true,
    600        query: expectedQuery,
    601        alias: token,
    602      };
    603      if (token == UrlbarTokenizer.RESTRICT.SEARCH) {
    604        payload.source = UrlbarUtils.RESULT_SOURCE.SEARCH;
    605        payload.engineName = SUGGESTIONS_ENGINE_NAME;
    606      }
    607      await check_results({
    608        context,
    609        matches: [makeSearchResult(context, payload)],
    610      });
    611    }
    612  }
    613 
    614  info(
    615    "Leading search-mode restriction tokens are removed from the search result with keyword.enabled = false."
    616  );
    617  Services.prefs.setBoolPref("keyword.enabled", false);
    618  for (let token of UrlbarTokenizer.SEARCH_MODE_RESTRICT) {
    619    for (let spaces of TEST_SPACES) {
    620      query = token + spaces + "query";
    621      info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) }));
    622      let expectedQuery = query.substring(1).trimStart();
    623      context = createContext(query, { isPrivate: false });
    624      info(`Searching for "${query}", expecting "${expectedQuery}"`);
    625      let payload = {
    626        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    627        heuristic: true,
    628        query: expectedQuery,
    629        alias: token,
    630      };
    631      if (token == UrlbarTokenizer.RESTRICT.SEARCH) {
    632        payload.source = UrlbarUtils.RESULT_SOURCE.SEARCH;
    633        payload.engineName = SUGGESTIONS_ENGINE_NAME;
    634      }
    635      await check_results({
    636        context,
    637        matches: [makeSearchResult(context, payload)],
    638      });
    639    }
    640  }
    641  Services.prefs.clearUserPref("keyword.enabled");
    642 
    643  info(
    644    "Leading non-search-mode restriction tokens are not removed from the search result."
    645  );
    646  for (let token of Object.values(UrlbarTokenizer.RESTRICT)) {
    647    if (UrlbarTokenizer.SEARCH_MODE_RESTRICT.has(token)) {
    648      continue;
    649    }
    650    for (let spaces of TEST_SPACES) {
    651      query = token + spaces + "query";
    652      info("Testing: " + JSON.stringify({ query, spaces: codePoints(spaces) }));
    653      let expectedQuery = query;
    654      context = createContext(query, { isPrivate: false });
    655      info(`Searching for "${query}", expecting "${expectedQuery}"`);
    656      await check_results({
    657        context,
    658        matches: [
    659          makeSearchResult(context, {
    660            heuristic: true,
    661            query: expectedQuery,
    662            engineName: SUGGESTIONS_ENGINE_NAME,
    663          }),
    664        ],
    665      });
    666    }
    667  }
    668 
    669  info(
    670    "Test the format inputed is user@host, and the host is in domainwhitelist"
    671  );
    672  Services.prefs.setBoolPref("browser.fixup.domainwhitelist.test-host", true);
    673  registerCleanupFunction(() => {
    674    Services.prefs.clearUserPref("browser.fixup.domainwhitelist.test-host");
    675  });
    676 
    677  query = "any@test-host";
    678  context = createContext(query, { isPrivate: false });
    679  await check_results({
    680    context,
    681    matches: [
    682      makeVisitResult(context, {
    683        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    684        uri: `http://${query}/`,
    685        title: `${query}/`,
    686        heuristic: true,
    687      }),
    688      makeSearchResult(context, {
    689        engineName: SUGGESTIONS_ENGINE_NAME,
    690      }),
    691    ],
    692  });
    693 
    694  info(
    695    "Test the format inputed is user@host, but the host is not in domainwhitelist"
    696  );
    697  query = "any@not-host";
    698  context = createContext(query, { isPrivate: false });
    699  await check_results({
    700    context,
    701    matches: [
    702      makeSearchResult(context, {
    703        heuristic: true,
    704        query,
    705        engineName: SUGGESTIONS_ENGINE_NAME,
    706      }),
    707    ],
    708  });
    709 
    710  info(
    711    "Test if the format of user:pass@host is handled as visit even if the host is not in domainwhitelist"
    712  );
    713  query = "user:pass@not-host";
    714  context = createContext(query, { isPrivate: false });
    715  await check_results({
    716    context,
    717    matches: [
    718      makeVisitResult(context, {
    719        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    720        uri: "http://user:pass@not-host/",
    721        title: "user:pass@not-host/",
    722        heuristic: true,
    723      }),
    724    ],
    725  });
    726 
    727  info("Test if the format of user@ipaddress is handled as visit");
    728  query = "user@192.168.0.1";
    729  context = createContext(query, { isPrivate: false });
    730  await check_results({
    731    context,
    732    matches: [
    733      makeVisitResult(context, {
    734        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    735        uri: "http://user@192.168.0.1/",
    736        title: "user@192.168.0.1/",
    737        heuristic: true,
    738      }),
    739      makeSearchResult(context, {
    740        heuristic: false,
    741        query,
    742        engineName: SUGGESTIONS_ENGINE_NAME,
    743      }),
    744    ],
    745  });
    746 
    747  await PlacesUtils.history.clear();
    748  // Check that punycode results are properly decoded before being displayed.
    749  info("visit url, host matching visited host but not visited url");
    750  await PlacesTestUtils.addVisits([
    751    {
    752      uri: Services.io.newURI("http://test.пример.com/"),
    753      title: "test.пример.com",
    754      transition: PlacesUtils.history.TRANSITION_TYPED,
    755    },
    756  ]);
    757  context = createContext("test", { isPrivate: false });
    758  await check_results({
    759    context,
    760    matches: [
    761      makeVisitResult(context, {
    762        source: UrlbarUtils.RESULT_SOURCE.HISTORY,
    763        uri: `http://test.xn--e1afmkfd.com/`,
    764        title: "test.пример.com",
    765        heuristic: true,
    766        iconUri: "page-icon:http://test.xn--e1afmkfd.com/",
    767      }),
    768    ],
    769  });
    770  await PlacesUtils.history.clear();
    771 });
    772 
    773 add_task(async function dont_fixup_urls_with_at_symbol() {
    774  info("don't fixup search string if it contains no protocol and spaces.");
    775  let query = "Lorem Ipsum @mozilla.org";
    776  let context = createContext(query, { isPrivate: false });
    777  await check_results({
    778    context,
    779    matches: [
    780      makeSearchResult(context, {
    781        engineName: SUGGESTIONS_ENGINE_NAME,
    782        heuristic: true,
    783      }),
    784    ],
    785  });
    786 
    787  query = "http://Lorem Ipsum @mozilla.org";
    788  context = createContext(query, { isPrivate: false });
    789  await check_results({
    790    context,
    791    matches: [
    792      makeVisitResult(context, {
    793        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    794        uri: `http://Lorem%20Ipsum%20@mozilla.org/`,
    795        title: `${query}/`,
    796        heuristic: true,
    797      }),
    798    ],
    799  });
    800  query = "https://Lorem Ipsum @mozilla.org";
    801  context = createContext(query, { isPrivate: false });
    802  await check_results({
    803    context,
    804    matches: [
    805      makeVisitResult(context, {
    806        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    807        uri: `https://Lorem%20Ipsum%20@mozilla.org/`,
    808        title: `${query}/`,
    809        heuristic: true,
    810      }),
    811    ],
    812  });
    813 
    814  query = "LoremIpsum@mozilla.org";
    815  context = createContext(query, { isPrivate: false });
    816  await check_results({
    817    context,
    818    matches: [
    819      makeVisitResult(context, {
    820        source: UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL,
    821        uri: `http://${query}/`,
    822        title: `${query}/`,
    823        heuristic: true,
    824      }),
    825      makeSearchResult(context, {
    826        engineName: SUGGESTIONS_ENGINE_NAME,
    827      }),
    828    ],
    829  });
    830 
    831  query = "";
    832  context = createContext(query, { isPrivate: false });
    833  await check_results({
    834    context,
    835    matches: [],
    836  });
    837 });
    838 
    839 /**
    840 * Returns an array of code points in the given string.  Each code point is
    841 * returned as a hexidecimal string.
    842 *
    843 * @param {string} str
    844 *   The code points of this string will be returned.
    845 * @returns {Array}
    846 *   Array of code points in the string, where each is a hexidecimal string.
    847 */
    848 function codePoints(str) {
    849  return str.split("").map(s => s.charCodeAt(0).toString(16));
    850 }