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