tor-browser

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

test_ext_settings_overrides_search.js (16349B)


      1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
      2 /* vim: set sts=2 sw=2 et tw=80: */
      3 
      4 "use strict";
      5 
      6 const { AddonTestUtils } = ChromeUtils.importESModule(
      7  "resource://testing-common/AddonTestUtils.sys.mjs"
      8 );
      9 const { setTimeout } = ChromeUtils.importESModule(
     10  "resource://gre/modules/Timer.sys.mjs"
     11 );
     12 
     13 let delay = () => new Promise(resolve => setTimeout(resolve, 0));
     14 
     15 const kSearchEngineURL = "https://example.com/?search={searchTerms}";
     16 const kSearchSuggestURL = "https://example.com/?suggest={searchTerms}";
     17 const kSearchTerm = "foo";
     18 const kSearchTermIntl = "日";
     19 const URLTYPE_SUGGEST_JSON = "application/x-suggestions+json";
     20 
     21 AddonTestUtils.init(this);
     22 AddonTestUtils.createAppInfo(
     23  "xpcshell@tests.mozilla.org",
     24  "XPCShell",
     25  "42",
     26  "42"
     27 );
     28 
     29 add_task(async function setup() {
     30  await AddonTestUtils.promiseStartupManager();
     31  await Services.search.init();
     32 });
     33 
     34 add_task(async function test_extension_adding_engine() {
     35  let ext1 = ExtensionTestUtils.loadExtension({
     36    manifest: {
     37      icons: {
     38        16: "foo.ico",
     39        32: "foo32.ico",
     40      },
     41      chrome_settings_overrides: {
     42        search_provider: {
     43          name: "MozSearch",
     44          keyword: "MozSearch",
     45          search_url: kSearchEngineURL,
     46          suggest_url: kSearchSuggestURL,
     47        },
     48      },
     49    },
     50    useAddonManager: "temporary",
     51  });
     52 
     53  await ext1.startup();
     54  await AddonTestUtils.waitForSearchProviderStartup(ext1);
     55 
     56  let engine = Services.search.getEngineByName("MozSearch");
     57  ok(engine, "Engine should exist.");
     58 
     59  let { baseURI } = ext1.extension;
     60  equal(
     61    await engine.getIconURL(),
     62    baseURI.resolve("foo.ico"),
     63    "16x16 icon path matches"
     64  );
     65  equal(
     66    await engine.getIconURL(16),
     67    baseURI.resolve("foo.ico"),
     68    "16x16 icon path matches"
     69  );
     70 
     71  equal(
     72    await engine.getIconURL(32),
     73    baseURI.resolve("foo32.ico"),
     74    "32x32 icon path matches"
     75  );
     76 
     77  let expectedSuggestURL = kSearchSuggestURL.replace(
     78    "{searchTerms}",
     79    kSearchTerm
     80  );
     81  let submissionSuggest = engine.getSubmission(
     82    kSearchTerm,
     83    URLTYPE_SUGGEST_JSON
     84  );
     85  let encodedSubmissionURL = engine.getSubmission(kSearchTermIntl).uri.spec;
     86  let testSubmissionURL = kSearchEngineURL.replace(
     87    "{searchTerms}",
     88    encodeURIComponent(kSearchTermIntl)
     89  );
     90  equal(
     91    encodedSubmissionURL,
     92    testSubmissionURL,
     93    "Encoded UTF-8 URLs should match"
     94  );
     95 
     96  equal(
     97    submissionSuggest.uri.spec,
     98    expectedSuggestURL,
     99    "Suggest URLs should match"
    100  );
    101 
    102  await ext1.unload();
    103  await delay();
    104 
    105  engine = Services.search.getEngineByName("MozSearch");
    106  ok(!engine, "Engine should not exist");
    107 });
    108 
    109 add_task(async function test_extension_adding_engine_with_spaces() {
    110  let ext1 = ExtensionTestUtils.loadExtension({
    111    manifest: {
    112      chrome_settings_overrides: {
    113        search_provider: {
    114          name: "MozSearch     ",
    115          keyword: "MozSearch",
    116          search_url: "https://example.com/?q={searchTerms}",
    117        },
    118      },
    119    },
    120    useAddonManager: "temporary",
    121  });
    122 
    123  await ext1.startup();
    124  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    125 
    126  let engine = Services.search.getEngineByName("MozSearch");
    127  ok(engine, "Engine should exist.");
    128 
    129  await ext1.unload();
    130  await delay();
    131 
    132  engine = Services.search.getEngineByName("MozSearch");
    133  ok(!engine, "Engine should not exist");
    134 });
    135 
    136 add_task(async function test_upgrade_default_position_engine() {
    137  let ext1 = ExtensionTestUtils.loadExtension({
    138    manifest: {
    139      chrome_settings_overrides: {
    140        search_provider: {
    141          name: "MozSearch",
    142          keyword: "MozSearch",
    143          search_url: "https://example.com/?q={searchTerms}",
    144        },
    145      },
    146      browser_specific_settings: {
    147        gecko: {
    148          id: "testengine@mozilla.com",
    149        },
    150      },
    151      version: "0.1",
    152    },
    153    useAddonManager: "temporary",
    154  });
    155 
    156  await ext1.startup();
    157  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    158 
    159  let engine = Services.search.getEngineByName("MozSearch");
    160  await Services.search.setDefault(
    161    engine,
    162    Ci.nsISearchService.CHANGE_REASON_UNKNOWN
    163  );
    164  await Services.search.moveEngine(engine, 1);
    165 
    166  await ext1.upgrade({
    167    manifest: {
    168      chrome_settings_overrides: {
    169        search_provider: {
    170          name: "MozSearch",
    171          keyword: "MozSearch",
    172          search_url: "https://example.com/?q={searchTerms}",
    173        },
    174      },
    175      browser_specific_settings: {
    176        gecko: {
    177          id: "testengine@mozilla.com",
    178        },
    179      },
    180      version: "0.2",
    181    },
    182    useAddonManager: "temporary",
    183  });
    184  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    185 
    186  engine = Services.search.getEngineByName("MozSearch");
    187  equal(
    188    Services.search.defaultEngine,
    189    engine,
    190    "Default engine should still be MozSearch"
    191  );
    192  equal(
    193    (await Services.search.getEngines()).map(e => e.name).indexOf(engine.name),
    194    1,
    195    "Engine is in position 1"
    196  );
    197 
    198  await ext1.unload();
    199  await delay();
    200 
    201  engine = Services.search.getEngineByName("MozSearch");
    202  ok(!engine, "Engine should not exist");
    203 });
    204 
    205 add_task(async function test_extension_get_params() {
    206  let ext1 = ExtensionTestUtils.loadExtension({
    207    manifest: {
    208      chrome_settings_overrides: {
    209        search_provider: {
    210          name: "MozSearch",
    211          keyword: "MozSearch",
    212          search_url: kSearchEngineURL,
    213          search_url_get_params: "foo=bar&bar=foo",
    214          suggest_url: kSearchSuggestURL,
    215          suggest_url_get_params: "foo=bar&bar=foo",
    216        },
    217      },
    218    },
    219    useAddonManager: "temporary",
    220  });
    221 
    222  await ext1.startup();
    223  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    224 
    225  let engine = Services.search.getEngineByName("MozSearch");
    226  ok(engine, "Engine should exist.");
    227 
    228  let url = engine.wrappedJSObject.getURLOfType("text/html");
    229  equal(url.method, "GET", "Search URLs method is GET");
    230 
    231  let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
    232  let submission = engine.getSubmission(kSearchTerm);
    233  equal(
    234    submission.uri.spec,
    235    `${expectedURL}&foo=bar&bar=foo`,
    236    "Search URLs should match"
    237  );
    238 
    239  let expectedSuggestURL = kSearchSuggestURL.replace(
    240    "{searchTerms}",
    241    kSearchTerm
    242  );
    243  let submissionSuggest = engine.getSubmission(
    244    kSearchTerm,
    245    URLTYPE_SUGGEST_JSON
    246  );
    247  equal(
    248    submissionSuggest.uri.spec,
    249    `${expectedSuggestURL}&foo=bar&bar=foo`,
    250    "Suggest URLs should match"
    251  );
    252 
    253  await ext1.unload();
    254 });
    255 
    256 add_task(async function test_extension_post_params() {
    257  let ext1 = ExtensionTestUtils.loadExtension({
    258    manifest: {
    259      chrome_settings_overrides: {
    260        search_provider: {
    261          name: "MozSearch",
    262          keyword: "MozSearch",
    263          search_url: kSearchEngineURL,
    264          search_url_post_params: "foo=bar&bar=foo",
    265          suggest_url: kSearchSuggestURL,
    266          suggest_url_post_params: "foo=bar&bar=foo",
    267        },
    268      },
    269    },
    270    useAddonManager: "temporary",
    271  });
    272 
    273  await ext1.startup();
    274  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    275 
    276  let engine = Services.search.getEngineByName("MozSearch");
    277  ok(engine, "Engine should exist.");
    278 
    279  let url = engine.wrappedJSObject.getURLOfType("text/html");
    280  equal(url.method, "POST", "Search URLs method is POST");
    281 
    282  let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
    283  let submission = engine.getSubmission(kSearchTerm);
    284  equal(submission.uri.spec, expectedURL, "Search URLs should match");
    285  // postData is a nsIMIMEInputStream which contains a nsIStringInputStream.
    286  equal(
    287    submission.postData.data.data,
    288    "foo=bar&bar=foo",
    289    "Search postData should match"
    290  );
    291 
    292  let expectedSuggestURL = kSearchSuggestURL.replace(
    293    "{searchTerms}",
    294    kSearchTerm
    295  );
    296  let submissionSuggest = engine.getSubmission(
    297    kSearchTerm,
    298    URLTYPE_SUGGEST_JSON
    299  );
    300  equal(
    301    submissionSuggest.uri.spec,
    302    expectedSuggestURL,
    303    "Suggest URLs should match"
    304  );
    305  equal(
    306    submissionSuggest.postData.data.data,
    307    "foo=bar&bar=foo",
    308    "Suggest postData should match"
    309  );
    310 
    311  await ext1.unload();
    312 });
    313 
    314 add_task(async function test_extension_no_query_params() {
    315  const ext1 = ExtensionTestUtils.loadExtension({
    316    manifest: {
    317      chrome_settings_overrides: {
    318        search_provider: {
    319          name: "MozSearch",
    320          keyword: "MozSearch",
    321          search_url: "https://example.com/{searchTerms}",
    322          suggest_url: "https://example.com/suggest/{searchTerms}",
    323        },
    324      },
    325    },
    326    useAddonManager: "temporary",
    327  });
    328 
    329  await ext1.startup();
    330  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    331 
    332  let engine = Services.search.getEngineByName("MozSearch");
    333  ok(engine, "Engine should exist.");
    334 
    335  const encodedSubmissionURL = engine.getSubmission(kSearchTermIntl).uri.spec;
    336  const testSubmissionURL =
    337    "https://example.com/" + encodeURIComponent(kSearchTermIntl);
    338  equal(
    339    encodedSubmissionURL,
    340    testSubmissionURL,
    341    "Encoded UTF-8 URLs should match"
    342  );
    343 
    344  const expectedSuggestURL = "https://example.com/suggest/" + kSearchTerm;
    345  let submissionSuggest = engine.getSubmission(
    346    kSearchTerm,
    347    URLTYPE_SUGGEST_JSON
    348  );
    349  equal(
    350    submissionSuggest.uri.spec,
    351    expectedSuggestURL,
    352    "Suggest URLs should match"
    353  );
    354 
    355  await ext1.unload();
    356  await delay();
    357 
    358  engine = Services.search.getEngineByName("MozSearch");
    359  ok(!engine, "Engine should not exist");
    360 });
    361 
    362 add_task(async function test_extension_empty_suggestUrl() {
    363  let ext1 = ExtensionTestUtils.loadExtension({
    364    manifest: {
    365      default_locale: "en",
    366      chrome_settings_overrides: {
    367        search_provider: {
    368          name: "MozSearch",
    369          keyword: "MozSearch",
    370          search_url: kSearchEngineURL,
    371          search_url_post_params: "foo=bar&bar=foo",
    372          suggest_url: "__MSG_suggestUrl__",
    373          suggest_url_get_params: "__MSG_suggestUrlGetParams__",
    374        },
    375      },
    376    },
    377    useAddonManager: "temporary",
    378    files: {
    379      "_locales/en/messages.json": {
    380        suggestUrl: {
    381          message: "",
    382        },
    383        suggestUrlGetParams: {
    384          message: "",
    385        },
    386      },
    387    },
    388  });
    389 
    390  await ext1.startup();
    391  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    392 
    393  let engine = Services.search.getEngineByName("MozSearch");
    394  ok(engine, "Engine should exist.");
    395 
    396  let url = engine.wrappedJSObject.getURLOfType("text/html");
    397  equal(url.method, "POST", "Search URLs method is POST");
    398 
    399  let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
    400  let submission = engine.getSubmission(kSearchTerm);
    401  equal(submission.uri.spec, expectedURL, "Search URLs should match");
    402  // postData is a nsIMIMEInputStream which contains a nsIStringInputStream.
    403  equal(
    404    submission.postData.data.data,
    405    "foo=bar&bar=foo",
    406    "Search postData should match"
    407  );
    408 
    409  let submissionSuggest = engine.getSubmission(
    410    kSearchTerm,
    411    URLTYPE_SUGGEST_JSON
    412  );
    413  ok(!submissionSuggest, "There should be no suggest URL.");
    414 
    415  await ext1.unload();
    416 });
    417 
    418 add_task(async function test_extension_empty_suggestUrl_with_params() {
    419  let ext1 = ExtensionTestUtils.loadExtension({
    420    manifest: {
    421      default_locale: "en",
    422      chrome_settings_overrides: {
    423        search_provider: {
    424          name: "MozSearch",
    425          keyword: "MozSearch",
    426          search_url: kSearchEngineURL,
    427          search_url_post_params: "foo=bar&bar=foo",
    428          suggest_url: "__MSG_suggestUrl__",
    429          suggest_url_get_params: "__MSG_suggestUrlGetParams__",
    430        },
    431      },
    432    },
    433    useAddonManager: "temporary",
    434    files: {
    435      "_locales/en/messages.json": {
    436        suggestUrl: {
    437          message: "",
    438        },
    439        suggestUrlGetParams: {
    440          message: "abc",
    441        },
    442      },
    443    },
    444  });
    445 
    446  await ext1.startup();
    447  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    448 
    449  let engine = Services.search.getEngineByName("MozSearch");
    450  ok(engine, "Engine should exist.");
    451 
    452  let url = engine.wrappedJSObject.getURLOfType("text/html");
    453  equal(url.method, "POST", "Search URLs method is POST");
    454 
    455  let expectedURL = kSearchEngineURL.replace("{searchTerms}", kSearchTerm);
    456  let submission = engine.getSubmission(kSearchTerm);
    457  equal(submission.uri.spec, expectedURL, "Search URLs should match");
    458  // postData is a nsIMIMEInputStream which contains a nsIStringInputStream.
    459  equal(
    460    submission.postData.data.data,
    461    "foo=bar&bar=foo",
    462    "Search postData should match"
    463  );
    464 
    465  let submissionSuggest = engine.getSubmission(
    466    kSearchTerm,
    467    URLTYPE_SUGGEST_JSON
    468  );
    469  ok(!submissionSuggest, "There should be no suggest URL.");
    470 
    471  await ext1.unload();
    472 });
    473 
    474 async function checkBadUrl(searchProviderKey, urlValue) {
    475  let normalized = await ExtensionTestUtils.normalizeManifest({
    476    chrome_settings_overrides: {
    477      search_provider: {
    478        name: "MozSearch",
    479        keyword: "MozSearch",
    480        search_url: "https://example.com/",
    481        [searchProviderKey]: urlValue,
    482      },
    483    },
    484  });
    485 
    486  ok(
    487    /Error processing chrome_settings_overrides\.search_provider[^:]*: .* must match/.test(
    488      normalized.error
    489    ),
    490    `Expected error for ${searchProviderKey}:${urlValue} "${normalized.error}"`
    491  );
    492 }
    493 
    494 async function checkValidUrl(urlValue) {
    495  let normalized = await ExtensionTestUtils.normalizeManifest({
    496    chrome_settings_overrides: {
    497      search_provider: {
    498        name: "MozSearch",
    499        keyword: "MozSearch",
    500        search_url: urlValue,
    501        suggest_url: urlValue,
    502      },
    503    },
    504  });
    505  equal(normalized.error, undefined, `Valid search_provider url: ${urlValue}`);
    506 }
    507 
    508 add_task(async function test_extension_not_allow_http() {
    509  await checkBadUrl("search_url", "http://example.com/{searchTerms}");
    510  await checkBadUrl("suggest_url", "http://example.com/{searchTerms}");
    511 });
    512 
    513 add_task(async function test_manifest_disallows_http_localhost_prefix() {
    514  await checkBadUrl("search_url", "http://localhost.example.com");
    515  await checkBadUrl("search_url", "http://localhost.example.com/");
    516  await checkBadUrl("search_url", "http://127.0.0.1.example.com/");
    517  await checkBadUrl("search_url", "http://localhost:1234@example.com/");
    518 });
    519 
    520 add_task(async function test_manifest_allow_http_for_localhost() {
    521  await checkValidUrl("http://localhost");
    522  await checkValidUrl("http://localhost/");
    523  await checkValidUrl("http://localhost:/");
    524  await checkValidUrl("http://localhost:1/");
    525  await checkValidUrl("http://localhost:65535/");
    526 
    527  await checkValidUrl("http://127.0.0.1");
    528  await checkValidUrl("http://127.0.0.1:");
    529  await checkValidUrl("http://127.0.0.1:/");
    530  await checkValidUrl("http://127.0.0.1/");
    531  await checkValidUrl("http://127.0.0.1:80/");
    532 
    533  await checkValidUrl("http://[::1]");
    534  await checkValidUrl("http://[::1]:");
    535  await checkValidUrl("http://[::1]:/");
    536  await checkValidUrl("http://[::1]/");
    537  await checkValidUrl("http://[::1]:80/");
    538 });
    539 
    540 add_task(async function test_extension_allow_http_for_localhost() {
    541  let ext1 = ExtensionTestUtils.loadExtension({
    542    manifest: {
    543      chrome_settings_overrides: {
    544        search_provider: {
    545          name: "MozSearch",
    546          keyword: "MozSearch",
    547          search_url: "http://localhost/{searchTerms}",
    548          suggest_url: "http://localhost/suggest/{searchTerms}",
    549        },
    550      },
    551    },
    552    useAddonManager: "temporary",
    553  });
    554 
    555  await ext1.startup();
    556  await AddonTestUtils.waitForSearchProviderStartup(ext1);
    557 
    558  let engine = Services.search.getEngineByName("MozSearch");
    559  ok(engine, "Engine should exist.");
    560 
    561  await ext1.unload();
    562 });
    563 
    564 add_task(async function test_search_favicon_mv3() {
    565  let normalized = await ExtensionTestUtils.normalizeManifest({
    566    manifest_version: 3,
    567    chrome_settings_overrides: {
    568      search_provider: {
    569        name: "HTTP Icon in MV3",
    570        search_url: "https://example.org/",
    571        favicon_url: "https://example.org/icon.png",
    572      },
    573    },
    574  });
    575  Assert.ok(
    576    normalized.error.endsWith("must be a relative URL"),
    577    "Should have an error"
    578  );
    579  normalized = await ExtensionTestUtils.normalizeManifest({
    580    manifest_version: 3,
    581    chrome_settings_overrides: {
    582      search_provider: {
    583        name: "HTTP Icon in MV3",
    584        search_url: "https://example.org/",
    585        favicon_url: "/icon.png",
    586      },
    587    },
    588  });
    589  Assert.ok(!normalized.error, "Should not have an error");
    590 });