- add sources.
[platform/framework/web/crosswalk.git] / src / extensions / common / url_pattern_unittest.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/memory/scoped_ptr.h"
6 #include "extensions/common/url_pattern.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "url/gurl.h"
9
10 namespace {
11
12 // See url_pattern.h for examples of valid and invalid patterns.
13
14 static const int kAllSchemes =
15     URLPattern::SCHEME_HTTP |
16     URLPattern::SCHEME_HTTPS |
17     URLPattern::SCHEME_FILE |
18     URLPattern::SCHEME_FTP |
19     URLPattern::SCHEME_CHROMEUI |
20     URLPattern::SCHEME_EXTENSION |
21     URLPattern::SCHEME_FILESYSTEM;
22
23 TEST(ExtensionURLPatternTest, ParseInvalid) {
24   const struct {
25     const char* pattern;
26     URLPattern::ParseResult expected_result;
27   } kInvalidPatterns[] = {
28     { "http", URLPattern::PARSE_ERROR_MISSING_SCHEME_SEPARATOR },
29     { "http:", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
30     { "http:/", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
31     { "about://", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
32     { "http://", URLPattern::PARSE_ERROR_EMPTY_HOST },
33     { "http:///", URLPattern::PARSE_ERROR_EMPTY_HOST },
34     { "http://*foo/bar", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
35     { "http://foo.*.bar/baz", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
36     { "http://fo.*.ba:123/baz", URLPattern::PARSE_ERROR_INVALID_HOST_WILDCARD },
37     { "http:/bar", URLPattern::PARSE_ERROR_WRONG_SCHEME_SEPARATOR },
38     { "http://bar", URLPattern::PARSE_ERROR_EMPTY_PATH },
39   };
40
41   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kInvalidPatterns); ++i) {
42     URLPattern pattern(URLPattern::SCHEME_ALL);
43     EXPECT_EQ(kInvalidPatterns[i].expected_result,
44               pattern.Parse(kInvalidPatterns[i].pattern))
45         << kInvalidPatterns[i].pattern;
46   }
47 };
48
49 TEST(ExtensionURLPatternTest, Ports) {
50   const struct {
51     const char* pattern;
52     URLPattern::ParseResult expected_result;
53     const char* expected_port;
54   } kTestPatterns[] = {
55     { "http://foo:1234/", URLPattern::PARSE_SUCCESS, "1234" },
56     { "http://foo:1234/bar", URLPattern::PARSE_SUCCESS, "1234" },
57     { "http://*.foo:1234/", URLPattern::PARSE_SUCCESS, "1234" },
58     { "http://*.foo:1234/bar", URLPattern::PARSE_SUCCESS,"1234" },
59     { "http://:1234/", URLPattern::PARSE_SUCCESS, "1234" },
60     { "http://foo:/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" },
61     { "http://foo:*/", URLPattern::PARSE_SUCCESS, "*" },
62     { "http://*.foo:/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" },
63     { "http://foo:com/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" },
64     { "http://foo:123456/", URLPattern::PARSE_ERROR_INVALID_PORT, "*" },
65     { "http://foo:80:80/monkey", URLPattern::PARSE_ERROR_INVALID_PORT, "*" },
66     { "file://foo:1234/bar", URLPattern::PARSE_SUCCESS, "*" },
67     { "chrome://foo:1234/bar", URLPattern::PARSE_ERROR_INVALID_PORT, "*" },
68
69     // Port-like strings in the path should not trigger a warning.
70     { "http://*/:1234", URLPattern::PARSE_SUCCESS, "*" },
71     { "http://*.foo/bar:1234", URLPattern::PARSE_SUCCESS, "*" },
72     { "http://foo/bar:1234/path", URLPattern::PARSE_SUCCESS,"*" },
73   };
74
75   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestPatterns); ++i) {
76     URLPattern pattern(URLPattern::SCHEME_ALL);
77     EXPECT_EQ(kTestPatterns[i].expected_result,
78               pattern.Parse(kTestPatterns[i].pattern))
79         << "Got unexpected result for URL pattern: "
80         << kTestPatterns[i].pattern;
81     EXPECT_EQ(kTestPatterns[i].expected_port, pattern.port())
82         << "Got unexpected port for URL pattern: " << kTestPatterns[i].pattern;
83   }
84 };
85
86 // all pages for a given scheme
87 TEST(ExtensionURLPatternTest, Match1) {
88   URLPattern pattern(kAllSchemes);
89   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*/*"));
90   EXPECT_EQ("http", pattern.scheme());
91   EXPECT_EQ("", pattern.host());
92   EXPECT_TRUE(pattern.match_subdomains());
93   EXPECT_FALSE(pattern.match_all_urls());
94   EXPECT_EQ("/*", pattern.path());
95   EXPECT_TRUE(pattern.MatchesURL(GURL("http://google.com")));
96   EXPECT_TRUE(pattern.MatchesURL(GURL("http://yahoo.com")));
97   EXPECT_TRUE(pattern.MatchesURL(GURL("http://google.com/foo")));
98   EXPECT_FALSE(pattern.MatchesURL(GURL("https://google.com")));
99   EXPECT_TRUE(pattern.MatchesURL(GURL("http://74.125.127.100/search")));
100 }
101
102 // all domains
103 TEST(ExtensionURLPatternTest, Match2) {
104   URLPattern pattern(kAllSchemes);
105   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("https://*/foo*"));
106   EXPECT_EQ("https", pattern.scheme());
107   EXPECT_EQ("", pattern.host());
108   EXPECT_TRUE(pattern.match_subdomains());
109   EXPECT_FALSE(pattern.match_all_urls());
110   EXPECT_EQ("/foo*", pattern.path());
111   EXPECT_TRUE(pattern.MatchesURL(GURL("https://www.google.com/foo")));
112   EXPECT_TRUE(pattern.MatchesURL(GURL("https://www.google.com/foobar")));
113   EXPECT_FALSE(pattern.MatchesURL(GURL("http://www.google.com/foo")));
114   EXPECT_FALSE(pattern.MatchesURL(GURL("https://www.google.com/")));
115   EXPECT_TRUE(pattern.MatchesURL(
116       GURL("filesystem:https://www.google.com/foobar/")));
117 }
118
119 // subdomains
120 TEST(URLPatternTest, Match3) {
121   URLPattern pattern(kAllSchemes);
122   EXPECT_EQ(URLPattern::PARSE_SUCCESS,
123             pattern.Parse("http://*.google.com/foo*bar"));
124   EXPECT_EQ("http", pattern.scheme());
125   EXPECT_EQ("google.com", pattern.host());
126   EXPECT_TRUE(pattern.match_subdomains());
127   EXPECT_FALSE(pattern.match_all_urls());
128   EXPECT_EQ("/foo*bar", pattern.path());
129   EXPECT_TRUE(pattern.MatchesURL(GURL("http://google.com/foobar")));
130   EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.google.com/foo?bar")));
131   EXPECT_TRUE(pattern.MatchesURL(
132       GURL("http://monkey.images.google.com/foooobar")));
133   EXPECT_FALSE(pattern.MatchesURL(GURL("http://yahoo.com/foobar")));
134   EXPECT_TRUE(pattern.MatchesURL(
135       GURL("filesystem:http://google.com/foo/bar")));
136   EXPECT_FALSE(pattern.MatchesURL(
137       GURL("filesystem:http://google.com/temporary/foobar")));
138 }
139
140 // glob escaping
141 TEST(ExtensionURLPatternTest, Match5) {
142   URLPattern pattern(kAllSchemes);
143   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file:///foo?bar\\*baz"));
144   EXPECT_EQ("file", pattern.scheme());
145   EXPECT_EQ("", pattern.host());
146   EXPECT_FALSE(pattern.match_subdomains());
147   EXPECT_FALSE(pattern.match_all_urls());
148   EXPECT_EQ("/foo?bar\\*baz", pattern.path());
149   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo?bar\\hellobaz")));
150   EXPECT_FALSE(pattern.MatchesURL(GURL("file:///fooXbar\\hellobaz")));
151 }
152
153 // ip addresses
154 TEST(ExtensionURLPatternTest, Match6) {
155   URLPattern pattern(kAllSchemes);
156   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://127.0.0.1/*"));
157   EXPECT_EQ("http", pattern.scheme());
158   EXPECT_EQ("127.0.0.1", pattern.host());
159   EXPECT_FALSE(pattern.match_subdomains());
160   EXPECT_FALSE(pattern.match_all_urls());
161   EXPECT_EQ("/*", pattern.path());
162   EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1")));
163 }
164
165 // subdomain matching with ip addresses
166 TEST(ExtensionURLPatternTest, Match7) {
167   URLPattern pattern(kAllSchemes);
168   // allowed, but useless
169   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("http://*.0.0.1/*"));
170   EXPECT_EQ("http", pattern.scheme());
171   EXPECT_EQ("0.0.1", pattern.host());
172   EXPECT_TRUE(pattern.match_subdomains());
173   EXPECT_FALSE(pattern.match_all_urls());
174   EXPECT_EQ("/*", pattern.path());
175   // Subdomain matching is never done if the argument has an IP address host.
176   EXPECT_FALSE(pattern.MatchesURL(GURL("http://127.0.0.1")));
177 };
178
179 // unicode
180 TEST(ExtensionURLPatternTest, Match8) {
181   URLPattern pattern(kAllSchemes);
182   // The below is the ASCII encoding of the following URL:
183   // http://*.\xe1\x80\xbf/a\xc2\x81\xe1*
184   EXPECT_EQ(URLPattern::PARSE_SUCCESS,
185             pattern.Parse("http://*.xn--gkd/a%C2%81%E1*"));
186   EXPECT_EQ("http", pattern.scheme());
187   EXPECT_EQ("xn--gkd", pattern.host());
188   EXPECT_TRUE(pattern.match_subdomains());
189   EXPECT_FALSE(pattern.match_all_urls());
190   EXPECT_EQ("/a%C2%81%E1*", pattern.path());
191   EXPECT_TRUE(pattern.MatchesURL(
192       GURL("http://abc.\xe1\x80\xbf/a\xc2\x81\xe1xyz")));
193   EXPECT_TRUE(pattern.MatchesURL(
194       GURL("http://\xe1\x80\xbf/a\xc2\x81\xe1\xe1")));
195 };
196
197 // chrome://
198 TEST(ExtensionURLPatternTest, Match9) {
199   URLPattern pattern(kAllSchemes);
200   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("chrome://favicon/*"));
201   EXPECT_EQ("chrome", pattern.scheme());
202   EXPECT_EQ("favicon", pattern.host());
203   EXPECT_FALSE(pattern.match_subdomains());
204   EXPECT_FALSE(pattern.match_all_urls());
205   EXPECT_EQ("/*", pattern.path());
206   EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com")));
207   EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/https://google.com")));
208   EXPECT_FALSE(pattern.MatchesURL(GURL("chrome://history")));
209 };
210
211 // *://
212 TEST(ExtensionURLPatternTest, Match10) {
213   URLPattern pattern(kAllSchemes);
214   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("*://*/*"));
215   EXPECT_TRUE(pattern.MatchesScheme("http"));
216   EXPECT_TRUE(pattern.MatchesScheme("https"));
217   EXPECT_FALSE(pattern.MatchesScheme("chrome"));
218   EXPECT_FALSE(pattern.MatchesScheme("file"));
219   EXPECT_FALSE(pattern.MatchesScheme("ftp"));
220   EXPECT_TRUE(pattern.match_subdomains());
221   EXPECT_FALSE(pattern.match_all_urls());
222   EXPECT_EQ("/*", pattern.path());
223   EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1")));
224   EXPECT_FALSE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com")));
225   EXPECT_FALSE(pattern.MatchesURL(GURL("file:///foo/bar")));
226   EXPECT_FALSE(pattern.MatchesURL(GURL("file://localhost/foo/bar")));
227 };
228
229 // <all_urls>
230 TEST(ExtensionURLPatternTest, Match11) {
231   URLPattern pattern(kAllSchemes);
232   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>"));
233   EXPECT_TRUE(pattern.MatchesScheme("chrome"));
234   EXPECT_TRUE(pattern.MatchesScheme("http"));
235   EXPECT_TRUE(pattern.MatchesScheme("https"));
236   EXPECT_TRUE(pattern.MatchesScheme("file"));
237   EXPECT_TRUE(pattern.MatchesScheme("filesystem"));
238   EXPECT_TRUE(pattern.MatchesScheme("chrome-extension"));
239   EXPECT_TRUE(pattern.match_subdomains());
240   EXPECT_TRUE(pattern.match_all_urls());
241   EXPECT_EQ("/*", pattern.path());
242   EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com")));
243   EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1")));
244   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo/bar")));
245   EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo/bar")));
246
247   // Make sure the properties are the same when creating an <all_urls> pattern
248   // via SetMatchAllURLs and by parsing <all_urls>.
249   URLPattern pattern2(kAllSchemes);
250   pattern2.SetMatchAllURLs(true);
251
252   EXPECT_EQ(pattern.valid_schemes(), pattern2.valid_schemes());
253   EXPECT_EQ(pattern.match_subdomains(), pattern2.match_subdomains());
254   EXPECT_EQ(pattern.path(), pattern2.path());
255   EXPECT_EQ(pattern.match_all_urls(), pattern2.match_all_urls());
256   EXPECT_EQ(pattern.scheme(), pattern2.scheme());
257   EXPECT_EQ(pattern.port(), pattern2.port());
258   EXPECT_EQ(pattern.GetAsString(), pattern2.GetAsString());
259 };
260
261 // SCHEME_ALL matches all schemes.
262 TEST(ExtensionURLPatternTest, Match12) {
263   URLPattern pattern(URLPattern::SCHEME_ALL);
264   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("<all_urls>"));
265   EXPECT_TRUE(pattern.MatchesScheme("chrome"));
266   EXPECT_TRUE(pattern.MatchesScheme("http"));
267   EXPECT_TRUE(pattern.MatchesScheme("https"));
268   EXPECT_TRUE(pattern.MatchesScheme("file"));
269   EXPECT_TRUE(pattern.MatchesScheme("filesystem"));
270   EXPECT_TRUE(pattern.MatchesScheme("javascript"));
271   EXPECT_TRUE(pattern.MatchesScheme("data"));
272   EXPECT_TRUE(pattern.MatchesScheme("about"));
273   EXPECT_TRUE(pattern.MatchesScheme("chrome-extension"));
274   EXPECT_TRUE(pattern.match_subdomains());
275   EXPECT_TRUE(pattern.match_all_urls());
276   EXPECT_EQ("/*", pattern.path());
277   EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://favicon/http://google.com")));
278   EXPECT_TRUE(pattern.MatchesURL(GURL("http://127.0.0.1")));
279   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo/bar")));
280   EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo/bar")));
281   EXPECT_TRUE(pattern.MatchesURL(GURL("chrome://newtab")));
282   EXPECT_TRUE(pattern.MatchesURL(GURL("about:blank")));
283   EXPECT_TRUE(pattern.MatchesURL(GURL("about:version")));
284   EXPECT_TRUE(pattern.MatchesURL(
285       GURL("data:text/html;charset=utf-8,<html>asdf</html>")));
286 };
287
288 static const struct MatchPatterns {
289   const char* pattern;
290   const char* matches;
291 } kMatch13UrlPatternTestCases[] = {
292   {"about:*", "about:blank"},
293   {"about:blank", "about:blank"},
294   {"about:*", "about:version"},
295   {"chrome-extension://*/*", "chrome-extension://FTW"},
296   {"data:*", "data:monkey"},
297   {"javascript:*", "javascript:atemyhomework"},
298 };
299
300 // SCHEME_ALL and specific schemes.
301 TEST(ExtensionURLPatternTest, Match13) {
302   for (size_t i = 0; i < arraysize(kMatch13UrlPatternTestCases); ++i) {
303     URLPattern pattern(URLPattern::SCHEME_ALL);
304     EXPECT_EQ(URLPattern::PARSE_SUCCESS,
305               pattern.Parse(kMatch13UrlPatternTestCases[i].pattern))
306         << " while parsing " << kMatch13UrlPatternTestCases[i].pattern;
307     EXPECT_TRUE(pattern.MatchesURL(
308         GURL(kMatch13UrlPatternTestCases[i].matches)))
309         << " while matching " << kMatch13UrlPatternTestCases[i].matches;
310   }
311
312   // Negative test.
313   URLPattern pattern(URLPattern::SCHEME_ALL);
314   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("data:*"));
315   EXPECT_FALSE(pattern.MatchesURL(GURL("about:blank")));
316 };
317
318 // file scheme with empty hostname
319 TEST(ExtensionURLPatternTest, Match14) {
320   URLPattern pattern(kAllSchemes);
321   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file:///foo*"));
322   EXPECT_EQ("file", pattern.scheme());
323   EXPECT_EQ("", pattern.host());
324   EXPECT_FALSE(pattern.match_subdomains());
325   EXPECT_FALSE(pattern.match_all_urls());
326   EXPECT_EQ("/foo*", pattern.path());
327   EXPECT_FALSE(pattern.MatchesURL(GURL("file://foo")));
328   EXPECT_FALSE(pattern.MatchesURL(GURL("file://foobar")));
329   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo")));
330   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foobar")));
331   EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo")));
332 }
333
334 // file scheme without hostname part
335 TEST(ExtensionURLPatternTest, Match15) {
336   URLPattern pattern(kAllSchemes);
337   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file://foo*"));
338   EXPECT_EQ("file", pattern.scheme());
339   EXPECT_EQ("", pattern.host());
340   EXPECT_FALSE(pattern.match_subdomains());
341   EXPECT_FALSE(pattern.match_all_urls());
342   EXPECT_EQ("/foo*", pattern.path());
343   EXPECT_FALSE(pattern.MatchesURL(GURL("file://foo")));
344   EXPECT_FALSE(pattern.MatchesURL(GURL("file://foobar")));
345   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo")));
346   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foobar")));
347   EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo")));
348 }
349
350 // file scheme with hostname
351 TEST(ExtensionURLPatternTest, Match16) {
352   URLPattern pattern(kAllSchemes);
353   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse("file://localhost/foo*"));
354   EXPECT_EQ("file", pattern.scheme());
355   // Since hostname is ignored for file://.
356   EXPECT_EQ("", pattern.host());
357   EXPECT_FALSE(pattern.match_subdomains());
358   EXPECT_FALSE(pattern.match_all_urls());
359   EXPECT_EQ("/foo*", pattern.path());
360   EXPECT_FALSE(pattern.MatchesURL(GURL("file://foo")));
361   EXPECT_FALSE(pattern.MatchesURL(GURL("file://foobar")));
362   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foo")));
363   EXPECT_TRUE(pattern.MatchesURL(GURL("file:///foobar")));
364   EXPECT_TRUE(pattern.MatchesURL(GURL("file://localhost/foo")));
365 }
366
367 // Specific port
368 TEST(ExtensionURLPatternTest, Match17) {
369   URLPattern pattern(kAllSchemes);
370   EXPECT_EQ(URLPattern::PARSE_SUCCESS,
371             pattern.Parse("http://www.example.com:80/foo"));
372   EXPECT_EQ("http", pattern.scheme());
373   EXPECT_EQ("www.example.com", pattern.host());
374   EXPECT_FALSE(pattern.match_subdomains());
375   EXPECT_FALSE(pattern.match_all_urls());
376   EXPECT_EQ("/foo", pattern.path());
377   EXPECT_EQ("80", pattern.port());
378   EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:80/foo")));
379   EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com/foo")));
380   EXPECT_FALSE(pattern.MatchesURL(GURL("http://www.example.com:8080/foo")));
381   EXPECT_FALSE(pattern.MatchesURL(
382       GURL("filesystem:http://www.example.com:8080/foo/")));
383   EXPECT_FALSE(pattern.MatchesURL(GURL("filesystem:http://www.example.com/f/foo")));
384 }
385
386 // Explicit port wildcard
387 TEST(ExtensionURLPatternTest, Match18) {
388   URLPattern pattern(kAllSchemes);
389   EXPECT_EQ(URLPattern::PARSE_SUCCESS,
390             pattern.Parse("http://www.example.com:*/foo"));
391   EXPECT_EQ("http", pattern.scheme());
392   EXPECT_EQ("www.example.com", pattern.host());
393   EXPECT_FALSE(pattern.match_subdomains());
394   EXPECT_FALSE(pattern.match_all_urls());
395   EXPECT_EQ("/foo", pattern.path());
396   EXPECT_EQ("*", pattern.port());
397   EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:80/foo")));
398   EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com/foo")));
399   EXPECT_TRUE(pattern.MatchesURL(GURL("http://www.example.com:8080/foo")));
400   EXPECT_FALSE(pattern.MatchesURL(
401       GURL("filesystem:http://www.example.com:8080/foo/")));
402 }
403
404 // chrome-extension://
405 TEST(ExtensionURLPatternTest, Match19) {
406   URLPattern pattern(URLPattern::SCHEME_EXTENSION);
407   EXPECT_EQ(URLPattern::PARSE_SUCCESS,
408             pattern.Parse("chrome-extension://ftw/*"));
409   EXPECT_EQ("chrome-extension", pattern.scheme());
410   EXPECT_EQ("ftw", pattern.host());
411   EXPECT_FALSE(pattern.match_subdomains());
412   EXPECT_FALSE(pattern.match_all_urls());
413   EXPECT_EQ("/*", pattern.path());
414   EXPECT_TRUE(pattern.MatchesURL(GURL("chrome-extension://ftw")));
415   EXPECT_TRUE(pattern.MatchesURL(
416       GURL("chrome-extension://ftw/http://google.com")));
417   EXPECT_TRUE(pattern.MatchesURL(
418       GURL("chrome-extension://ftw/https://google.com")));
419   EXPECT_FALSE(pattern.MatchesURL(GURL("chrome-extension://foobar")));
420   EXPECT_TRUE(pattern.MatchesURL(
421       GURL("filesystem:chrome-extension://ftw/t/file.txt")));
422 };
423
424 static const struct GetAsStringPatterns {
425   const char* pattern;
426 } kGetAsStringTestCases[] = {
427   { "http://www/" },
428   { "http://*/*" },
429   { "chrome://*/*" },
430   { "chrome://newtab/" },
431   { "about:*" },
432   { "about:blank" },
433   { "chrome-extension://*/*" },
434   { "chrome-extension://FTW/" },
435   { "data:*" },
436   { "data:monkey" },
437   { "javascript:*" },
438   { "javascript:atemyhomework" },
439   { "http://www.example.com:8080/foo" },
440 };
441
442 TEST(ExtensionURLPatternTest, GetAsString) {
443   for (size_t i = 0; i < arraysize(kGetAsStringTestCases); ++i) {
444     URLPattern pattern(URLPattern::SCHEME_ALL);
445     EXPECT_EQ(URLPattern::PARSE_SUCCESS,
446               pattern.Parse(kGetAsStringTestCases[i].pattern))
447         << "Error parsing " << kGetAsStringTestCases[i].pattern;
448     EXPECT_EQ(kGetAsStringTestCases[i].pattern,
449               pattern.GetAsString());
450   }
451 }
452
453 testing::AssertionResult Overlaps(const URLPattern& pattern1,
454                                   const URLPattern& pattern2) {
455   if (!pattern1.OverlapsWith(pattern2)) {
456     return testing::AssertionFailure()
457         << pattern1.GetAsString() << " does not overlap " <<
458                                      pattern2.GetAsString();
459   }
460   if (!pattern2.OverlapsWith(pattern1)) {
461     return testing::AssertionFailure()
462         << pattern2.GetAsString() << " does not overlap " <<
463                                      pattern1.GetAsString();
464   }
465   return testing::AssertionSuccess()
466       << pattern1.GetAsString() << " overlaps with " << pattern2.GetAsString();
467 }
468
469 TEST(ExtensionURLPatternTest, Overlaps) {
470   URLPattern pattern1(kAllSchemes, "http://www.google.com/foo/*");
471   URLPattern pattern2(kAllSchemes, "https://www.google.com/foo/*");
472   URLPattern pattern3(kAllSchemes, "http://*.google.com/foo/*");
473   URLPattern pattern4(kAllSchemes, "http://*.yahooo.com/foo/*");
474   URLPattern pattern5(kAllSchemes, "http://www.yahooo.com/bar/*");
475   URLPattern pattern6(kAllSchemes,
476                       "http://www.yahooo.com/bar/baz/*");
477   URLPattern pattern7(kAllSchemes, "file:///*");
478   URLPattern pattern8(kAllSchemes, "*://*/*");
479   URLPattern pattern9(URLPattern::SCHEME_HTTPS, "*://*/*");
480   URLPattern pattern10(kAllSchemes, "<all_urls>");
481
482   EXPECT_TRUE(Overlaps(pattern1, pattern1));
483   EXPECT_FALSE(Overlaps(pattern1, pattern2));
484   EXPECT_TRUE(Overlaps(pattern1, pattern3));
485   EXPECT_FALSE(Overlaps(pattern1, pattern4));
486   EXPECT_FALSE(Overlaps(pattern3, pattern4));
487   EXPECT_FALSE(Overlaps(pattern4, pattern5));
488   EXPECT_TRUE(Overlaps(pattern5, pattern6));
489
490   // Test that scheme restrictions work.
491   EXPECT_TRUE(Overlaps(pattern1, pattern8));
492   EXPECT_FALSE(Overlaps(pattern1, pattern9));
493   EXPECT_TRUE(Overlaps(pattern1, pattern10));
494
495   // Test that '<all_urls>' includes file URLs, while scheme '*' does not.
496   EXPECT_FALSE(Overlaps(pattern7, pattern8));
497   EXPECT_TRUE(Overlaps(pattern7, pattern10));
498
499   // Test that wildcard schemes are handled correctly, especially when compared
500   // to each-other.
501   URLPattern pattern11(kAllSchemes, "http://example.com/*");
502   URLPattern pattern12(kAllSchemes, "*://example.com/*");
503   URLPattern pattern13(kAllSchemes, "*://example.com/foo/*");
504   URLPattern pattern14(kAllSchemes, "*://google.com/*");
505   EXPECT_TRUE(Overlaps(pattern8, pattern12));
506   EXPECT_TRUE(Overlaps(pattern9, pattern12));
507   EXPECT_TRUE(Overlaps(pattern10, pattern12));
508   EXPECT_TRUE(Overlaps(pattern11, pattern12));
509   EXPECT_TRUE(Overlaps(pattern12, pattern13));
510   EXPECT_TRUE(Overlaps(pattern11, pattern13));
511   EXPECT_FALSE(Overlaps(pattern14, pattern12));
512   EXPECT_FALSE(Overlaps(pattern14, pattern13));
513 }
514
515 TEST(ExtensionURLPatternTest, ConvertToExplicitSchemes) {
516   URLPatternList all_urls(URLPattern(
517       kAllSchemes,
518       "<all_urls>").ConvertToExplicitSchemes());
519
520   URLPatternList all_schemes(URLPattern(
521       kAllSchemes,
522       "*://google.com/foo").ConvertToExplicitSchemes());
523
524   URLPatternList monkey(URLPattern(
525       URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS |
526       URLPattern::SCHEME_FTP,
527       "http://google.com/monkey").ConvertToExplicitSchemes());
528
529   ASSERT_EQ(7u, all_urls.size());
530   ASSERT_EQ(2u, all_schemes.size());
531   ASSERT_EQ(1u, monkey.size());
532
533   EXPECT_EQ("http://*/*", all_urls[0].GetAsString());
534   EXPECT_EQ("https://*/*", all_urls[1].GetAsString());
535   EXPECT_EQ("file:///*", all_urls[2].GetAsString());
536   EXPECT_EQ("ftp://*/*", all_urls[3].GetAsString());
537   EXPECT_EQ("chrome://*/*", all_urls[4].GetAsString());
538
539   EXPECT_EQ("http://google.com/foo", all_schemes[0].GetAsString());
540   EXPECT_EQ("https://google.com/foo", all_schemes[1].GetAsString());
541
542   EXPECT_EQ("http://google.com/monkey", monkey[0].GetAsString());
543 }
544
545 TEST(ExtensionURLPatternTest, IgnorePorts) {
546   std::string pattern_str = "http://www.example.com:8080/foo";
547   GURL url("http://www.example.com:1234/foo");
548
549   URLPattern pattern(kAllSchemes);
550   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern.Parse(pattern_str));
551
552   EXPECT_EQ(pattern_str, pattern.GetAsString());
553   EXPECT_FALSE(pattern.MatchesURL(url));
554 }
555
556 TEST(ExtensionURLPatternTest, IgnoreMissingBackslashes) {
557   std::string pattern_str1 = "http://www.example.com/example";
558   std::string pattern_str2 = "http://www.example.com/example/*";
559   GURL url1("http://www.example.com/example");
560   GURL url2("http://www.example.com/example/");
561
562   URLPattern pattern1(kAllSchemes);
563   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse(pattern_str1));
564   URLPattern pattern2(kAllSchemes);
565   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern2.Parse(pattern_str2));
566
567   // Same patterns should match same urls.
568   EXPECT_TRUE(pattern1.MatchesURL(url1));
569   EXPECT_TRUE(pattern2.MatchesURL(url2));
570   // The not terminated path should match the terminated pattern.
571   EXPECT_TRUE(pattern2.MatchesURL(url1));
572   // The terminated path however should not match the unterminated pattern.
573   EXPECT_FALSE(pattern1.MatchesURL(url2));
574 }
575
576 TEST(ExtensionURLPatternTest, Equals) {
577   const struct {
578     const char* pattern1;
579     const char* pattern2;
580     bool expected_equal;
581   } kEqualsTestCases[] = {
582     // schemes
583     { "http://en.google.com/blah/*/foo",
584       "https://en.google.com/blah/*/foo",
585       false
586     },
587     { "https://en.google.com/blah/*/foo",
588       "https://en.google.com/blah/*/foo",
589       true
590     },
591     { "https://en.google.com/blah/*/foo",
592       "ftp://en.google.com/blah/*/foo",
593       false
594     },
595
596     // subdomains
597     { "https://en.google.com/blah/*/foo",
598       "https://fr.google.com/blah/*/foo",
599       false
600     },
601     { "https://www.google.com/blah/*/foo",
602       "https://*.google.com/blah/*/foo",
603       false
604     },
605     { "https://*.google.com/blah/*/foo",
606       "https://*.google.com/blah/*/foo",
607       true
608     },
609
610     // domains
611     { "http://en.example.com/blah/*/foo",
612       "http://en.google.com/blah/*/foo",
613       false
614     },
615
616     // ports
617     { "http://en.google.com:8000/blah/*/foo",
618       "http://en.google.com/blah/*/foo",
619       false
620     },
621     { "http://fr.google.com:8000/blah/*/foo",
622       "http://fr.google.com:8000/blah/*/foo",
623       true
624     },
625     { "http://en.google.com:8000/blah/*/foo",
626       "http://en.google.com:8080/blah/*/foo",
627       false
628     },
629
630     // paths
631     { "http://en.google.com/blah/*/foo",
632       "http://en.google.com/blah/*",
633       false
634     },
635     { "http://en.google.com/*",
636       "http://en.google.com/",
637       false
638     },
639     { "http://en.google.com/*",
640       "http://en.google.com/*",
641       true
642     },
643
644     // all_urls
645     { "<all_urls>",
646       "<all_urls>",
647       true
648     },
649     { "<all_urls>",
650       "http://*/*",
651       false
652     }
653   };
654
655   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kEqualsTestCases); ++i) {
656     std::string message = kEqualsTestCases[i].pattern1;
657     message += " ";
658     message += kEqualsTestCases[i].pattern2;
659
660     URLPattern pattern1(URLPattern::SCHEME_ALL);
661     URLPattern pattern2(URLPattern::SCHEME_ALL);
662
663     pattern1.Parse(kEqualsTestCases[i].pattern1);
664     pattern2.Parse(kEqualsTestCases[i].pattern2);
665     EXPECT_EQ(kEqualsTestCases[i].expected_equal, pattern1 == pattern2)
666         << message;
667   }
668 }
669
670 TEST(ExtensionURLPatternTest, CanReusePatternWithParse) {
671   URLPattern pattern1(URLPattern::SCHEME_ALL);
672   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse("http://aa.com/*"));
673   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern1.Parse("http://bb.com/*"));
674
675   EXPECT_TRUE(pattern1.MatchesURL(GURL("http://bb.com/path")));
676   EXPECT_FALSE(pattern1.MatchesURL(GURL("http://aa.com/path")));
677
678   URLPattern pattern2(URLPattern::SCHEME_ALL, URLPattern::kAllUrlsPattern);
679   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern2.Parse("http://aa.com/*"));
680
681   EXPECT_FALSE(pattern2.MatchesURL(GURL("http://bb.com/path")));
682   EXPECT_TRUE(pattern2.MatchesURL(GURL("http://aa.com/path")));
683   EXPECT_FALSE(pattern2.MatchesURL(GURL("http://sub.aa.com/path")));
684
685   URLPattern pattern3(URLPattern::SCHEME_ALL, "http://aa.com/*");
686   EXPECT_EQ(URLPattern::PARSE_SUCCESS, pattern3.Parse("http://aa.com:88/*"));
687   EXPECT_FALSE(pattern3.MatchesURL(GURL("http://aa.com/path")));
688   EXPECT_TRUE(pattern3.MatchesURL(GURL("http://aa.com:88/path")));
689 }
690
691 // Returns success if neither |a| nor |b| encompasses the other.
692 testing::AssertionResult NeitherContains(const URLPattern& a,
693                                          const URLPattern& b) {
694   if (a.Contains(b))
695     return testing::AssertionFailure() << a.GetAsString() << " encompasses " <<
696                                           b.GetAsString();
697   if (b.Contains(a))
698     return testing::AssertionFailure() << b.GetAsString() << " encompasses " <<
699                                           a.GetAsString();
700   return testing::AssertionSuccess() <<
701       "Neither " << a.GetAsString() << " nor " << b.GetAsString() <<
702       " encompass the other";
703 }
704
705 // Returns success if |a| encompasses |b| but not the other way around.
706 testing::AssertionResult StrictlyContains(const URLPattern& a,
707                                           const URLPattern& b) {
708   if (!a.Contains(b))
709     return testing::AssertionFailure() << a.GetAsString() <<
710                                           " does not encompass " <<
711                                           b.GetAsString();
712   if (b.Contains(a))
713     return testing::AssertionFailure() << b.GetAsString() << " encompasses " <<
714                                           a.GetAsString();
715   return testing::AssertionSuccess() << a.GetAsString() <<
716                                         " strictly encompasses " <<
717                                         b.GetAsString();
718 }
719
720 TEST(ExtensionURLPatternTest, Subset) {
721   URLPattern pattern1(kAllSchemes, "http://www.google.com/foo/*");
722   URLPattern pattern2(kAllSchemes, "https://www.google.com/foo/*");
723   URLPattern pattern3(kAllSchemes, "http://*.google.com/foo/*");
724   URLPattern pattern4(kAllSchemes, "http://*.yahooo.com/foo/*");
725   URLPattern pattern5(kAllSchemes, "http://www.yahooo.com/bar/*");
726   URLPattern pattern6(kAllSchemes, "http://www.yahooo.com/bar/baz/*");
727   URLPattern pattern7(kAllSchemes, "file:///*");
728   URLPattern pattern8(kAllSchemes, "*://*/*");
729   URLPattern pattern9(URLPattern::SCHEME_HTTPS, "*://*/*");
730   URLPattern pattern10(kAllSchemes, "<all_urls>");
731   URLPattern pattern11(kAllSchemes, "http://example.com/*");
732   URLPattern pattern12(kAllSchemes, "*://example.com/*");
733   URLPattern pattern13(kAllSchemes, "*://example.com/foo/*");
734
735   // All patterns should encompass themselves.
736   EXPECT_TRUE(pattern1.Contains(pattern1));
737   EXPECT_TRUE(pattern2.Contains(pattern2));
738   EXPECT_TRUE(pattern3.Contains(pattern3));
739   EXPECT_TRUE(pattern4.Contains(pattern4));
740   EXPECT_TRUE(pattern5.Contains(pattern5));
741   EXPECT_TRUE(pattern6.Contains(pattern6));
742   EXPECT_TRUE(pattern7.Contains(pattern7));
743   EXPECT_TRUE(pattern8.Contains(pattern8));
744   EXPECT_TRUE(pattern9.Contains(pattern9));
745   EXPECT_TRUE(pattern10.Contains(pattern10));
746   EXPECT_TRUE(pattern11.Contains(pattern11));
747   EXPECT_TRUE(pattern12.Contains(pattern12));
748   EXPECT_TRUE(pattern13.Contains(pattern13));
749
750   // pattern1's relationship to the other patterns.
751   EXPECT_TRUE(NeitherContains(pattern1, pattern2));
752   EXPECT_TRUE(StrictlyContains(pattern3, pattern1));
753   EXPECT_TRUE(NeitherContains(pattern1, pattern4));
754   EXPECT_TRUE(NeitherContains(pattern1, pattern5));
755   EXPECT_TRUE(NeitherContains(pattern1, pattern6));
756   EXPECT_TRUE(NeitherContains(pattern1, pattern7));
757   EXPECT_TRUE(StrictlyContains(pattern8, pattern1));
758   EXPECT_TRUE(NeitherContains(pattern1, pattern9));
759   EXPECT_TRUE(StrictlyContains(pattern10, pattern1));
760   EXPECT_TRUE(NeitherContains(pattern1, pattern11));
761   EXPECT_TRUE(NeitherContains(pattern1, pattern12));
762   EXPECT_TRUE(NeitherContains(pattern1, pattern13));
763
764   // pattern2's relationship to the other patterns.
765   EXPECT_TRUE(NeitherContains(pattern2, pattern3));
766   EXPECT_TRUE(NeitherContains(pattern2, pattern4));
767   EXPECT_TRUE(NeitherContains(pattern2, pattern5));
768   EXPECT_TRUE(NeitherContains(pattern2, pattern6));
769   EXPECT_TRUE(NeitherContains(pattern2, pattern7));
770   EXPECT_TRUE(StrictlyContains(pattern8, pattern2));
771   EXPECT_TRUE(StrictlyContains(pattern9, pattern2));
772   EXPECT_TRUE(StrictlyContains(pattern10, pattern2));
773   EXPECT_TRUE(NeitherContains(pattern2, pattern11));
774   EXPECT_TRUE(NeitherContains(pattern2, pattern12));
775   EXPECT_TRUE(NeitherContains(pattern2, pattern13));
776
777   // Specifically test file:// URLs.
778   EXPECT_TRUE(NeitherContains(pattern7, pattern8));
779   EXPECT_TRUE(NeitherContains(pattern7, pattern9));
780   EXPECT_TRUE(StrictlyContains(pattern10, pattern7));
781
782   // <all_urls> encompasses everything.
783   EXPECT_TRUE(StrictlyContains(pattern10, pattern1));
784   EXPECT_TRUE(StrictlyContains(pattern10, pattern2));
785   EXPECT_TRUE(StrictlyContains(pattern10, pattern3));
786   EXPECT_TRUE(StrictlyContains(pattern10, pattern4));
787   EXPECT_TRUE(StrictlyContains(pattern10, pattern5));
788   EXPECT_TRUE(StrictlyContains(pattern10, pattern6));
789   EXPECT_TRUE(StrictlyContains(pattern10, pattern7));
790   EXPECT_TRUE(StrictlyContains(pattern10, pattern8));
791   EXPECT_TRUE(StrictlyContains(pattern10, pattern9));
792   EXPECT_TRUE(StrictlyContains(pattern10, pattern11));
793   EXPECT_TRUE(StrictlyContains(pattern10, pattern12));
794   EXPECT_TRUE(StrictlyContains(pattern10, pattern13));
795
796   // More...
797   EXPECT_TRUE(StrictlyContains(pattern12, pattern11));
798   EXPECT_TRUE(NeitherContains(pattern11, pattern13));
799   EXPECT_TRUE(StrictlyContains(pattern12, pattern13));
800 }
801
802 }  // namespace