Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(522)

Side by Side Diff: components/content_settings/core/browser/content_settings_default_provider.cc

Issue 1004733003: Split the default content settings into syncable and nonsyncable. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Reset PMI, reacting to unsyncable pref changes as well. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/content_settings/core/browser/content_settings_default_prov ider.h" 5 #include "components/content_settings/core/browser/content_settings_default_prov ider.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/auto_reset.h" 10 #include "base/auto_reset.h"
11 #include "base/basictypes.h" 11 #include "base/basictypes.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/prefs/pref_service.h" 15 #include "base/prefs/pref_service.h"
16 #include "base/prefs/scoped_user_pref_update.h" 16 #include "base/prefs/scoped_user_pref_update.h"
17 #include "components/content_settings/core/browser/content_settings_rule.h" 17 #include "components/content_settings/core/browser/content_settings_rule.h"
18 #include "components/content_settings/core/browser/content_settings_utils.h" 18 #include "components/content_settings/core/browser/content_settings_utils.h"
19 #include "components/content_settings/core/common/content_settings.h" 19 #include "components/content_settings/core/common/content_settings.h"
20 #include "components/content_settings/core/common/content_settings_pattern.h" 20 #include "components/content_settings/core/common/content_settings_pattern.h"
21 #include "components/content_settings/core/common/pref_names.h" 21 #include "components/content_settings/core/common/pref_names.h"
22 #include "components/pref_registry/pref_registry_syncable.h" 22 #include "components/pref_registry/pref_registry_syncable.h"
23 #include "url/gurl.h" 23 #include "url/gurl.h"
24 24
25 namespace { 25 namespace {
26 26
27 // The default setting for each content type. 27 struct DefaultContentSettingInfo {
28 const ContentSetting kDefaultSettings[] = { 28 // The profile preference associated with this default setting.
29 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES 29 const char* pref_name;
30 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES 30
31 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT 31 // The default value of this default setting.
32 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS 32 const ContentSetting default_value;
33 CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS 33
34 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_GEOLOCATION 34 // Whether this preference should be synced.
35 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_NOTIFICATIONS 35 const bool syncable;
36 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE 36 };
37 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_FULLSCREEN 37
38 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MOUSELOCK 38 // The corresponding preference, default value and syncability for each
39 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_MIXEDSCRIPT 39 // default content setting. This array must be kept in sync with the enum
40 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM 40 // |ContentSettingsType|.
41 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC 41 const DefaultContentSettingInfo kDefaultSettings[] = {
42 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA 42 {prefs::kDefaultCookiesSetting, CONTENT_SETTING_ALLOW, true},
Bernhard Bauer 2015/03/26 10:12:34 Indent these lines by two spaces, and add a space
msramek 2015/03/27 16:17:46 Done.
43 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS 43 {prefs::kDefaultImagesSetting, CONTENT_SETTING_ALLOW, true},
44 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PPAPI_BROKER 44 {prefs::kDefaultJavaScriptSetting, CONTENT_SETTING_ALLOW, true},
45 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS 45 {prefs::kDefaultPluginsSetting, CONTENT_SETTING_ALLOW, true},
46 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_MIDI_SYSEX 46 {prefs::kDefaultPopupsSetting, CONTENT_SETTING_BLOCK, true},
47 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PUSH_MESSAGING 47 {prefs::kDefaultGeolocationSetting, CONTENT_SETTING_ASK, false},
48 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS 48 {prefs::kDefaultNotificationsSetting, CONTENT_SETTING_ASK, true},
49 {prefs::kDefaultAutoSelectCertificateSetting, CONTENT_SETTING_DEFAULT,
50 false},
51 {prefs::kDefaultFullScreenSetting, CONTENT_SETTING_ASK, true},
52 {prefs::kDefaultMouseLockSetting, CONTENT_SETTING_ASK, true},
53 {prefs::kDefaultMixedScriptSetting, CONTENT_SETTING_DEFAULT, true},
54 {prefs::kDefaultMediaStreamSetting, CONTENT_SETTING_ASK, false},
55 {prefs::kDefaultMediaStreamMicSetting, CONTENT_SETTING_ASK, false},
56 {prefs::kDefaultMediaStreamCameraSetting, CONTENT_SETTING_ASK, false},
57 {prefs::kDefaultProtocolHandlersSetting, CONTENT_SETTING_DEFAULT, true},
58 {prefs::kDefaultPpapiBrokerSetting, CONTENT_SETTING_ASK, false},
59 {prefs::kDefaultAutomaticDownloadsSetting, CONTENT_SETTING_ASK, true},
60 {prefs::kDefaultMidiSysexSetting, CONTENT_SETTING_ASK, true},
61 {prefs::kDefaultPushMessagingSetting, CONTENT_SETTING_ASK, true},
62 {prefs::kDefaultSSLCertDecisionsSetting, CONTENT_SETTING_ALLOW, false},
49 #if defined(OS_WIN) 63 #if defined(OS_WIN)
50 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP 64 {prefs::kDefaultMetroSwitchToDesktopSetting, CONTENT_SETTING_ASK, true},
51 #elif defined(OS_ANDROID) || defined(OS_CHROMEOS) 65 #elif defined(OS_ANDROID) || defined(OS_CHROMEOS)
52 CONTENT_SETTING_ASK, // CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER 66 {prefs::kDefaultProtectedMediaIdentifierSetting, CONTENT_SETTING_ASK,
67 false},
53 #endif 68 #endif
54 CONTENT_SETTING_DEFAULT, // CONTENT_SETTINGS_TYPE_APP_BANNER 69 {prefs::kDefaultAppBannerSetting, CONTENT_SETTING_DEFAULT, false}
55 }; 70 };
56 static_assert(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES, 71 static_assert(arraysize(kDefaultSettings) == CONTENT_SETTINGS_NUM_TYPES,
57 "kDefaultSettings should have CONTENT_SETTINGS_NUM_TYPES " 72 "kDefaultSettings should have CONTENT_SETTINGS_NUM_TYPES "
58 "elements"); 73 "elements");
59 74
60 } // namespace 75 } // namespace
61 76
62 namespace content_settings { 77 namespace content_settings {
63 78
64 namespace { 79 namespace {
(...skipping 27 matching lines...) Expand all
92 // also include the default values for default content settings. This allows 107 // also include the default values for default content settings. This allows
93 // functional tests to get default content settings by reading the preference 108 // functional tests to get default content settings by reading the preference
94 // prefs::kDefaultContentSettings via pyauto. 109 // prefs::kDefaultContentSettings via pyauto.
95 // TODO(markusheintz): Write pyauto hooks for the content settings map as 110 // TODO(markusheintz): Write pyauto hooks for the content settings map as
96 // content settings should be read from the host content settings map. 111 // content settings should be read from the host content settings map.
97 base::DictionaryValue* default_content_settings = new base::DictionaryValue(); 112 base::DictionaryValue* default_content_settings = new base::DictionaryValue();
98 registry->RegisterDictionaryPref( 113 registry->RegisterDictionaryPref(
99 prefs::kDefaultContentSettings, 114 prefs::kDefaultContentSettings,
100 default_content_settings, 115 default_content_settings,
101 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 116 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
117
118 // Register individual default setting preferences.
119 // TODO(msramek): The aggregate preference above is deprecated. Remove it
120 // after two stable releases.
121 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
Bernhard Bauer 2015/03/26 10:12:34 Use an int unless you really really need size_t.
msramek 2015/03/27 16:17:45 Ah. This is a leftover. I originally used size_t,
122 registry->RegisterIntegerPref(
123 kDefaultSettings[i].pref_name,
124 kDefaultSettings[i].default_value,
125 kDefaultSettings[i].syncable
126 ? user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
127 : user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
128 }
129
130 // Whether the deprecated dictionary preference has already been migrated
131 // into the individual preferences in this profile.
132 registry->RegisterBooleanPref(
133 prefs::kMigratedDefaultContentSettings,
134 false,
135 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
102 } 136 }
103 137
104 DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito) 138 DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito)
105 : prefs_(prefs), 139 : prefs_(prefs),
106 is_incognito_(incognito), 140 is_incognito_(incognito),
107 updating_preferences_(false) { 141 updating_preferences_(false) {
108 DCHECK(prefs_); 142 DCHECK(prefs_);
109 143
144 // Migrate the dictionary of default content settings to the new individual
145 // preferences.
146 MigrateDefaultSettings();
147
110 // Read global defaults. 148 // Read global defaults.
111 ReadDefaultSettings(true); 149 ReadDefaultSettings();
112 150
113 UMA_HISTOGRAM_ENUMERATION( 151 UMA_HISTOGRAM_ENUMERATION(
114 "ContentSettings.DefaultCookiesSetting", 152 "ContentSettings.DefaultCookiesSetting",
115 ValueToContentSetting( 153 IntToContentSetting(prefs_->GetInteger(
116 default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()), 154 kDefaultSettings[CONTENT_SETTINGS_TYPE_COOKIES].pref_name)),
117 CONTENT_SETTING_NUM_SETTINGS); 155 CONTENT_SETTING_NUM_SETTINGS);
118 UMA_HISTOGRAM_ENUMERATION( 156 UMA_HISTOGRAM_ENUMERATION(
119 "ContentSettings.DefaultImagesSetting", 157 "ContentSettings.DefaultImagesSetting",
120 ValueToContentSetting( 158 IntToContentSetting(prefs_->GetInteger(
121 default_settings_[CONTENT_SETTINGS_TYPE_IMAGES].get()), 159 kDefaultSettings[CONTENT_SETTINGS_TYPE_IMAGES].pref_name)),
122 CONTENT_SETTING_NUM_SETTINGS); 160 CONTENT_SETTING_NUM_SETTINGS);
123 UMA_HISTOGRAM_ENUMERATION( 161 UMA_HISTOGRAM_ENUMERATION(
124 "ContentSettings.DefaultJavaScriptSetting", 162 "ContentSettings.DefaultJavaScriptSetting",
125 ValueToContentSetting( 163 IntToContentSetting(prefs_->GetInteger(
126 default_settings_[CONTENT_SETTINGS_TYPE_JAVASCRIPT].get()), 164 kDefaultSettings[CONTENT_SETTINGS_TYPE_JAVASCRIPT].pref_name)),
127 CONTENT_SETTING_NUM_SETTINGS); 165 CONTENT_SETTING_NUM_SETTINGS);
128 UMA_HISTOGRAM_ENUMERATION( 166 UMA_HISTOGRAM_ENUMERATION(
129 "ContentSettings.DefaultPluginsSetting", 167 "ContentSettings.DefaultPluginsSetting",
130 ValueToContentSetting( 168 IntToContentSetting(prefs_->GetInteger(
131 default_settings_[CONTENT_SETTINGS_TYPE_PLUGINS].get()), 169 kDefaultSettings[CONTENT_SETTINGS_TYPE_PLUGINS].pref_name)),
132 CONTENT_SETTING_NUM_SETTINGS); 170 CONTENT_SETTING_NUM_SETTINGS);
133 UMA_HISTOGRAM_ENUMERATION( 171 UMA_HISTOGRAM_ENUMERATION(
134 "ContentSettings.DefaultPopupsSetting", 172 "ContentSettings.DefaultPopupsSetting",
135 ValueToContentSetting( 173 IntToContentSetting(prefs_->GetInteger(
136 default_settings_[CONTENT_SETTINGS_TYPE_POPUPS].get()), 174 kDefaultSettings[CONTENT_SETTINGS_TYPE_POPUPS].pref_name)),
137 CONTENT_SETTING_NUM_SETTINGS); 175 CONTENT_SETTING_NUM_SETTINGS);
138 UMA_HISTOGRAM_ENUMERATION( 176 UMA_HISTOGRAM_ENUMERATION(
139 "ContentSettings.DefaultLocationSetting", 177 "ContentSettings.DefaultLocationSetting",
140 ValueToContentSetting( 178 IntToContentSetting(prefs_->GetInteger(
141 default_settings_[CONTENT_SETTINGS_TYPE_GEOLOCATION].get()), 179 kDefaultSettings[CONTENT_SETTINGS_TYPE_GEOLOCATION].pref_name)),
142 CONTENT_SETTING_NUM_SETTINGS); 180 CONTENT_SETTING_NUM_SETTINGS);
143 UMA_HISTOGRAM_ENUMERATION( 181 UMA_HISTOGRAM_ENUMERATION(
144 "ContentSettings.DefaultNotificationsSetting", 182 "ContentSettings.DefaultNotificationsSetting",
145 ValueToContentSetting( 183 IntToContentSetting(prefs_->GetInteger(
146 default_settings_[CONTENT_SETTINGS_TYPE_NOTIFICATIONS].get()), 184 kDefaultSettings[CONTENT_SETTINGS_TYPE_NOTIFICATIONS].pref_name)),
147 CONTENT_SETTING_NUM_SETTINGS); 185 CONTENT_SETTING_NUM_SETTINGS);
148 UMA_HISTOGRAM_ENUMERATION( 186 UMA_HISTOGRAM_ENUMERATION(
149 "ContentSettings.DefaultMouseCursorSetting", 187 "ContentSettings.DefaultMouseCursorSetting",
150 ValueToContentSetting( 188 IntToContentSetting(prefs_->GetInteger(
151 default_settings_[CONTENT_SETTINGS_TYPE_MOUSELOCK].get()), 189 kDefaultSettings[CONTENT_SETTINGS_TYPE_MOUSELOCK].pref_name)),
152 CONTENT_SETTING_NUM_SETTINGS); 190 CONTENT_SETTING_NUM_SETTINGS);
153 UMA_HISTOGRAM_ENUMERATION( 191 UMA_HISTOGRAM_ENUMERATION(
154 "ContentSettings.DefaultMediaStreamSetting", 192 "ContentSettings.DefaultMediaStreamSetting",
155 ValueToContentSetting( 193 IntToContentSetting(prefs_->GetInteger(
156 default_settings_[CONTENT_SETTINGS_TYPE_MEDIASTREAM].get()), 194 kDefaultSettings[CONTENT_SETTINGS_TYPE_MEDIASTREAM].pref_name)),
157 CONTENT_SETTING_NUM_SETTINGS); 195 CONTENT_SETTING_NUM_SETTINGS);
158 UMA_HISTOGRAM_ENUMERATION( 196 UMA_HISTOGRAM_ENUMERATION(
159 "ContentSettings.DefaultMIDISysExSetting", 197 "ContentSettings.DefaultMIDISysExSetting",
160 ValueToContentSetting( 198 IntToContentSetting(prefs_->GetInteger(
161 default_settings_[CONTENT_SETTINGS_TYPE_MIDI_SYSEX].get()), 199 kDefaultSettings[CONTENT_SETTINGS_TYPE_MIDI_SYSEX].pref_name)),
162 CONTENT_SETTING_NUM_SETTINGS); 200 CONTENT_SETTING_NUM_SETTINGS);
163 UMA_HISTOGRAM_ENUMERATION( 201 UMA_HISTOGRAM_ENUMERATION(
164 "ContentSettings.DefaultPushMessagingSetting", 202 "ContentSettings.DefaultPushMessagingSetting",
165 ValueToContentSetting( 203 IntToContentSetting(prefs_->GetInteger(
166 default_settings_[CONTENT_SETTINGS_TYPE_PUSH_MESSAGING].get()), 204 kDefaultSettings[CONTENT_SETTINGS_TYPE_PUSH_MESSAGING].pref_name)),
167 CONTENT_SETTING_NUM_SETTINGS); 205 CONTENT_SETTING_NUM_SETTINGS);
168 206
169 pref_change_registrar_.Init(prefs_); 207 pref_change_registrar_.Init(prefs_);
170 PrefChangeRegistrar::NamedChangeCallback callback = base::Bind( 208 PrefChangeRegistrar::NamedChangeCallback callback = base::Bind(
171 &DefaultProvider::OnPreferenceChanged, base::Unretained(this)); 209 &DefaultProvider::OnPreferenceChanged, base::Unretained(this));
172 pref_change_registrar_.Add(prefs::kDefaultContentSettings, callback); 210 pref_change_registrar_.Add(prefs::kDefaultContentSettings, callback);
211
212 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
213 pref_change_registrar_.Add(kDefaultSettings[i].pref_name, callback);
173 } 214 }
174 215
175 DefaultProvider::~DefaultProvider() { 216 DefaultProvider::~DefaultProvider() {
176 } 217 }
177 218
178 bool DefaultProvider::SetWebsiteSetting( 219 bool DefaultProvider::SetWebsiteSetting(
179 const ContentSettingsPattern& primary_pattern, 220 const ContentSettingsPattern& primary_pattern,
180 const ContentSettingsPattern& secondary_pattern, 221 const ContentSettingsPattern& secondary_pattern,
181 ContentSettingsType content_type, 222 ContentSettingsType content_type,
182 const ResourceIdentifier& resource_identifier, 223 const ResourceIdentifier& resource_identifier,
(...skipping 10 matching lines...) Expand all
193 // The default settings may not be directly modified for OTR sessions. 234 // The default settings may not be directly modified for OTR sessions.
194 // Instead, they are synced to the main profile's setting. 235 // Instead, they are synced to the main profile's setting.
195 if (is_incognito_) 236 if (is_incognito_)
196 return false; 237 return false;
197 238
198 // Put |in_value| in a scoped pointer to ensure that it gets cleaned up 239 // Put |in_value| in a scoped pointer to ensure that it gets cleaned up
199 // properly if we don't pass on the ownership. 240 // properly if we don't pass on the ownership.
200 scoped_ptr<base::Value> value(in_value); 241 scoped_ptr<base::Value> value(in_value);
201 { 242 {
202 base::AutoReset<bool> auto_reset(&updating_preferences_, true); 243 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
244 base::AutoLock lock(lock_);
203 245
204 // |DefaultProvider| should not send any notifications when holding 246 ChangeSetting(content_type, value.get());
205 // |lock_|. |DictionaryPrefUpdate| destructor and 247 WriteIndividualPref(content_type, value.get());
206 // |PrefService::SetInteger()| send out notifications. As a response, the
207 // upper layers may call |GetAllContentSettingRules| which acquires |lock_|
208 // again.
209 DictionaryPrefUpdate update(prefs_, prefs::kDefaultContentSettings);
210 base::DictionaryValue* default_settings_dictionary = update.Get();
211 base::AutoLock lock(lock_);
212 if (value.get() == NULL ||
213 ValueToContentSetting(value.get()) == kDefaultSettings[content_type]) {
214 // If |value| is NULL we need to reset the default setting the the
215 // hardcoded default.
216 default_settings_[content_type].reset(
217 new base::FundamentalValue(kDefaultSettings[content_type]));
218 248
219 // Remove the corresponding pref entry since the hardcoded default value 249 // If the changed setting is syncable, write it to the old dictionary
220 // is used. 250 // preference as well, so it can be synced to older versions of Chrome.
221 default_settings_dictionary->RemoveWithoutPathExpansion( 251 // TODO(msramek): Remove this after two stable releases.
222 GetTypeName(content_type), NULL); 252 if (kDefaultSettings[content_type].syncable)
223 } else { 253 WriteDictionaryPref(content_type, value.get());
224 default_settings_[content_type].reset(value->DeepCopy());
225 // Transfer ownership of |value| to the |default_settings_dictionary|.
226 default_settings_dictionary->SetWithoutPathExpansion(
227 GetTypeName(content_type), value.release());
228 }
229 } 254 }
230 255
231 NotifyObservers(ContentSettingsPattern(), 256 NotifyObservers(ContentSettingsPattern(),
232 ContentSettingsPattern(), 257 ContentSettingsPattern(),
233 content_type, 258 content_type,
234 std::string()); 259 std::string());
235 260
236 return true; 261 return true;
237 } 262 }
238 263
(...skipping 21 matching lines...) Expand all
260 } 285 }
261 286
262 void DefaultProvider::ShutdownOnUIThread() { 287 void DefaultProvider::ShutdownOnUIThread() {
263 DCHECK(CalledOnValidThread()); 288 DCHECK(CalledOnValidThread());
264 DCHECK(prefs_); 289 DCHECK(prefs_);
265 RemoveAllObservers(); 290 RemoveAllObservers();
266 pref_change_registrar_.RemoveAll(); 291 pref_change_registrar_.RemoveAll();
267 prefs_ = NULL; 292 prefs_ = NULL;
268 } 293 }
269 294
295 void DefaultProvider::ReadDefaultSettings() {
296 base::AutoLock lock(lock_);
297 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
298 ContentSettingsType content_type = ContentSettingsType(i);
299 ChangeSetting(content_type, ReadIndividualPref(content_type).get());
300 }
301 }
302
303 bool DefaultProvider::IsValueEmptyOrDefault(ContentSettingsType content_type,
304 base::Value* value) {
305 return (value == NULL ||
Bernhard Bauer 2015/03/26 10:12:34 Use nullptr, or just `!value` (which would also be
msramek 2015/03/27 16:17:45 Done.
306 ValueToContentSetting(value)
307 == kDefaultSettings[content_type].default_value);
308 }
309
310 void DefaultProvider::ChangeSetting(ContentSettingsType content_type,
311 base::Value* value) {
312 if (!value) {
313 default_settings_[content_type].reset(
314 kDefaultSettings[content_type].default_value != CONTENT_SETTING_DEFAULT
315 ? new base::FundamentalValue(
316 kDefaultSettings[content_type].default_value)
317 : NULL);
318 } else {
319 default_settings_[content_type].reset(value->DeepCopy());
320 }
321 }
322
323 void DefaultProvider::WriteIndividualPref(ContentSettingsType content_type,
324 base::Value* value) {
325 if (IsValueEmptyOrDefault(content_type, value)) {
326 prefs_->ClearPref(kDefaultSettings[content_type].pref_name);
327 return;
328 }
329
330 int int_value = kDefaultSettings[content_type].default_value;
331 bool is_integer = value->GetAsInteger(&int_value);
332 DCHECK(is_integer);
333 prefs_->SetInteger(kDefaultSettings[content_type].pref_name, int_value);
334 }
335
336 void DefaultProvider::WriteDictionaryPref(ContentSettingsType content_type,
337 base::Value* value) {
338 // |DefaultProvider| should not send any notifications when holding
339 // |lock_|. |DictionaryPrefUpdate| destructor and
340 // |PrefService::SetInteger()| send out notifications. As a response, the
341 // upper layers may call |GetAllContentSettingRules| which acquires |lock_|
342 // again.
343 DictionaryPrefUpdate update(prefs_, prefs::kDefaultContentSettings);
344 base::DictionaryValue* default_settings_dictionary = update.Get();
345
346 if (IsValueEmptyOrDefault(content_type, value)) {
347 default_settings_dictionary->RemoveWithoutPathExpansion(
348 GetTypeName(content_type), NULL);
349 return;
350 }
351
352 default_settings_dictionary->SetWithoutPathExpansion(
353 GetTypeName(content_type), value->DeepCopy());
354 }
355
270 void DefaultProvider::OnPreferenceChanged(const std::string& name) { 356 void DefaultProvider::OnPreferenceChanged(const std::string& name) {
271 DCHECK(CalledOnValidThread()); 357 DCHECK(CalledOnValidThread());
272 if (updating_preferences_) 358 if (updating_preferences_)
273 return; 359 return;
274 360
361 // Write the changed setting from individual preferences to dictionary,
362 // or vice versa - depending on which of them changed.
363 // TODO(msramek): This is only necessary in the phase of migration between
364 // the old dictionary preference and the new individual preferences. Remove
365 // this after two stable releases.
366 std::vector<ContentSettingsType> to_notify;
367
275 if (name == prefs::kDefaultContentSettings) { 368 if (name == prefs::kDefaultContentSettings) {
276 ReadDefaultSettings(true); 369 // If the dictionary preference gets synced from an old version
370 // of Chrome, we should update all individual preferences that
371 // are marked as syncable.
372 base::AutoLock lock(lock_);
373 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
374
375 scoped_ptr<ValueMap> dictionary = ReadDictionaryPref();
376
377 for (ValueMap::iterator it = dictionary->begin();
Bernhard Bauer 2015/03/26 10:12:34 Use a C++11-style loop?
msramek 2015/03/27 16:17:45 Done.
378 it != dictionary->end(); ++it) {
379 if (!kDefaultSettings[it->first].syncable)
380 continue;
381
382 DCHECK(default_settings_.find(it->first) != default_settings_.end());
383 ChangeSetting(it->first, it->second.get());
384 WriteIndividualPref(it->first, it->second.get());
385 to_notify.push_back(it->first);
386 }
277 } else { 387 } else {
278 NOTREACHED() << "Unexpected preference observed"; 388 // Find out which content setting the preference corresponds to.
279 return; 389 ContentSettingsType content_type = CONTENT_SETTINGS_TYPE_DEFAULT;
390
391 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
392 if (kDefaultSettings[i].pref_name == name) {
393 content_type = ContentSettingsType(i);
394 break;
395 }
396 }
397
398 if (content_type == CONTENT_SETTINGS_TYPE_DEFAULT) {
399 NOTREACHED() << "Unexpected preference observed";
400 return;
401 }
402
403 // A new individual preference is changed. If it is syncable, we should
404 // change its entry in the dictionary preference as well, so that it
405 // can be synced to older versions of Chrome.
406 base::AutoLock lock(lock_);
407 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
408
409 ChangeSetting(content_type, ReadIndividualPref(content_type).get());
410 if (kDefaultSettings[content_type].syncable)
411 WriteDictionaryPref(content_type, default_settings_[content_type].get());
412 to_notify.push_back(content_type);
280 } 413 }
281 414
282 NotifyObservers(ContentSettingsPattern(), 415 for (size_t i = 0; i < to_notify.size(); ++i) {
283 ContentSettingsPattern(), 416 NotifyObservers(ContentSettingsPattern(),
284 CONTENT_SETTINGS_TYPE_DEFAULT, 417 ContentSettingsPattern(),
285 std::string()); 418 to_notify[i],
419 std::string());
420 }
286 } 421 }
287 422
288 void DefaultProvider::ReadDefaultSettings(bool overwrite) { 423 scoped_ptr<base::Value> DefaultProvider::ReadIndividualPref(
289 base::AutoLock lock(lock_); 424 ContentSettingsType content_type) {
425 int int_value = prefs_->GetInteger(kDefaultSettings[content_type].pref_name);
426
427 if (int_value == CONTENT_SETTING_DEFAULT)
428 return make_scoped_ptr((base::Value*)NULL);
Bernhard Bauer 2015/03/26 10:12:35 Use nullptr; that might even allow you to get rid
msramek 2015/03/27 16:17:45 Done. Cast is necessary here even with nullptr. A
429 else
430 return make_scoped_ptr(new base::FundamentalValue(int_value));
431 }
432
433 scoped_ptr<DefaultProvider::ValueMap> DefaultProvider::ReadDictionaryPref() {
290 const base::DictionaryValue* default_settings_dictionary = 434 const base::DictionaryValue* default_settings_dictionary =
291 prefs_->GetDictionary(prefs::kDefaultContentSettings); 435 prefs_->GetDictionary(prefs::kDefaultContentSettings);
292 436
293 if (overwrite) 437 scoped_ptr<ValueMap> value_map =
294 default_settings_.clear(); 438 GetSettingsFromDictionary(default_settings_dictionary);
295 439
296 // Careful: The returned value could be NULL if the pref has never been set. 440 ForceDefaultsToBeExplicit(value_map.get());
297 if (default_settings_dictionary) 441 return value_map.Pass();
298 GetSettingsFromDictionary(default_settings_dictionary);
299
300 ForceDefaultsToBeExplicit();
301 } 442 }
302 443
303 void DefaultProvider::ForceDefaultsToBeExplicit() { 444 void DefaultProvider::ForceDefaultsToBeExplicit(ValueMap* value_map) {
304 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { 445 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
305 ContentSettingsType type = ContentSettingsType(i); 446 ContentSettingsType type = ContentSettingsType(i);
306 if (!default_settings_[type].get() && 447 if (!(*value_map)[type].get() &&
307 kDefaultSettings[i] != CONTENT_SETTING_DEFAULT) { 448 kDefaultSettings[i].default_value != CONTENT_SETTING_DEFAULT) {
308 default_settings_[type].reset( 449 (*value_map)[type].reset(
309 new base::FundamentalValue(kDefaultSettings[i])); 450 new base::FundamentalValue(kDefaultSettings[i].default_value));
310 } 451 }
311 } 452 }
312 } 453 }
313 454
314 void DefaultProvider::GetSettingsFromDictionary( 455 scoped_ptr<DefaultProvider::ValueMap>
315 const base::DictionaryValue* dictionary) { 456 DefaultProvider::GetSettingsFromDictionary(
457 const base::DictionaryValue* dictionary) {
458 if (!dictionary)
459 return make_scoped_ptr(new ValueMap());
460 ValueMap* value_map = new ValueMap();
Bernhard Bauer 2015/03/26 10:12:34 Put this into a scoped_ptr, and return it immediat
msramek 2015/03/27 16:17:46 Done. I just found it more elegant to create the s
461
316 for (base::DictionaryValue::Iterator i(*dictionary); 462 for (base::DictionaryValue::Iterator i(*dictionary);
317 !i.IsAtEnd(); i.Advance()) { 463 !i.IsAtEnd(); i.Advance()) {
318 const std::string& content_type(i.key()); 464 const std::string& content_type(i.key());
319 for (size_t type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) { 465 for (size_t type = 0; type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
320 if (content_type == GetTypeName(ContentSettingsType(type))) { 466 if (content_type == GetTypeName(ContentSettingsType(type))) {
321 int int_value = CONTENT_SETTING_DEFAULT; 467 int int_value = CONTENT_SETTING_DEFAULT;
322 bool is_integer = i.value().GetAsInteger(&int_value); 468 bool is_integer = i.value().GetAsInteger(&int_value);
323 DCHECK(is_integer); 469 DCHECK(is_integer);
324 default_settings_[ContentSettingsType(type)].reset( 470 (*value_map)[ContentSettingsType(type)].reset(
325 new base::FundamentalValue(int_value)); 471 new base::FundamentalValue(int_value));
326 break; 472 break;
327 } 473 }
328 } 474 }
329 } 475 }
330 // Migrate obsolete cookie prompt mode. 476 // Migrate obsolete cookie prompt mode.
331 if (ValueToContentSetting( 477 if (ValueToContentSetting(
332 default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].get()) == 478 (*value_map)[CONTENT_SETTINGS_TYPE_COOKIES].get())
333 CONTENT_SETTING_ASK) { 479 == CONTENT_SETTING_ASK) {
334 default_settings_[CONTENT_SETTINGS_TYPE_COOKIES].reset( 480 (*value_map)[CONTENT_SETTINGS_TYPE_COOKIES].reset(
335 new base::FundamentalValue(CONTENT_SETTING_BLOCK)); 481 new base::FundamentalValue(CONTENT_SETTING_BLOCK));
336 } 482 }
483
484 return make_scoped_ptr(value_map);
485 }
486
487 void DefaultProvider::MigrateDefaultSettings() {
488 // Only do the migration once.
489 if (prefs_->GetBoolean(prefs::kMigratedDefaultContentSettings))
490 return;
491
492 scoped_ptr<DefaultProvider::ValueMap> value_map = ReadDictionaryPref();
493
494 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) {
495 ContentSettingsType content_type = ContentSettingsType(i);
496 WriteIndividualPref(content_type, (*value_map)[content_type].get());
497 }
498
499 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
500 // For protected media identifier, it is desirable to just reset the setting
501 // instead of migrating it from the old preference.
502 WriteIndividualPref(CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, NULL);
xhwang 2015/03/20 16:23:30 Thank you!
xhwang 2015/03/24 22:28:49 Just to double check. Will this only reset the "de
503 #endif
504
505 prefs_->SetBoolean(prefs::kMigratedDefaultContentSettings, true);
337 } 506 }
338 507
339 } // namespace content_settings 508 } // namespace content_settings
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698