Update mojo surfaces bindings and mojo/cc/ glue
[chromium-blink-merge.git] / chrome / browser / content_settings / content_settings_default_provider.cc
blob143b2c52515a347e0aa90bf45dd9cafbd6d0640d
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.
5 #include "chrome/browser/content_settings/content_settings_default_provider.h"
7 #include <string>
8 #include <vector>
10 #include "base/auto_reset.h"
11 #include "base/basictypes.h"
12 #include "base/command_line.h"
13 #include "base/metrics/histogram.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/prefs/scoped_user_pref_update.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/content_settings/content_settings_rule.h"
18 #include "chrome/browser/content_settings/content_settings_utils.h"
19 #include "chrome/common/content_settings.h"
20 #include "chrome/common/content_settings_pattern.h"
21 #include "chrome/common/pref_names.h"
22 #include "components/pref_registry/pref_registry_syncable.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_source.h"
26 #include "content/public/browser/user_metrics.h"
27 #include "url/gurl.h"
29 using base::UserMetricsAction;
30 using content::BrowserThread;
32 namespace {
34 // The default setting for each content type.
35 const ContentSetting kDefaultSettings[] = {
36 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES
37 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES
38 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT
39 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS
40 CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS
41 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_GEOLOCATION
42 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_NOTIFICATIONS
43 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
44 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_FULLSCREEN
45 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MOUSELOCK
46 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
47 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM
48 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
49 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
50 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
51 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PPAPI_BROKER
52 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
53 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MIDI_SYSEX
54 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PUSH_MESSAGING
55 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS
56 #if defined(OS_WIN)
57 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP
58 #elif defined(OS_ANDROID) || defined(OS_CHROMEOS)
59 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
60 #endif
61 #if defined(OS_ANDROID)
62 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_APP_BANNER
63 #endif
65 COMPILE_ASSERT(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES,
66 default_settings_incorrect_size);
68 } // namespace
70 namespace content_settings {
72 namespace {
74 class DefaultRuleIterator : public RuleIterator {
75 public:
76 explicit DefaultRuleIterator(const base::Value* value) {
77 if (value)
78 value_.reset(value->DeepCopy());
81 virtual bool HasNext() const OVERRIDE {
82 return value_.get() != NULL;
85 virtual Rule Next() OVERRIDE {
86 DCHECK(value_.get());
87 return Rule(ContentSettingsPattern::Wildcard(),
88 ContentSettingsPattern::Wildcard(),
89 value_.release());
92 private:
93 scoped_ptr<base::Value> value_;
96 } // namespace
98 // static
99 void DefaultProvider::RegisterProfilePrefs(
100 user_prefs::PrefRegistrySyncable* registry) {
101 // The registration of the preference prefs::kDefaultContentSettings should
102 // also include the default values for default content settings. This allows
103 // functional tests to get default content settings by reading the preference
104 // prefs::kDefaultContentSettings via pyauto.
105 // TODO(markusheintz): Write pyauto hooks for the content settings map as
106 // content settings should be read from the host content settings map.
107 base::DictionaryValue* default_content_settings = new base::DictionaryValue();
108 registry->RegisterDictionaryPref(
109 prefs::kDefaultContentSettings,
110 default_content_settings,
111 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
114 DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito)
115 : prefs_(prefs),
116 is_incognito_(incognito),
117 updating_preferences_(false) {
118 DCHECK(prefs_);
120 // Read global defaults.
121 ReadDefaultSettings(true);
123 UMA_HISTOGRAM_ENUMERATION(
124 "ContentSettings.DefaultCookiesSetting",
125 ValueToContentSetting(
126 default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()),
127 CONTENT_SETTING_NUM_SETTINGS);
128 UMA_HISTOGRAM_ENUMERATION(
129 "ContentSettings.DefaultImagesSetting",
130 ValueToContentSetting(
131 default_settings_[CONTENT_SETTINGS_TYPE_IMAGES].get()),
132 CONTENT_SETTING_NUM_SETTINGS);
133 UMA_HISTOGRAM_ENUMERATION(
134 "ContentSettings.DefaultJavaScriptSetting",
135 ValueToContentSetting(
136 default_settings_[CONTENT_SETTINGS_TYPE_JAVASCRIPT].get()),
137 CONTENT_SETTING_NUM_SETTINGS);
138 UMA_HISTOGRAM_ENUMERATION(
139 "ContentSettings.DefaultPluginsSetting",
140 ValueToContentSetting(
141 default_settings_[CONTENT_SETTINGS_TYPE_PLUGINS].get()),
142 CONTENT_SETTING_NUM_SETTINGS);
143 UMA_HISTOGRAM_ENUMERATION(
144 "ContentSettings.DefaultPopupsSetting",
145 ValueToContentSetting(
146 default_settings_[CONTENT_SETTINGS_TYPE_POPUPS].get()),
147 CONTENT_SETTING_NUM_SETTINGS);
148 UMA_HISTOGRAM_ENUMERATION(
149 "ContentSettings.DefaultLocationSetting",
150 ValueToContentSetting(
151 default_settings_[CONTENT_SETTINGS_TYPE_GEOLOCATION].get()),
152 CONTENT_SETTING_NUM_SETTINGS);
153 UMA_HISTOGRAM_ENUMERATION(
154 "ContentSettings.DefaultNotificationsSetting",
155 ValueToContentSetting(
156 default_settings_[CONTENT_SETTINGS_TYPE_NOTIFICATIONS].get()),
157 CONTENT_SETTING_NUM_SETTINGS);
158 UMA_HISTOGRAM_ENUMERATION(
159 "ContentSettings.DefaultMouseCursorSetting",
160 ValueToContentSetting(
161 default_settings_[CONTENT_SETTINGS_TYPE_MOUSELOCK].get()),
162 CONTENT_SETTING_NUM_SETTINGS);
163 UMA_HISTOGRAM_ENUMERATION(
164 "ContentSettings.DefaultMediaStreamSetting",
165 ValueToContentSetting(
166 default_settings_[CONTENT_SETTINGS_TYPE_MEDIASTREAM].get()),
167 CONTENT_SETTING_NUM_SETTINGS);
168 UMA_HISTOGRAM_ENUMERATION(
169 "ContentSettings.DefaultMIDISysExSetting",
170 ValueToContentSetting(
171 default_settings_[CONTENT_SETTINGS_TYPE_MIDI_SYSEX].get()),
172 CONTENT_SETTING_NUM_SETTINGS);
173 UMA_HISTOGRAM_ENUMERATION(
174 "ContentSettings.DefaultPushMessagingSetting",
175 ValueToContentSetting(
176 default_settings_[CONTENT_SETTINGS_TYPE_PUSH_MESSAGING].get()),
177 CONTENT_SETTING_NUM_SETTINGS);
179 pref_change_registrar_.Init(prefs_);
180 PrefChangeRegistrar::NamedChangeCallback callback = base::Bind(
181 &DefaultProvider::OnPreferenceChanged, base::Unretained(this));
182 pref_change_registrar_.Add(prefs::kDefaultContentSettings, callback);
185 DefaultProvider::~DefaultProvider() {
188 bool DefaultProvider::SetWebsiteSetting(
189 const ContentSettingsPattern& primary_pattern,
190 const ContentSettingsPattern& secondary_pattern,
191 ContentSettingsType content_type,
192 const ResourceIdentifier& resource_identifier,
193 base::Value* in_value) {
194 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
195 DCHECK(prefs_);
197 // Ignore non default settings
198 if (primary_pattern != ContentSettingsPattern::Wildcard() ||
199 secondary_pattern != ContentSettingsPattern::Wildcard()) {
200 return false;
203 // The default settings may not be directly modified for OTR sessions.
204 // Instead, they are synced to the main profile's setting.
205 if (is_incognito_)
206 return false;
208 // Put |in_value| in a scoped pointer to ensure that it gets cleaned up
209 // properly if we don't pass on the ownership.
210 scoped_ptr<base::Value> value(in_value);
212 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
214 // |DefaultProvider| should not send any notifications when holding
215 // |lock_|. |DictionaryPrefUpdate| destructor and
216 // |PrefService::SetInteger()| send out notifications. As a response, the
217 // upper layers may call |GetAllContentSettingRules| which acquires |lock_|
218 // again.
219 DictionaryPrefUpdate update(prefs_, prefs::kDefaultContentSettings);
220 base::DictionaryValue* default_settings_dictionary = update.Get();
221 base::AutoLock lock(lock_);
222 if (value.get() == NULL ||
223 ValueToContentSetting(value.get()) == kDefaultSettings[content_type]) {
224 // If |value| is NULL we need to reset the default setting the the
225 // hardcoded default.
226 default_settings_[content_type].reset(
227 new base::FundamentalValue(kDefaultSettings[content_type]));
229 // Remove the corresponding pref entry since the hardcoded default value
230 // is used.
231 default_settings_dictionary->RemoveWithoutPathExpansion(
232 GetTypeName(content_type), NULL);
233 } else {
234 default_settings_[content_type].reset(value->DeepCopy());
235 // Transfer ownership of |value| to the |default_settings_dictionary|.
236 default_settings_dictionary->SetWithoutPathExpansion(
237 GetTypeName(content_type), value.release());
241 NotifyObservers(ContentSettingsPattern(),
242 ContentSettingsPattern(),
243 content_type,
244 std::string());
246 return true;
249 RuleIterator* DefaultProvider::GetRuleIterator(
250 ContentSettingsType content_type,
251 const ResourceIdentifier& resource_identifier,
252 bool incognito) const {
253 base::AutoLock lock(lock_);
254 if (resource_identifier.empty()) {
255 ValueMap::const_iterator it(default_settings_.find(content_type));
256 if (it != default_settings_.end()) {
257 return new DefaultRuleIterator(it->second.get());
259 NOTREACHED();
261 return new EmptyRuleIterator();
264 void DefaultProvider::ClearAllContentSettingsRules(
265 ContentSettingsType content_type) {
266 // TODO(markusheintz): This method is only called when the
267 // |DesktopNotificationService| calls |ClearAllSettingsForType| method on the
268 // |HostContentSettingsMap|. Don't implement this method yet, otherwise the
269 // default notification settings will be cleared as well.
272 void DefaultProvider::ShutdownOnUIThread() {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
274 DCHECK(prefs_);
275 RemoveAllObservers();
276 pref_change_registrar_.RemoveAll();
277 prefs_ = NULL;
280 void DefaultProvider::OnPreferenceChanged(const std::string& name) {
281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
282 if (updating_preferences_)
283 return;
285 if (name == prefs::kDefaultContentSettings) {
286 ReadDefaultSettings(true);
287 } else {
288 NOTREACHED() << "Unexpected preference observed";
289 return;
292 NotifyObservers(ContentSettingsPattern(),
293 ContentSettingsPattern(),
294 CONTENT_SETTINGS_TYPE_DEFAULT,
295 std::string());
298 void DefaultProvider::ReadDefaultSettings(bool overwrite) {
299 base::AutoLock lock(lock_);
300 const base::DictionaryValue* default_settings_dictionary =
301 prefs_->GetDictionary(prefs::kDefaultContentSettings);
303 if (overwrite)
304 default_settings_.clear();
306 // Careful: The returned value could be NULL if the pref has never been set.
307 if (default_settings_dictionary)
308 GetSettingsFromDictionary(default_settings_dictionary);
310 ForceDefaultsToBeExplicit();
313 void DefaultProvider::ForceDefaultsToBeExplicit() {
314 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
315 ContentSettingsType type = ContentSettingsType(i);
316 if (!default_settings_[type].get() &&
317 kDefaultSettings[i] != CONTENT_SETTING_DEFAULT) {
318 default_settings_[type].reset(
319 new base::FundamentalValue(kDefaultSettings[i]));
324 void DefaultProvider::GetSettingsFromDictionary(
325 const base::DictionaryValue* dictionary) {
326 for (base::DictionaryValue::Iterator i(*dictionary);
327 !i.IsAtEnd(); i.Advance()) {
328 const std::string& content_type(i.key());
329 for (size_t type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
330 if (content_type == GetTypeName(ContentSettingsType(type))) {
331 int int_value = CONTENT_SETTING_DEFAULT;
332 bool is_integer = i.value().GetAsInteger(&int_value);
333 DCHECK(is_integer);
334 default_settings_[ContentSettingsType(type)].reset(
335 new base::FundamentalValue(int_value));
336 break;
340 // Migrate obsolete cookie prompt mode.
341 if (ValueToContentSetting(
342 default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()) ==
343 CONTENT_SETTING_ASK) {
344 default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].reset(
345 new base::FundamentalValue(CONTENT_SETTING_BLOCK));
349 } // namespace content_settings