content_settings_utils.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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/content_settings/content_settings_utils.h"
6
7#include <vector>
8
9#include "base/command_line.h"
10#include "base/logging.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/memory/scoped_vector.h"
13#include "base/strings/string_split.h"
14#include "base/values.h"
15#include "chrome/browser/content_settings/content_settings_provider.h"
16#include "chrome/browser/content_settings/content_settings_rule.h"
17#include "chrome/browser/content_settings/host_content_settings_map.h"
18#include "chrome/common/chrome_switches.h"
19#include "chrome/common/content_settings_pattern.h"
20#include "url/gurl.h"
21
22namespace {
23
24// The names of the ContentSettingsType values, for use with dictionary prefs.
25const char* kTypeNames[] = {
26  "cookies",
27  "images",
28  "javascript",
29  "plugins",
30  "popups",
31  "geolocation",
32  "notifications",
33  "auto-select-certificate",
34  "fullscreen",
35  "mouselock",
36  "mixed-script",
37  "media-stream",
38  "media-stream-mic",
39  "media-stream-camera",
40  "register-protocol-handler",
41  "ppapi-broker",
42  "multiple-automatic-downloads",
43  "midi-sysex",
44  "push-messaging",
45  "ssl-cert-decisions",
46#if defined(OS_WIN)
47  "metro-switch-to-desktop",
48#elif defined(OS_ANDROID) || defined(OS_CHROMEOS)
49  "protected-media-identifier",
50#endif
51#if defined(OS_ANDROID)
52  "app-banner",
53#endif
54};
55COMPILE_ASSERT(arraysize(kTypeNames) == CONTENT_SETTINGS_NUM_TYPES,
56               type_names_incorrect_size);
57
58const char kPatternSeparator[] = ",";
59
60}  // namespace
61
62namespace content_settings {
63
64std::string GetTypeName(ContentSettingsType type) {
65  return std::string(kTypeNames[type]);
66}
67
68bool GetTypeFromName(const std::string& name,
69                     ContentSettingsType* return_setting) {
70  for (size_t type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
71    if (name.compare(kTypeNames[type]) == 0) {
72      *return_setting = static_cast<ContentSettingsType>(type);
73      return true;
74    }
75  }
76  return false;
77}
78
79std::string CreatePatternString(
80    const ContentSettingsPattern& item_pattern,
81    const ContentSettingsPattern& top_level_frame_pattern) {
82  return item_pattern.ToString()
83         + std::string(kPatternSeparator)
84         + top_level_frame_pattern.ToString();
85}
86
87PatternPair ParsePatternString(const std::string& pattern_str) {
88  std::vector<std::string> pattern_str_list;
89  base::SplitString(pattern_str, kPatternSeparator[0], &pattern_str_list);
90
91  // If the |pattern_str| is an empty string then the |pattern_string_list|
92  // contains a single empty string. In this case the empty string will be
93  // removed to signal an invalid |pattern_str|. Invalid pattern strings are
94  // handle by the "if"-statment below. So the order of the if statements here
95  // must be preserved.
96  if (pattern_str_list.size() == 1) {
97    if (pattern_str_list[0].empty()) {
98      pattern_str_list.pop_back();
99    } else {
100      pattern_str_list.push_back("*");
101    }
102  }
103
104  if (pattern_str_list.size() > 2 ||
105      pattern_str_list.size() == 0) {
106    return PatternPair(ContentSettingsPattern(),
107                       ContentSettingsPattern());
108  }
109
110  PatternPair pattern_pair;
111  pattern_pair.first =
112      ContentSettingsPattern::FromString(pattern_str_list[0]);
113  pattern_pair.second =
114      ContentSettingsPattern::FromString(pattern_str_list[1]);
115  return pattern_pair;
116}
117
118ContentSetting ValueToContentSetting(const base::Value* value) {
119  ContentSetting setting = CONTENT_SETTING_DEFAULT;
120  bool valid = ParseContentSettingValue(value, &setting);
121  DCHECK(valid);
122  return setting;
123}
124
125bool ParseContentSettingValue(const base::Value* value,
126                              ContentSetting* setting) {
127  if (!value) {
128    *setting = CONTENT_SETTING_DEFAULT;
129    return true;
130  }
131  int int_value = -1;
132  if (!value->GetAsInteger(&int_value))
133    return false;
134  *setting = IntToContentSetting(int_value);
135  return *setting != CONTENT_SETTING_DEFAULT;
136}
137
138base::Value* GetContentSettingValueAndPatterns(
139    const ProviderInterface* provider,
140    const GURL& primary_url,
141    const GURL& secondary_url,
142    ContentSettingsType content_type,
143    const std::string& resource_identifier,
144    bool include_incognito,
145    ContentSettingsPattern* primary_pattern,
146    ContentSettingsPattern* secondary_pattern) {
147  if (include_incognito) {
148    // Check incognito-only specific settings. It's essential that the
149    // |RuleIterator| gets out of scope before we get a rule iterator for the
150    // normal mode.
151    scoped_ptr<RuleIterator> incognito_rule_iterator(
152        provider->GetRuleIterator(content_type, resource_identifier, true));
153    base::Value* value = GetContentSettingValueAndPatterns(
154        incognito_rule_iterator.get(), primary_url, secondary_url,
155        primary_pattern, secondary_pattern);
156    if (value)
157      return value;
158  }
159  // No settings from the incognito; use the normal mode.
160  scoped_ptr<RuleIterator> rule_iterator(
161      provider->GetRuleIterator(content_type, resource_identifier, false));
162  return GetContentSettingValueAndPatterns(
163      rule_iterator.get(), primary_url, secondary_url,
164      primary_pattern, secondary_pattern);
165}
166
167base::Value* GetContentSettingValueAndPatterns(
168    RuleIterator* rule_iterator,
169    const GURL& primary_url,
170    const GURL& secondary_url,
171    ContentSettingsPattern* primary_pattern,
172    ContentSettingsPattern* secondary_pattern) {
173  while (rule_iterator->HasNext()) {
174    const Rule& rule = rule_iterator->Next();
175    if (rule.primary_pattern.Matches(primary_url) &&
176        rule.secondary_pattern.Matches(secondary_url)) {
177      if (primary_pattern)
178        *primary_pattern = rule.primary_pattern;
179      if (secondary_pattern)
180        *secondary_pattern = rule.secondary_pattern;
181      return rule.value.get()->DeepCopy();
182    }
183  }
184  return NULL;
185}
186
187base::Value* GetContentSettingValue(const ProviderInterface* provider,
188                                    const GURL& primary_url,
189                                    const GURL& secondary_url,
190                                    ContentSettingsType content_type,
191                                    const std::string& resource_identifier,
192                                    bool include_incognito) {
193  return GetContentSettingValueAndPatterns(provider, primary_url, secondary_url,
194                               content_type, resource_identifier,
195                               include_incognito, NULL, NULL);
196}
197
198ContentSetting GetContentSetting(const ProviderInterface* provider,
199                                 const GURL& primary_url,
200                                 const GURL& secondary_url,
201                                 ContentSettingsType content_type,
202                                 const std::string& resource_identifier,
203                                 bool include_incognito) {
204  scoped_ptr<base::Value> value(
205      GetContentSettingValue(provider, primary_url, secondary_url,
206                             content_type, resource_identifier,
207                             include_incognito));
208  return ValueToContentSetting(value.get());
209}
210
211void GetRendererContentSettingRules(const HostContentSettingsMap* map,
212                                    RendererContentSettingRules* rules) {
213  map->GetSettingsForOneType(
214      CONTENT_SETTINGS_TYPE_IMAGES, std::string(), &(rules->image_rules));
215  map->GetSettingsForOneType(
216      CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(), &(rules->script_rules));
217}
218
219}  // namespace content_settings
220