summaryrefslogtreecommitdiffstats
path: root/toolkit/components/search/tests/xpcshell/test_parseSubmissionURL.js
blob: bee90dbb5b3a52253c66c36f6176e0e35b211b21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* Any copyright is dedicated to the Public Domain.
 *    https://creativecommons.org/publicdomain/zero/1.0/ */

/*
 * Tests getAlternateDomains API.
 */

"use strict";

add_task(async function setup() {
  useHttpServer();
  await AddonTestUtils.promiseStartupManager();
});

add_task(async function test_parseSubmissionURL() {
  let engine1 = await SearchTestUtils.promiseNewSearchEngine({
    url: `${gDataUrl}engine.xml`,
  });
  let engine2 = await SearchTestUtils.promiseNewSearchEngine({
    url: `${gDataUrl}engine-fr.xml`,
  });

  await SearchTestUtils.installSearchExtension({
    name: "bacon_addParam",
    keyword: "bacon_addParam",
    encoding: "windows-1252",
    search_url: "https://www.bacon.test/find",
  });
  await SearchTestUtils.installSearchExtension({
    name: "idn_addParam",
    keyword: "idn_addParam",
    search_url: "https://www.xn--bcher-kva.ch/search",
  });
  let engine3 = Services.search.getEngineByName("bacon_addParam");
  let engine4 = Services.search.getEngineByName("idn_addParam");

  // The following engine provides it's query keyword in
  // its template in the form of q={searchTerms}
  let engine5 = await SearchTestUtils.promiseNewSearchEngine({
    url: `${gDataUrl}engine2.xml`,
  });

  // The following engines cannot identify the search parameter.
  await SearchTestUtils.installSearchExtension({
    name: "bacon",
    keyword: "bacon",
    search_url: "https://www.bacon.moz/search?q=",
    search_url_get_params: "",
  });

  await Services.search.setDefault(
    engine1,
    Ci.nsISearchService.CHANGE_REASON_UNKNOWN
  );

  // Hide the default engines to prevent them from being used in the search.
  for (let engine of await Services.search.getAppProvidedEngines()) {
    await Services.search.removeEngine(engine);
  }

  // Test the first engine, whose URLs use UTF-8 encoding.
  // This also tests the query parameter in a different position not being the
  // first parameter.
  let url = "https://www.google.com/search?foo=bar&q=caff%C3%A8";
  let result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, "caff\u00E8");

  // The second engine uses a locale-specific domain that is an alternate domain
  // of the first one, but the second engine should get priority when matching.
  // The URL used with this engine uses ISO-8859-1 encoding instead.
  url = "https://www.google.fr/search?q=caff%E8";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine2);
  Assert.equal(result.terms, "caff\u00E8");

  // Test a domain that is an alternate domain of those defined.  In this case,
  // the first matching engine from the ordered list should be returned.
  url = "https://www.google.co.uk/search?q=caff%C3%A8";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, "caff\u00E8");

  // We support parsing URLs from a dynamically added engine.
  url = "https://www.bacon.test/find?q=caff%E8";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine, engine3);
  Assert.equal(result.terms, "caff\u00E8");

  // Test URLs with unescaped unicode characters.
  url = "https://www.google.com/search?q=foo+b\u00E4r";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, "foo b\u00E4r");

  // Test search engines with unescaped IDNs.
  url = "https://www.b\u00FCcher.ch/search?q=foo+bar";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine, engine4);
  Assert.equal(result.terms, "foo bar");

  // Test search engines with escaped IDNs.
  url = "https://www.xn--bcher-kva.ch/search?q=foo+bar";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine, engine4);
  Assert.equal(result.terms, "foo bar");

  // Parsing of parameters from an engine template URL is not supported
  // if no matching parameter value template is provided.
  Assert.equal(
    Services.search.parseSubmissionURL("https://www.bacon.moz/search?q=")
      .engine,
    null
  );

  // Parsing of parameters from an engine template URL is supported
  // if a matching parameter value template is provided.
  url = "https://duckduckgo.com/?foo=bar&q=caff%C3%A8";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine5);
  Assert.equal(result.terms, "caff\u00E8");

  // If the search params are in the template, the query parameter
  // doesn't need to be separated from the host by a slash, only by
  // by a question mark.
  url = "https://duckduckgo.com?foo=bar&q=caff%C3%A8";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine5);
  Assert.equal(result.terms, "caff\u00E8");

  // HTTP and HTTPS schemes are interchangeable.
  url = "https://www.google.com/search?q=caff%C3%A8";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, "caff\u00E8");

  // Decoding search terms with multiple spaces should work.
  result = Services.search.parseSubmissionURL(
    "https://www.google.com/search?q=+with++spaces+"
  );
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, " with  spaces ");

  // Parsing search terms with ampersands should work.
  result = Services.search.parseSubmissionURL(
    "https://www.google.com/search?q=with%26ampersand"
  );
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, "with&ampersand");

  // Capitals in the path should work
  result = Services.search.parseSubmissionURL(
    "https://www.google.com/SEARCH?q=caps"
  );
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, "caps");

  // An empty query parameter should work the same.
  url = "https://www.google.com/search?q=";
  result = Services.search.parseSubmissionURL(url);
  Assert.equal(result.engine.wrappedJSObject, engine1);
  Assert.equal(result.terms, "");

  // There should be no match when the path is different.
  result = Services.search.parseSubmissionURL(
    "https://www.google.com/search/?q=test"
  );
  Assert.equal(result.engine, null);
  Assert.equal(result.terms, "");

  // There should be no match when the argument is different.
  result = Services.search.parseSubmissionURL(
    "https://www.google.com/search?q2=test"
  );
  Assert.equal(result.engine, null);
  Assert.equal(result.terms, "");

  // There should be no match for URIs that are not HTTP or HTTPS.
  result = Services.search.parseSubmissionURL("file://localhost/search?q=test");
  Assert.equal(result.engine, null);
  Assert.equal(result.terms, "");
});