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