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/browser/extensions/api/content_settings/content_settings_helpers.h"
6
7#include "base/basictypes.h"
8#include "base/logging.h"
9#include "base/memory/scoped_ptr.h"
10#include "content/public/common/url_constants.h"
11#include "extensions/common/url_pattern.h"
12
13namespace {
14
15const char kNoPathWildcardsError[] =
16    "Path wildcards in file URL patterns are not allowed.";
17const char kNoPathsError[] = "Specific paths are not allowed.";
18const char kInvalidPatternError[] = "The pattern \"*\" is invalid.";
19
20const char* const kContentSettingsTypeNames[] = {
21  "cookies",
22  "images",
23  "javascript",
24  "plugins",
25  "popups",
26  "location",
27  "notifications",
28};
29COMPILE_ASSERT(arraysize(kContentSettingsTypeNames) <=
30               CONTENT_SETTINGS_NUM_TYPES,
31               content_settings_type_names_size_invalid);
32
33const char* const kContentSettingNames[] = {
34  "default",
35  "allow",
36  "block",
37  "ask",
38  "session_only",
39};
40COMPILE_ASSERT(arraysize(kContentSettingNames) <=
41               CONTENT_SETTING_NUM_SETTINGS,
42               content_setting_names_size_invalid);
43
44// TODO(bauerb): Move this someplace where it can be reused.
45std::string GetDefaultPort(const std::string& scheme) {
46  if (scheme == url::kHttpScheme)
47    return "80";
48  if (scheme == url::kHttpsScheme)
49    return "443";
50  NOTREACHED();
51  return std::string();
52}
53
54}  // namespace
55
56namespace extensions {
57namespace content_settings_helpers {
58
59ContentSettingsPattern ParseExtensionPattern(const std::string& pattern_str,
60                                             std::string* error) {
61  const int kAllowedSchemes =
62      URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS |
63      URLPattern::SCHEME_FILE;
64  URLPattern url_pattern(kAllowedSchemes);
65  URLPattern::ParseResult result = url_pattern.Parse(pattern_str);
66  if (result != URLPattern::PARSE_SUCCESS) {
67    *error = URLPattern::GetParseResultString(result);
68    return ContentSettingsPattern();
69  } else {
70    scoped_ptr<ContentSettingsPattern::BuilderInterface> builder(
71        ContentSettingsPattern::CreateBuilder(false));
72    builder->WithHost(url_pattern.host());
73    if (url_pattern.match_subdomains())
74      builder->WithDomainWildcard();
75
76    std::string scheme = url_pattern.scheme();
77    if (scheme == "*")
78      builder->WithSchemeWildcard();
79    else
80      builder->WithScheme(scheme);
81
82    std::string port = url_pattern.port();
83    if (port.empty() && scheme != "file") {
84      if (scheme == "*")
85        port = "*";
86      else
87        port = GetDefaultPort(scheme);
88    }
89    if (port == "*")
90      builder->WithPortWildcard();
91    else
92      builder->WithPort(port);
93
94    std::string path = url_pattern.path();
95    if (scheme == "file") {
96      // For file URLs we allow only exact path matches.
97      if (path.find_first_of("*?") != std::string::npos) {
98        *error = kNoPathWildcardsError;
99        return ContentSettingsPattern();
100      } else {
101        builder->WithPath(path);
102      }
103    } else if (path != "/*") {
104      // For other URLs we allow only paths which match everything.
105      *error = kNoPathsError;
106      return ContentSettingsPattern();
107    }
108
109    ContentSettingsPattern pattern = builder->Build();
110    if (!pattern.IsValid())
111      *error = kInvalidPatternError;
112    return pattern;
113  }
114}
115
116ContentSettingsType StringToContentSettingsType(
117    const std::string& content_type) {
118  for (size_t type = 0; type < arraysize(kContentSettingsTypeNames); ++type) {
119    if (content_type == kContentSettingsTypeNames[type])
120      return static_cast<ContentSettingsType>(type);
121  }
122  return CONTENT_SETTINGS_TYPE_DEFAULT;
123}
124
125const char* ContentSettingsTypeToString(ContentSettingsType type) {
126  size_t index = static_cast<size_t>(type);
127  DCHECK_LT(index, arraysize(kContentSettingsTypeNames));
128  return kContentSettingsTypeNames[index];
129}
130
131bool StringToContentSetting(const std::string& setting_str,
132                            ContentSetting* setting) {
133  for (size_t type = 0; type < arraysize(kContentSettingNames); ++type) {
134    if (setting_str == kContentSettingNames[type]) {
135      *setting = static_cast<ContentSetting>(type);
136      return true;
137    }
138  }
139  return false;
140}
141
142const char* ContentSettingToString(ContentSetting setting) {
143  size_t index = static_cast<size_t>(setting);
144  DCHECK_LT(index, arraysize(kContentSettingNames));
145  return kContentSettingNames[index];
146}
147
148}  // namespace content_settings_helpers
149}  // namespace extensions
150