OLD | NEW |
| (Empty) |
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 "chrome/common/content_settings_pattern.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/strings/string_split.h" | |
11 #include "base/strings/string_util.h" | |
12 #include "chrome/common/content_settings_pattern_parser.h" | |
13 #include "net/base/dns_util.h" | |
14 #include "net/base/net_util.h" | |
15 #include "url/gurl.h" | |
16 | |
17 namespace { | |
18 | |
19 // The component supports only one scheme for simplicity. | |
20 const char* non_port_non_domain_wildcard_scheme = NULL; | |
21 | |
22 std::string GetDefaultPort(const std::string& scheme) { | |
23 if (scheme == url::kHttpScheme) | |
24 return "80"; | |
25 if (scheme == url::kHttpsScheme) | |
26 return "443"; | |
27 return std::string(); | |
28 } | |
29 | |
30 // Returns true if |sub_domain| is a sub domain or equls |domain|. E.g. | |
31 // "mail.google.com" is a sub domain of "google.com" but "evilhost.com" is not a | |
32 // subdomain of "host.com". | |
33 bool IsSubDomainOrEqual(const std::string& sub_domain, | |
34 const std::string& domain) { | |
35 // The empty string serves as wildcard. Each domain is a subdomain of the | |
36 // wildcard. | |
37 if (domain.empty()) | |
38 return true; | |
39 const size_t match = sub_domain.rfind(domain); | |
40 if (match == std::string::npos || | |
41 (match > 0 && sub_domain[match - 1] != '.') || | |
42 (match + domain.length() != sub_domain.length())) { | |
43 return false; | |
44 } | |
45 return true; | |
46 } | |
47 | |
48 // Compares two domain names. | |
49 int CompareDomainNames(const std::string& str1, const std::string& str2) { | |
50 std::vector<std::string> domain_name1; | |
51 std::vector<std::string> domain_name2; | |
52 | |
53 base::SplitString(str1, '.', &domain_name1); | |
54 base::SplitString(str2, '.', &domain_name2); | |
55 | |
56 int i1 = domain_name1.size() - 1; | |
57 int i2 = domain_name2.size() - 1; | |
58 int rv; | |
59 while (i1 >= 0 && i2 >= 0) { | |
60 // domain names are stored in puny code. So it's fine to use the compare | |
61 // method. | |
62 rv = domain_name1[i1].compare(domain_name2[i2]); | |
63 if (rv != 0) | |
64 return rv; | |
65 --i1; | |
66 --i2; | |
67 } | |
68 | |
69 if (i1 > i2) | |
70 return 1; | |
71 | |
72 if (i1 < i2) | |
73 return -1; | |
74 | |
75 // The domain names are identical. | |
76 return 0; | |
77 } | |
78 | |
79 typedef ContentSettingsPattern::BuilderInterface BuilderInterface; | |
80 | |
81 } // namespace | |
82 | |
83 // //////////////////////////////////////////////////////////////////////////// | |
84 // ContentSettingsPattern::Builder | |
85 // | |
86 class ContentSettingsPattern::Builder : | |
87 public ContentSettingsPattern::BuilderInterface { | |
88 public: | |
89 explicit Builder(bool use_legacy_validate); | |
90 virtual ~Builder(); | |
91 | |
92 // BuilderInterface: | |
93 virtual BuilderInterface* WithPort(const std::string& port) OVERRIDE; | |
94 virtual BuilderInterface* WithPortWildcard() OVERRIDE; | |
95 virtual BuilderInterface* WithHost(const std::string& host) OVERRIDE; | |
96 virtual BuilderInterface* WithDomainWildcard() OVERRIDE; | |
97 virtual BuilderInterface* WithScheme(const std::string& scheme) OVERRIDE; | |
98 virtual BuilderInterface* WithSchemeWildcard() OVERRIDE; | |
99 virtual BuilderInterface* WithPath(const std::string& path) OVERRIDE; | |
100 virtual BuilderInterface* WithPathWildcard() OVERRIDE; | |
101 virtual BuilderInterface* Invalid() OVERRIDE; | |
102 virtual ContentSettingsPattern Build() OVERRIDE; | |
103 | |
104 private: | |
105 // Canonicalizes the pattern parts so that they are ASCII only, either | |
106 // in original (if it was already ASCII) or punycode form. Returns true if | |
107 // the canonicalization was successful. | |
108 static bool Canonicalize(PatternParts* parts); | |
109 | |
110 // Returns true when the pattern |parts| represent a valid pattern. | |
111 static bool Validate(const PatternParts& parts); | |
112 | |
113 static bool LegacyValidate(const PatternParts& parts); | |
114 | |
115 bool is_valid_; | |
116 | |
117 bool use_legacy_validate_; | |
118 | |
119 PatternParts parts_; | |
120 | |
121 DISALLOW_COPY_AND_ASSIGN(Builder); | |
122 }; | |
123 | |
124 ContentSettingsPattern::Builder::Builder(bool use_legacy_validate) | |
125 : is_valid_(true), | |
126 use_legacy_validate_(use_legacy_validate) {} | |
127 | |
128 ContentSettingsPattern::Builder::~Builder() {} | |
129 | |
130 BuilderInterface* ContentSettingsPattern::Builder::WithPort( | |
131 const std::string& port) { | |
132 parts_.port = port; | |
133 parts_.is_port_wildcard = false; | |
134 return this; | |
135 } | |
136 | |
137 BuilderInterface* ContentSettingsPattern::Builder::WithPortWildcard() { | |
138 parts_.port = ""; | |
139 parts_.is_port_wildcard = true; | |
140 return this; | |
141 } | |
142 | |
143 BuilderInterface* ContentSettingsPattern::Builder::WithHost( | |
144 const std::string& host) { | |
145 parts_.host = host; | |
146 return this; | |
147 } | |
148 | |
149 BuilderInterface* ContentSettingsPattern::Builder::WithDomainWildcard() { | |
150 parts_.has_domain_wildcard = true; | |
151 return this; | |
152 } | |
153 | |
154 BuilderInterface* ContentSettingsPattern::Builder::WithScheme( | |
155 const std::string& scheme) { | |
156 parts_.scheme = scheme; | |
157 parts_.is_scheme_wildcard = false; | |
158 return this; | |
159 } | |
160 | |
161 BuilderInterface* ContentSettingsPattern::Builder::WithSchemeWildcard() { | |
162 parts_.scheme = ""; | |
163 parts_.is_scheme_wildcard = true; | |
164 return this; | |
165 } | |
166 | |
167 BuilderInterface* ContentSettingsPattern::Builder::WithPath( | |
168 const std::string& path) { | |
169 parts_.path = path; | |
170 parts_.is_path_wildcard = false; | |
171 return this; | |
172 } | |
173 | |
174 BuilderInterface* ContentSettingsPattern::Builder::WithPathWildcard() { | |
175 parts_.path = ""; | |
176 parts_.is_path_wildcard = true; | |
177 return this; | |
178 } | |
179 | |
180 BuilderInterface* ContentSettingsPattern::Builder::Invalid() { | |
181 is_valid_ = false; | |
182 return this; | |
183 } | |
184 | |
185 ContentSettingsPattern ContentSettingsPattern::Builder::Build() { | |
186 if (!is_valid_) | |
187 return ContentSettingsPattern(); | |
188 if (!Canonicalize(&parts_)) | |
189 return ContentSettingsPattern(); | |
190 if (use_legacy_validate_) { | |
191 is_valid_ = LegacyValidate(parts_); | |
192 } else { | |
193 is_valid_ = Validate(parts_); | |
194 } | |
195 if (!is_valid_) | |
196 return ContentSettingsPattern(); | |
197 | |
198 // A pattern is invalid if canonicalization is not idempotent. | |
199 // This check is here because it should be checked no matter | |
200 // use_legacy_validate_ is. | |
201 PatternParts parts(parts_); | |
202 if (!Canonicalize(&parts)) | |
203 return ContentSettingsPattern(); | |
204 if (ContentSettingsPattern(parts_, true) != | |
205 ContentSettingsPattern(parts, true)) { | |
206 return ContentSettingsPattern(); | |
207 } | |
208 | |
209 return ContentSettingsPattern(parts_, is_valid_); | |
210 } | |
211 | |
212 // static | |
213 bool ContentSettingsPattern::Builder::Canonicalize(PatternParts* parts) { | |
214 // Canonicalize the scheme part. | |
215 const std::string scheme(base::StringToLowerASCII(parts->scheme)); | |
216 parts->scheme = scheme; | |
217 | |
218 if (parts->scheme == std::string(url::kFileScheme) && | |
219 !parts->is_path_wildcard) { | |
220 GURL url(std::string(url::kFileScheme) + | |
221 std::string(url::kStandardSchemeSeparator) + parts->path); | |
222 parts->path = url.path(); | |
223 } | |
224 | |
225 // Canonicalize the host part. | |
226 const std::string host(parts->host); | |
227 url::CanonHostInfo host_info; | |
228 std::string canonicalized_host(net::CanonicalizeHost(host, &host_info)); | |
229 if (host_info.IsIPAddress() && parts->has_domain_wildcard) | |
230 return false; | |
231 canonicalized_host = net::TrimEndingDot(canonicalized_host); | |
232 | |
233 parts->host = ""; | |
234 if ((host.find('*') == std::string::npos) && | |
235 !canonicalized_host.empty()) { | |
236 // Valid host. | |
237 parts->host += canonicalized_host; | |
238 } | |
239 return true; | |
240 } | |
241 | |
242 // static | |
243 bool ContentSettingsPattern::Builder::Validate(const PatternParts& parts) { | |
244 // Sanity checks first: {scheme, port} wildcards imply empty {scheme, port}. | |
245 if ((parts.is_scheme_wildcard && !parts.scheme.empty()) || | |
246 (parts.is_port_wildcard && !parts.port.empty())) { | |
247 NOTREACHED(); | |
248 return false; | |
249 } | |
250 | |
251 // file:// URL patterns have an empty host and port. | |
252 if (parts.scheme == std::string(url::kFileScheme)) { | |
253 if (parts.has_domain_wildcard || !parts.host.empty() || !parts.port.empty()) | |
254 return false; | |
255 if (parts.is_path_wildcard) | |
256 return parts.path.empty(); | |
257 return (!parts.path.empty() && | |
258 parts.path != "/" && | |
259 parts.path.find("*") == std::string::npos); | |
260 } | |
261 | |
262 // If the pattern is for an extension URL test if it is valid. | |
263 if (IsNonWildcardDomainNonPortScheme(parts.scheme) && | |
264 parts.port.empty() && | |
265 !parts.is_port_wildcard) { | |
266 return true; | |
267 } | |
268 | |
269 // Non-file patterns are invalid if either the scheme, host or port part is | |
270 // empty. | |
271 if ((parts.scheme.empty() && !parts.is_scheme_wildcard) || | |
272 (parts.host.empty() && !parts.has_domain_wildcard) || | |
273 (parts.port.empty() && !parts.is_port_wildcard)) { | |
274 return false; | |
275 } | |
276 | |
277 if (parts.host.find("*") != std::string::npos) | |
278 return false; | |
279 | |
280 // Test if the scheme is supported or a wildcard. | |
281 if (!parts.is_scheme_wildcard && | |
282 parts.scheme != std::string(url::kHttpScheme) && | |
283 parts.scheme != std::string(url::kHttpsScheme)) { | |
284 return false; | |
285 } | |
286 return true; | |
287 } | |
288 | |
289 // static | |
290 bool ContentSettingsPattern::Builder::LegacyValidate( | |
291 const PatternParts& parts) { | |
292 // If the pattern is for a "file-pattern" test if it is valid. | |
293 if (parts.scheme == std::string(url::kFileScheme) && | |
294 !parts.is_scheme_wildcard && | |
295 parts.host.empty() && | |
296 parts.port.empty()) | |
297 return true; | |
298 | |
299 // If the pattern is for an extension URL test if it is valid. | |
300 if (IsNonWildcardDomainNonPortScheme(parts.scheme) && | |
301 !parts.is_scheme_wildcard && | |
302 !parts.host.empty() && | |
303 !parts.has_domain_wildcard && | |
304 parts.port.empty() && | |
305 !parts.is_port_wildcard) | |
306 return true; | |
307 | |
308 // Non-file patterns are invalid if either the scheme, host or port part is | |
309 // empty. | |
310 if ((!parts.is_scheme_wildcard) || | |
311 (parts.host.empty() && !parts.has_domain_wildcard) || | |
312 (!parts.is_port_wildcard)) | |
313 return false; | |
314 | |
315 // Test if the scheme is supported or a wildcard. | |
316 if (!parts.is_scheme_wildcard && | |
317 parts.scheme != std::string(url::kHttpScheme) && | |
318 parts.scheme != std::string(url::kHttpsScheme)) { | |
319 return false; | |
320 } | |
321 return true; | |
322 } | |
323 | |
324 // //////////////////////////////////////////////////////////////////////////// | |
325 // ContentSettingsPattern::PatternParts | |
326 // | |
327 ContentSettingsPattern::PatternParts::PatternParts() | |
328 : is_scheme_wildcard(false), | |
329 has_domain_wildcard(false), | |
330 is_port_wildcard(false), | |
331 is_path_wildcard(false) {} | |
332 | |
333 ContentSettingsPattern::PatternParts::~PatternParts() {} | |
334 | |
335 // //////////////////////////////////////////////////////////////////////////// | |
336 // ContentSettingsPattern | |
337 // | |
338 | |
339 // The version of the pattern format implemented. Version 1 includes the | |
340 // following patterns: | |
341 // - [*.]domain.tld (matches domain.tld and all sub-domains) | |
342 // - host (matches an exact hostname) | |
343 // - a.b.c.d (matches an exact IPv4 ip) | |
344 // - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip) | |
345 // - file:///tmp/test.html (a complete URL without a host) | |
346 // Version 2 adds a resource identifier for plugins. | |
347 // TODO(jochen): update once this feature is no longer behind a flag. | |
348 const int ContentSettingsPattern::kContentSettingsPatternVersion = 1; | |
349 | |
350 // static | |
351 BuilderInterface* ContentSettingsPattern::CreateBuilder( | |
352 bool validate) { | |
353 return new Builder(validate); | |
354 } | |
355 | |
356 // static | |
357 ContentSettingsPattern ContentSettingsPattern::Wildcard() { | |
358 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | |
359 ContentSettingsPattern::CreateBuilder(true)); | |
360 builder->WithSchemeWildcard()->WithDomainWildcard()->WithPortWildcard()-> | |
361 WithPathWildcard(); | |
362 return builder->Build(); | |
363 } | |
364 | |
365 // static | |
366 ContentSettingsPattern ContentSettingsPattern::FromURL( | |
367 const GURL& url) { | |
368 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | |
369 ContentSettingsPattern::CreateBuilder(false)); | |
370 | |
371 const GURL* local_url = &url; | |
372 if (url.SchemeIsFileSystem() && url.inner_url()) { | |
373 local_url = url.inner_url(); | |
374 } | |
375 if (local_url->SchemeIsFile()) { | |
376 builder->WithScheme(local_url->scheme())->WithPath(local_url->path()); | |
377 } else { | |
378 // Please keep the order of the ifs below as URLs with an IP as host can | |
379 // also have a "http" scheme. | |
380 if (local_url->HostIsIPAddress()) { | |
381 builder->WithScheme(local_url->scheme())->WithHost(local_url->host()); | |
382 } else if (local_url->SchemeIs(url::kHttpScheme)) { | |
383 builder->WithSchemeWildcard()->WithDomainWildcard()->WithHost( | |
384 local_url->host()); | |
385 } else if (local_url->SchemeIs(url::kHttpsScheme)) { | |
386 builder->WithScheme(local_url->scheme())->WithDomainWildcard()->WithHost( | |
387 local_url->host()); | |
388 } else { | |
389 // Unsupported scheme | |
390 } | |
391 if (local_url->port().empty()) { | |
392 if (local_url->SchemeIs(url::kHttpsScheme)) | |
393 builder->WithPort(GetDefaultPort(url::kHttpsScheme)); | |
394 else | |
395 builder->WithPortWildcard(); | |
396 } else { | |
397 builder->WithPort(local_url->port()); | |
398 } | |
399 } | |
400 return builder->Build(); | |
401 } | |
402 | |
403 // static | |
404 ContentSettingsPattern ContentSettingsPattern::FromURLNoWildcard( | |
405 const GURL& url) { | |
406 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | |
407 ContentSettingsPattern::CreateBuilder(false)); | |
408 | |
409 const GURL* local_url = &url; | |
410 if (url.SchemeIsFileSystem() && url.inner_url()) { | |
411 local_url = url.inner_url(); | |
412 } | |
413 if (local_url->SchemeIsFile()) { | |
414 builder->WithScheme(local_url->scheme())->WithPath(local_url->path()); | |
415 } else { | |
416 builder->WithScheme(local_url->scheme())->WithHost(local_url->host()); | |
417 if (local_url->port().empty()) { | |
418 builder->WithPort(GetDefaultPort(local_url->scheme())); | |
419 } else { | |
420 builder->WithPort(local_url->port()); | |
421 } | |
422 } | |
423 return builder->Build(); | |
424 } | |
425 | |
426 // static | |
427 ContentSettingsPattern ContentSettingsPattern::FromString( | |
428 const std::string& pattern_spec) { | |
429 scoped_ptr<ContentSettingsPattern::BuilderInterface> builder( | |
430 ContentSettingsPattern::CreateBuilder(false)); | |
431 content_settings::PatternParser::Parse(pattern_spec, | |
432 builder.get()); | |
433 return builder->Build(); | |
434 } | |
435 | |
436 // static | |
437 void ContentSettingsPattern::SetNonWildcardDomainNonPortScheme( | |
438 const char* scheme) { | |
439 DCHECK(scheme); | |
440 DCHECK(!non_port_non_domain_wildcard_scheme || | |
441 non_port_non_domain_wildcard_scheme == scheme); | |
442 non_port_non_domain_wildcard_scheme = scheme; | |
443 } | |
444 | |
445 // static | |
446 bool ContentSettingsPattern::IsNonWildcardDomainNonPortScheme( | |
447 const std::string& scheme) { | |
448 DCHECK(non_port_non_domain_wildcard_scheme); | |
449 return scheme == non_port_non_domain_wildcard_scheme; | |
450 } | |
451 | |
452 ContentSettingsPattern::ContentSettingsPattern() | |
453 : is_valid_(false) { | |
454 } | |
455 | |
456 ContentSettingsPattern::ContentSettingsPattern( | |
457 const PatternParts& parts, | |
458 bool valid) | |
459 : parts_(parts), | |
460 is_valid_(valid) { | |
461 } | |
462 | |
463 bool ContentSettingsPattern::Matches( | |
464 const GURL& url) const { | |
465 // An invalid pattern matches nothing. | |
466 if (!is_valid_) | |
467 return false; | |
468 | |
469 const GURL* local_url = &url; | |
470 if (url.SchemeIsFileSystem() && url.inner_url()) { | |
471 local_url = url.inner_url(); | |
472 } | |
473 | |
474 // Match the scheme part. | |
475 const std::string scheme(local_url->scheme()); | |
476 if (!parts_.is_scheme_wildcard && | |
477 parts_.scheme != scheme) { | |
478 return false; | |
479 } | |
480 | |
481 // File URLs have no host. Matches if the pattern has the path wildcard set, | |
482 // or if the path in the URL is identical to the one in the pattern. | |
483 // For filesystem:file URLs, the path used is the filesystem type, so all | |
484 // filesystem:file:///temporary/... are equivalent. | |
485 // TODO(markusheintz): Content settings should be defined for all files on | |
486 // a machine. Unless there is a good use case for supporting paths for file | |
487 // patterns, stop supporting path for file patterns. | |
488 if (!parts_.is_scheme_wildcard && scheme == url::kFileScheme) | |
489 return parts_.is_path_wildcard || | |
490 parts_.path == std::string(local_url->path()); | |
491 | |
492 // Match the host part. | |
493 const std::string host(net::TrimEndingDot(local_url->host())); | |
494 if (!parts_.has_domain_wildcard) { | |
495 if (parts_.host != host) | |
496 return false; | |
497 } else { | |
498 if (!IsSubDomainOrEqual(host, parts_.host)) | |
499 return false; | |
500 } | |
501 | |
502 // Ignore the port if the scheme doesn't support it. | |
503 if (IsNonWildcardDomainNonPortScheme(parts_.scheme)) | |
504 return true; | |
505 | |
506 // Match the port part. | |
507 std::string port(local_url->port()); | |
508 | |
509 // Use the default port if the port string is empty. GURL returns an empty | |
510 // string if no port at all was specified or if the default port was | |
511 // specified. | |
512 if (port.empty()) { | |
513 port = GetDefaultPort(scheme); | |
514 } | |
515 | |
516 if (!parts_.is_port_wildcard && | |
517 parts_.port != port ) { | |
518 return false; | |
519 } | |
520 | |
521 return true; | |
522 } | |
523 | |
524 bool ContentSettingsPattern::MatchesAllHosts() const { | |
525 return parts_.has_domain_wildcard && parts_.host.empty(); | |
526 } | |
527 | |
528 std::string ContentSettingsPattern::ToString() const { | |
529 if (IsValid()) | |
530 return content_settings::PatternParser::ToString(parts_); | |
531 else | |
532 return std::string(); | |
533 } | |
534 | |
535 ContentSettingsPattern::Relation ContentSettingsPattern::Compare( | |
536 const ContentSettingsPattern& other) const { | |
537 // Two invalid patterns are identical in the way they behave. They don't match | |
538 // anything and are represented as an empty string. So it's fair to treat them | |
539 // as identical. | |
540 if ((this == &other) || | |
541 (!is_valid_ && !other.is_valid_)) | |
542 return IDENTITY; | |
543 | |
544 if (!is_valid_ && other.is_valid_) | |
545 return DISJOINT_ORDER_POST; | |
546 if (is_valid_ && !other.is_valid_) | |
547 return DISJOINT_ORDER_PRE; | |
548 | |
549 // If either host, port or scheme are disjoint return immediately. | |
550 Relation host_relation = CompareHost(parts_, other.parts_); | |
551 if (host_relation == DISJOINT_ORDER_PRE || | |
552 host_relation == DISJOINT_ORDER_POST) | |
553 return host_relation; | |
554 | |
555 Relation port_relation = ComparePort(parts_, other.parts_); | |
556 if (port_relation == DISJOINT_ORDER_PRE || | |
557 port_relation == DISJOINT_ORDER_POST) | |
558 return port_relation; | |
559 | |
560 Relation scheme_relation = CompareScheme(parts_, other.parts_); | |
561 if (scheme_relation == DISJOINT_ORDER_PRE || | |
562 scheme_relation == DISJOINT_ORDER_POST) | |
563 return scheme_relation; | |
564 | |
565 if (host_relation != IDENTITY) | |
566 return host_relation; | |
567 if (port_relation != IDENTITY) | |
568 return port_relation; | |
569 return scheme_relation; | |
570 } | |
571 | |
572 bool ContentSettingsPattern::operator==( | |
573 const ContentSettingsPattern& other) const { | |
574 return Compare(other) == IDENTITY; | |
575 } | |
576 | |
577 bool ContentSettingsPattern::operator!=( | |
578 const ContentSettingsPattern& other) const { | |
579 return !(*this == other); | |
580 } | |
581 | |
582 bool ContentSettingsPattern::operator<( | |
583 const ContentSettingsPattern& other) const { | |
584 return Compare(other) < 0; | |
585 } | |
586 | |
587 bool ContentSettingsPattern::operator>( | |
588 const ContentSettingsPattern& other) const { | |
589 return Compare(other) > 0; | |
590 } | |
591 | |
592 // static | |
593 ContentSettingsPattern::Relation ContentSettingsPattern::CompareScheme( | |
594 const ContentSettingsPattern::PatternParts& parts, | |
595 const ContentSettingsPattern::PatternParts& other_parts) { | |
596 if (parts.is_scheme_wildcard && !other_parts.is_scheme_wildcard) | |
597 return ContentSettingsPattern::SUCCESSOR; | |
598 if (!parts.is_scheme_wildcard && other_parts.is_scheme_wildcard) | |
599 return ContentSettingsPattern::PREDECESSOR; | |
600 | |
601 int result = parts.scheme.compare(other_parts.scheme); | |
602 if (result == 0) | |
603 return ContentSettingsPattern::IDENTITY; | |
604 if (result > 0) | |
605 return ContentSettingsPattern::DISJOINT_ORDER_PRE; | |
606 return ContentSettingsPattern::DISJOINT_ORDER_POST; | |
607 } | |
608 | |
609 // static | |
610 ContentSettingsPattern::Relation ContentSettingsPattern::CompareHost( | |
611 const ContentSettingsPattern::PatternParts& parts, | |
612 const ContentSettingsPattern::PatternParts& other_parts) { | |
613 if (!parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { | |
614 // Case 1: No host starts with a wild card | |
615 int result = CompareDomainNames(parts.host, other_parts.host); | |
616 if (result == 0) | |
617 return ContentSettingsPattern::IDENTITY; | |
618 if (result < 0) | |
619 return ContentSettingsPattern::DISJOINT_ORDER_PRE; | |
620 return ContentSettingsPattern::DISJOINT_ORDER_POST; | |
621 } else if (parts.has_domain_wildcard && !other_parts.has_domain_wildcard) { | |
622 // Case 2: |host| starts with a domain wildcard and |other_host| does not | |
623 // start with a domain wildcard. | |
624 // Examples: | |
625 // "this" host: [*.]google.com | |
626 // "other" host: google.com | |
627 // | |
628 // [*.]google.com | |
629 // mail.google.com | |
630 // | |
631 // [*.]mail.google.com | |
632 // google.com | |
633 // | |
634 // [*.]youtube.com | |
635 // google.de | |
636 // | |
637 // [*.]youtube.com | |
638 // mail.google.com | |
639 // | |
640 // * | |
641 // google.de | |
642 if (IsSubDomainOrEqual(other_parts.host, parts.host)) { | |
643 return ContentSettingsPattern::SUCCESSOR; | |
644 } else { | |
645 if (CompareDomainNames(parts.host, other_parts.host) < 0) | |
646 return ContentSettingsPattern::DISJOINT_ORDER_PRE; | |
647 return ContentSettingsPattern::DISJOINT_ORDER_POST; | |
648 } | |
649 } else if (!parts.has_domain_wildcard && other_parts.has_domain_wildcard) { | |
650 // Case 3: |host| starts NOT with a domain wildcard and |other_host| starts | |
651 // with a domain wildcard. | |
652 if (IsSubDomainOrEqual(parts.host, other_parts.host)) { | |
653 return ContentSettingsPattern::PREDECESSOR; | |
654 } else { | |
655 if (CompareDomainNames(parts.host, other_parts.host) < 0) | |
656 return ContentSettingsPattern::DISJOINT_ORDER_PRE; | |
657 return ContentSettingsPattern::DISJOINT_ORDER_POST; | |
658 } | |
659 } else if (parts.has_domain_wildcard && other_parts.has_domain_wildcard) { | |
660 // Case 4: |host| and |other_host| both start with a domain wildcard. | |
661 // Examples: | |
662 // [*.]google.com | |
663 // [*.]google.com | |
664 // | |
665 // [*.]google.com | |
666 // [*.]mail.google.com | |
667 // | |
668 // [*.]youtube.com | |
669 // [*.]google.de | |
670 // | |
671 // [*.]youtube.com | |
672 // [*.]mail.google.com | |
673 // | |
674 // [*.]youtube.com | |
675 // * | |
676 // | |
677 // * | |
678 // [*.]youtube.com | |
679 if (parts.host == other_parts.host) { | |
680 return ContentSettingsPattern::IDENTITY; | |
681 } else if (IsSubDomainOrEqual(other_parts.host, parts.host)) { | |
682 return ContentSettingsPattern::SUCCESSOR; | |
683 } else if (IsSubDomainOrEqual(parts.host, other_parts.host)) { | |
684 return ContentSettingsPattern::PREDECESSOR; | |
685 } else { | |
686 if (CompareDomainNames(parts.host, other_parts.host) < 0) | |
687 return ContentSettingsPattern::DISJOINT_ORDER_PRE; | |
688 return ContentSettingsPattern::DISJOINT_ORDER_POST; | |
689 } | |
690 } | |
691 | |
692 NOTREACHED(); | |
693 return ContentSettingsPattern::IDENTITY; | |
694 } | |
695 | |
696 // static | |
697 ContentSettingsPattern::Relation ContentSettingsPattern::ComparePort( | |
698 const ContentSettingsPattern::PatternParts& parts, | |
699 const ContentSettingsPattern::PatternParts& other_parts) { | |
700 if (parts.is_port_wildcard && !other_parts.is_port_wildcard) | |
701 return ContentSettingsPattern::SUCCESSOR; | |
702 if (!parts.is_port_wildcard && other_parts.is_port_wildcard) | |
703 return ContentSettingsPattern::PREDECESSOR; | |
704 | |
705 int result = parts.port.compare(other_parts.port); | |
706 if (result == 0) | |
707 return ContentSettingsPattern::IDENTITY; | |
708 if (result > 0) | |
709 return ContentSettingsPattern::DISJOINT_ORDER_PRE; | |
710 return ContentSettingsPattern::DISJOINT_ORDER_POST; | |
711 } | |
OLD | NEW |