1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be
321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file.
421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/content_settings/content_settings_pattern.h"
621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/string_util.h"
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/common/url_constants.h"
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/net_util.h"
1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "googleurl/src/gurl.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "googleurl/src/url_canon.h"
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace {
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool IsValidHostlessPattern(const std::string& pattern) {
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::string file_scheme_plus_separator(chrome::kFileScheme);
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  file_scheme_plus_separator += chrome::kStandardSchemeSeparator;
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return StartsWithASCII(pattern, file_scheme_plus_separator, false);
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// The version of the pattern format implemented. Version 1 includes the
2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// following patterns:
2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//   - [*.]domain.tld (matches domain.tld and all sub-domains)
2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//   - host (matches an exact hostname)
2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//   - a.b.c.d (matches an exact IPv4 ip)
2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//   - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip)
3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen//   - file:///tmp/test.html (a complete URL without a host)
3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Version 2 adds a resource identifier for plugins.
3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// TODO(jochen): update once this feature is no longer behind a flag.
3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst int ContentSettingsPattern::kContentSettingsPatternVersion = 1;
3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst char* ContentSettingsPattern::kDomainWildcard = "[*.]";
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst size_t ContentSettingsPattern::kDomainWildcardLength = 4;
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// static
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenContentSettingsPattern ContentSettingsPattern::FromURL(
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const GURL& url) {
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(markusheintz): Add scheme wildcard;
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return ContentSettingsPattern(!url.has_host() || url.HostIsIPAddress() ?
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      net::GetHostOrSpecFromURL(url) :
4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      std::string(kDomainWildcard) + url.host());
4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// static
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenContentSettingsPattern ContentSettingsPattern::FromURLNoWildcard(
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const GURL& url) {
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return ContentSettingsPattern(net::GetHostOrSpecFromURL(url), url.scheme());
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool ContentSettingsPattern::IsValid() const {
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (pattern_.empty())
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return false;
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsValidHostlessPattern(pattern_))
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return true;
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const std::string host(pattern_.length() > kDomainWildcardLength &&
6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                         StartsWithASCII(pattern_, kDomainWildcard, false) ?
6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                         pattern_.substr(kDomainWildcardLength) :
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                         pattern_);
6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  url_canon::CanonHostInfo host_info;
6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return host.find('*') == std::string::npos &&
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         !net::CanonicalizeHost(host, &host_info).empty();
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool ContentSettingsPattern::Matches(const GURL& url) const {
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!IsValid())
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return false;
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const std::string host(net::GetHostOrSpecFromURL(url));
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (pattern_.length() < kDomainWildcardLength ||
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      !StartsWithASCII(pattern_, kDomainWildcard, false))
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return pattern_ == host;
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const size_t match =
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      host.rfind(pattern_.substr(kDomainWildcardLength));
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return (match != std::string::npos) &&
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         (match == 0 || host[match - 1] == '.') &&
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         (match + pattern_.length() - kDomainWildcardLength == host.length());
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstd::string ContentSettingsPattern::CanonicalizePattern() const {
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!IsValid())
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return "";
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (IsValidHostlessPattern(pattern_))
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return GURL(pattern_).spec();
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool starts_with_wildcard = pattern_.length() > kDomainWildcardLength &&
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      StartsWithASCII(pattern_, kDomainWildcard, false);
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const std::string host(starts_with_wildcard ?
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      pattern_.substr(kDomainWildcardLength) : pattern_);
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string canonicalized_pattern =
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      starts_with_wildcard ? kDomainWildcard : "";
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  url_canon::CanonHostInfo host_info;
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  canonicalized_pattern += net::CanonicalizeHost(host, &host_info);
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return canonicalized_pattern;
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
106