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
22 namespace {
23
24 // The names of the ContentSettingsType values, for use with dictionary prefs.
25 const 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 #if defined(OS_WIN)
45 "metro-switch-to-desktop",
46 #elif defined(OS_ANDROID) || defined(OS_CHROMEOS)
47 "protected-media-identifier",
48 #endif
49 #if defined(OS_ANDROID)
50 "app-banner",
51 #endif
52 };
53 COMPILE_ASSERT(arraysize(kTypeNames) == CONTENT_SETTINGS_NUM_TYPES,
54 type_names_incorrect_size);
55
56 const char kPatternSeparator[] = ",";
57
58 } // namespace
59
60 namespace content_settings {
61
GetTypeName(ContentSettingsType type)62 std::string GetTypeName(ContentSettingsType type) {
63 return std::string(kTypeNames[type]);
64 }
65
CreatePatternString(const ContentSettingsPattern & item_pattern,const ContentSettingsPattern & top_level_frame_pattern)66 std::string CreatePatternString(
67 const ContentSettingsPattern& item_pattern,
68 const ContentSettingsPattern& top_level_frame_pattern) {
69 return item_pattern.ToString()
70 + std::string(kPatternSeparator)
71 + top_level_frame_pattern.ToString();
72 }
73
ParsePatternString(const std::string & pattern_str)74 PatternPair ParsePatternString(const std::string& pattern_str) {
75 std::vector<std::string> pattern_str_list;
76 base::SplitString(pattern_str, kPatternSeparator[0], &pattern_str_list);
77
78 // If the |pattern_str| is an empty string then the |pattern_string_list|
79 // contains a single empty string. In this case the empty string will be
80 // removed to signal an invalid |pattern_str|. Invalid pattern strings are
81 // handle by the "if"-statment below. So the order of the if statements here
82 // must be preserved.
83 if (pattern_str_list.size() == 1) {
84 if (pattern_str_list[0].empty()) {
85 pattern_str_list.pop_back();
86 } else {
87 pattern_str_list.push_back("*");
88 }
89 }
90
91 if (pattern_str_list.size() > 2 ||
92 pattern_str_list.size() == 0) {
93 return PatternPair(ContentSettingsPattern(),
94 ContentSettingsPattern());
95 }
96
97 PatternPair pattern_pair;
98 pattern_pair.first =
99 ContentSettingsPattern::FromString(pattern_str_list[0]);
100 pattern_pair.second =
101 ContentSettingsPattern::FromString(pattern_str_list[1]);
102 return pattern_pair;
103 }
104
ValueToContentSetting(const base::Value * value)105 ContentSetting ValueToContentSetting(const base::Value* value) {
106 ContentSetting setting = CONTENT_SETTING_DEFAULT;
107 bool valid = ParseContentSettingValue(value, &setting);
108 DCHECK(valid);
109 return setting;
110 }
111
ParseContentSettingValue(const base::Value * value,ContentSetting * setting)112 bool ParseContentSettingValue(const base::Value* value,
113 ContentSetting* setting) {
114 if (!value) {
115 *setting = CONTENT_SETTING_DEFAULT;
116 return true;
117 }
118 int int_value = -1;
119 if (!value->GetAsInteger(&int_value))
120 return false;
121 *setting = IntToContentSetting(int_value);
122 return *setting != CONTENT_SETTING_DEFAULT;
123 }
124
GetContentSettingValueAndPatterns(const ProviderInterface * provider,const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,bool include_incognito,ContentSettingsPattern * primary_pattern,ContentSettingsPattern * secondary_pattern)125 base::Value* GetContentSettingValueAndPatterns(
126 const ProviderInterface* provider,
127 const GURL& primary_url,
128 const GURL& secondary_url,
129 ContentSettingsType content_type,
130 const std::string& resource_identifier,
131 bool include_incognito,
132 ContentSettingsPattern* primary_pattern,
133 ContentSettingsPattern* secondary_pattern) {
134 if (include_incognito) {
135 // Check incognito-only specific settings. It's essential that the
136 // |RuleIterator| gets out of scope before we get a rule iterator for the
137 // normal mode.
138 scoped_ptr<RuleIterator> incognito_rule_iterator(
139 provider->GetRuleIterator(content_type, resource_identifier, true));
140 base::Value* value = GetContentSettingValueAndPatterns(
141 incognito_rule_iterator.get(), primary_url, secondary_url,
142 primary_pattern, secondary_pattern);
143 if (value)
144 return value;
145 }
146 // No settings from the incognito; use the normal mode.
147 scoped_ptr<RuleIterator> rule_iterator(
148 provider->GetRuleIterator(content_type, resource_identifier, false));
149 return GetContentSettingValueAndPatterns(
150 rule_iterator.get(), primary_url, secondary_url,
151 primary_pattern, secondary_pattern);
152 }
153
GetContentSettingValueAndPatterns(RuleIterator * rule_iterator,const GURL & primary_url,const GURL & secondary_url,ContentSettingsPattern * primary_pattern,ContentSettingsPattern * secondary_pattern)154 base::Value* GetContentSettingValueAndPatterns(
155 RuleIterator* rule_iterator,
156 const GURL& primary_url,
157 const GURL& secondary_url,
158 ContentSettingsPattern* primary_pattern,
159 ContentSettingsPattern* secondary_pattern) {
160 while (rule_iterator->HasNext()) {
161 const Rule& rule = rule_iterator->Next();
162 if (rule.primary_pattern.Matches(primary_url) &&
163 rule.secondary_pattern.Matches(secondary_url)) {
164 if (primary_pattern)
165 *primary_pattern = rule.primary_pattern;
166 if (secondary_pattern)
167 *secondary_pattern = rule.secondary_pattern;
168 return rule.value.get()->DeepCopy();
169 }
170 }
171 return NULL;
172 }
173
GetContentSettingValue(const ProviderInterface * provider,const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,bool include_incognito)174 base::Value* GetContentSettingValue(const ProviderInterface* provider,
175 const GURL& primary_url,
176 const GURL& secondary_url,
177 ContentSettingsType content_type,
178 const std::string& resource_identifier,
179 bool include_incognito) {
180 return GetContentSettingValueAndPatterns(provider, primary_url, secondary_url,
181 content_type, resource_identifier,
182 include_incognito, NULL, NULL);
183 }
184
GetContentSetting(const ProviderInterface * provider,const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,bool include_incognito)185 ContentSetting GetContentSetting(const ProviderInterface* provider,
186 const GURL& primary_url,
187 const GURL& secondary_url,
188 ContentSettingsType content_type,
189 const std::string& resource_identifier,
190 bool include_incognito) {
191 scoped_ptr<base::Value> value(
192 GetContentSettingValue(provider, primary_url, secondary_url,
193 content_type, resource_identifier,
194 include_incognito));
195 return ValueToContentSetting(value.get());
196 }
197
GetRendererContentSettingRules(const HostContentSettingsMap * map,RendererContentSettingRules * rules)198 void GetRendererContentSettingRules(const HostContentSettingsMap* map,
199 RendererContentSettingRules* rules) {
200 map->GetSettingsForOneType(
201 CONTENT_SETTINGS_TYPE_IMAGES, std::string(), &(rules->image_rules));
202 map->GetSettingsForOneType(
203 CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string(), &(rules->script_rules));
204 }
205
206 } // namespace content_settings
207