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

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

Issue 1005303003: Split the aggregate dictionary of content settings exceptions into per-type dictionaries (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test fix. Created 5 years, 8 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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_pref.h" 5 #include "components/content_settings/core/browser/content_settings_pref.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/prefs/scoped_user_pref_update.h" 11 #include "base/prefs/scoped_user_pref_update.h"
12 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
13 #include "base/time/clock.h" 13 #include "base/time/clock.h"
14 #include "components/content_settings/core/browser/content_settings_rule.h" 14 #include "components/content_settings/core/browser/content_settings_rule.h"
15 #include "components/content_settings/core/browser/content_settings_utils.h" 15 #include "components/content_settings/core/browser/content_settings_utils.h"
16 #include "components/content_settings/core/browser/host_content_settings_map.h" 16 #include "components/content_settings/core/browser/host_content_settings_map.h"
17 #include "components/content_settings/core/common/content_settings.h" 17 #include "components/content_settings/core/common/content_settings.h"
18 #include "components/content_settings/core/common/content_settings_pattern.h" 18 #include "components/content_settings/core/common/content_settings_pattern.h"
19 #include "components/content_settings/core/common/pref_names.h" 19 #include "components/content_settings/core/common/pref_names.h"
20 #include "url/gurl.h" 20 #include "url/gurl.h"
21 21
22 namespace { 22 namespace {
23 23
24 typedef std::pair<std::string, std::string> StringPair; 24 const char kSettingPath[] = "setting";
25 25 const char kPerResourceIdentifierPrefName[] = "per_resource";
26 const char kPerPluginPrefName[] = "per_plugin"; 26 const char kPerPluginPrefName[] = "per_plugin";
27 const char kLastUsed[] = "last_used"; 27 const char kLastUsed[] = "last_used";
28 28
29 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type, 29 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type,
30 ContentSetting setting) { 30 ContentSetting setting) {
31 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && 31 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
32 setting == CONTENT_SETTING_ASK) { 32 setting == CONTENT_SETTING_ASK) {
33 return CONTENT_SETTING_BLOCK; 33 return CONTENT_SETTING_BLOCK;
34 } 34 }
35 return setting; 35 return setting;
36 } 36 }
37 37
38 // If the given content type supports resource identifiers in user preferences, 38 // If the given content type supports resource identifiers in user preferences,
39 // returns true and sets |pref_key| to the key in the content settings 39 // returns true and sets |pref_key| to the key in the content settings
40 // dictionary under which per-resource content settings are stored. 40 // dictionary under which per-resource content settings are stored.
41 // Otherwise, returns false. 41 // Otherwise, returns false.
42 bool GetResourceTypeName(ContentSettingsType content_type, 42 bool SupportsResourceIdentifiers(ContentSettingsType content_type) {
43 std::string* pref_key) { 43 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS;
44 if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS) {
45 *pref_key = kPerPluginPrefName;
46 return true;
47 }
48 return false;
49 } 44 }
50 45
51 } // namespace 46 } // namespace
52 47
53 namespace content_settings { 48 namespace content_settings {
54 49
55 ContentSettingsPref::ContentSettingsPref( 50 ContentSettingsPref::ContentSettingsPref(
51 ContentSettingsType content_type,
56 PrefService* prefs, 52 PrefService* prefs,
57 PrefChangeRegistrar* registrar, 53 PrefChangeRegistrar* registrar,
58 base::Clock* clock, 54 const char* pref_name,
59 bool incognito, 55 bool incognito,
56 bool* updating_old_preferences_flag,
60 NotifyObserversCallback notify_callback) 57 NotifyObserversCallback notify_callback)
61 : prefs_(prefs), 58 : content_type_(content_type),
62 clock_(clock), 59 prefs_(prefs),
63 registrar_(registrar), 60 registrar_(registrar),
61 pref_name_(pref_name),
64 is_incognito_(incognito), 62 is_incognito_(incognito),
65 updating_preferences_(false), 63 updating_preferences_(false),
64 updating_old_preferences_(updating_old_preferences_flag),
66 notify_callback_(notify_callback) { 65 notify_callback_(notify_callback) {
67 DCHECK(prefs_); 66 DCHECK(prefs_);
68 67
69 // Read content settings exceptions. 68 // If the migration hasn't happened yet, or if this content setting
70 ReadContentSettingsFromPref(); 69 // is syncable, the parent |PrefProvider| is going to copy the contents
70 // of the old preference to this new preference. There is no need
71 // to initialize this preference separately (in fact, in the case
72 // of migration, we would be writing the empty new preference back to the
73 // old one, erasing it).
74 if (prefs_->GetBoolean(prefs::kMigratedContentSettingsPatternPairs) &&
75 !IsContentSettingsTypeSyncable(content_type_)) {
76 ReadContentSettingsFromPrefAndWriteToOldPref();
77 }
71 78
72 registrar->Add( 79 registrar_->Add(
73 prefs::kContentSettingsPatternPairs, 80 pref_name_,
74 base::Bind(&ContentSettingsPref::OnContentSettingsPatternPairsChanged, 81 base::Bind(&ContentSettingsPref::OnPrefChanged, base::Unretained(this)));
75 base::Unretained(this)));
76 } 82 }
77 83
78 ContentSettingsPref::~ContentSettingsPref() { 84 ContentSettingsPref::~ContentSettingsPref() {
79 } 85 }
80 86
81 RuleIterator* ContentSettingsPref::GetRuleIterator( 87 RuleIterator* ContentSettingsPref::GetRuleIterator(
82 ContentSettingsType content_type,
83 const ResourceIdentifier& resource_identifier, 88 const ResourceIdentifier& resource_identifier,
84 bool incognito) const { 89 bool incognito) const {
85 if (incognito) 90 if (incognito)
86 return incognito_value_map_.GetRuleIterator(content_type, 91 return incognito_value_map_.GetRuleIterator(content_type_,
87 resource_identifier, 92 resource_identifier,
88 &lock_); 93 &lock_);
89 return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_); 94 return value_map_.GetRuleIterator(content_type_, resource_identifier, &lock_);
90 } 95 }
91 96
92 bool ContentSettingsPref::SetWebsiteSetting( 97 bool ContentSettingsPref::SetWebsiteSetting(
93 const ContentSettingsPattern& primary_pattern, 98 const ContentSettingsPattern& primary_pattern,
94 const ContentSettingsPattern& secondary_pattern, 99 const ContentSettingsPattern& secondary_pattern,
95 ContentSettingsType content_type,
96 const ResourceIdentifier& resource_identifier, 100 const ResourceIdentifier& resource_identifier,
97 base::Value* in_value) { 101 base::Value* in_value) {
98 DCHECK(thread_checker_.CalledOnValidThread()); 102 DCHECK(thread_checker_.CalledOnValidThread());
99 DCHECK(prefs_); 103 DCHECK(prefs_);
100 104 DCHECK(primary_pattern != ContentSettingsPattern::Wildcard() ||
101 // Default settings are set using a wildcard pattern for both 105 secondary_pattern != ContentSettingsPattern::Wildcard() ||
102 // |primary_pattern| and |secondary_pattern|. Don't store default settings in 106 !resource_identifier.empty());
103 // the |PrefProvider|. The |PrefProvider| handles settings for specific
104 // sites/origins defined by the |primary_pattern| and the |secondary_pattern|.
105 // Default settings are handled by the |DefaultProvider|.
106 if (primary_pattern == ContentSettingsPattern::Wildcard() &&
107 secondary_pattern == ContentSettingsPattern::Wildcard() &&
108 resource_identifier.empty()) {
109 return false;
110 }
111 107
112 // At this point take the ownership of the |in_value|. 108 // At this point take the ownership of the |in_value|.
113 scoped_ptr<base::Value> value(in_value); 109 scoped_ptr<base::Value> value(in_value);
110
114 // Update in memory value map. 111 // Update in memory value map.
115 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; 112 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_;
116 if (!is_incognito_) 113 if (!is_incognito_)
117 map_to_modify = &value_map_; 114 map_to_modify = &value_map_;
118 115
119 { 116 {
120 base::AutoLock auto_lock(lock_); 117 base::AutoLock auto_lock(lock_);
121 if (value.get()) { 118 if (value.get()) {
122 map_to_modify->SetValue( 119 map_to_modify->SetValue(
123 primary_pattern, 120 primary_pattern,
124 secondary_pattern, 121 secondary_pattern,
125 content_type, 122 content_type_,
126 resource_identifier, 123 resource_identifier,
127 value->DeepCopy()); 124 value->DeepCopy());
128 } else { 125 } else {
129 map_to_modify->DeleteValue( 126 map_to_modify->DeleteValue(
130 primary_pattern, 127 primary_pattern,
131 secondary_pattern, 128 secondary_pattern,
132 content_type, 129 content_type_,
133 resource_identifier); 130 resource_identifier);
134 } 131 }
135 } 132 }
136 // Update the content settings preference. 133 // Update the content settings preference.
137 if (!is_incognito_) { 134 if (!is_incognito_) {
138 UpdatePref(primary_pattern, 135 UpdatePref(primary_pattern,
139 secondary_pattern, 136 secondary_pattern,
140 content_type,
141 resource_identifier, 137 resource_identifier,
142 value.get()); 138 value.get());
139 if (IsContentSettingsTypeSyncable(content_type_)) {
140 UpdateOldPref(primary_pattern,
141 secondary_pattern,
142 resource_identifier,
143 value.get());
144 }
143 } 145 }
144 146
145 notify_callback_.Run( 147 notify_callback_.Run(
146 primary_pattern, secondary_pattern, content_type, resource_identifier); 148 primary_pattern, secondary_pattern, content_type_, resource_identifier);
147 149
148 return true; 150 return true;
149 } 151 }
150 152
151 void ContentSettingsPref::ClearAllContentSettingsRules( 153 void ContentSettingsPref::ClearAllContentSettingsRules() {
152 ContentSettingsType content_type) {
153 DCHECK(thread_checker_.CalledOnValidThread()); 154 DCHECK(thread_checker_.CalledOnValidThread());
154 DCHECK(prefs_); 155 DCHECK(prefs_);
155 156
156 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; 157 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_;
157 if (!is_incognito_) 158 if (!is_incognito_)
158 map_to_modify = &value_map_; 159 map_to_modify = &value_map_;
159 160
160 std::vector<Rule> rules_to_delete; 161 std::vector<Rule> rules_to_delete;
161 { 162 {
162 base::AutoLock auto_lock(lock_); 163 base::AutoLock auto_lock(lock_);
163 scoped_ptr<RuleIterator> rule_iterator( 164 scoped_ptr<RuleIterator> rule_iterator(
164 map_to_modify->GetRuleIterator(content_type, std::string(), NULL)); 165 map_to_modify->GetRuleIterator(content_type_, std::string(), NULL));
165 // Copy the rules; we cannot call |UpdatePref| while holding |lock_|. 166 // Copy the rules; we cannot call |UpdatePref| while holding |lock_|.
166 while (rule_iterator->HasNext()) 167 while (rule_iterator->HasNext())
167 rules_to_delete.push_back(rule_iterator->Next()); 168 rules_to_delete.push_back(rule_iterator->Next());
168 169
169 map_to_modify->DeleteValues(content_type, std::string()); 170 map_to_modify->DeleteValues(content_type_, std::string());
170 } 171 }
171 172
172 for (std::vector<Rule>::const_iterator it = rules_to_delete.begin(); 173 for (std::vector<Rule>::const_iterator it = rules_to_delete.begin();
173 it != rules_to_delete.end(); ++it) { 174 it != rules_to_delete.end(); ++it) {
174 UpdatePref(it->primary_pattern, 175 UpdatePref(it->primary_pattern,
175 it->secondary_pattern, 176 it->secondary_pattern,
176 content_type,
177 std::string(), 177 std::string(),
178 NULL); 178 NULL);
179 if (IsContentSettingsTypeSyncable(content_type_)) {
180 UpdateOldPref(it->primary_pattern,
181 it->secondary_pattern,
182 std::string(),
183 NULL);
184 }
179 } 185 }
180 notify_callback_.Run(ContentSettingsPattern(), 186 notify_callback_.Run(ContentSettingsPattern(),
181 ContentSettingsPattern(), 187 ContentSettingsPattern(),
182 content_type, 188 content_type_,
183 std::string()); 189 std::string());
184 } 190 }
185 191
186 void ContentSettingsPref::UpdateLastUsage( 192 void ContentSettingsPref::UpdateLastUsage(
187 const ContentSettingsPattern& primary_pattern, 193 const ContentSettingsPattern& primary_pattern,
188 const ContentSettingsPattern& secondary_pattern, 194 const ContentSettingsPattern& secondary_pattern,
189 ContentSettingsType content_type) { 195 base::Clock* clock) {
190 // Don't write if in incognito. 196 // Don't write if in incognito.
191 if (is_incognito_) { 197 if (is_incognito_) {
192 return; 198 return;
193 } 199 }
194 200
195 // Ensure that |lock_| is not held by this thread, since this function will 201 // Ensure that |lock_| is not held by this thread, since this function will
196 // send out notifications (by |~DictionaryPrefUpdate|). 202 // send out notifications (by |~DictionaryPrefUpdate|).
197 AssertLockNotHeld(); 203 AssertLockNotHeld();
198 204
199 base::AutoReset<bool> auto_reset(&updating_preferences_, true); 205 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
200 { 206 {
201 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); 207 DictionaryPrefUpdate update(prefs_, pref_name_);
202 base::DictionaryValue* pattern_pairs_settings = update.Get(); 208 base::DictionaryValue* pattern_pairs_settings = update.Get();
203 209
204 std::string pattern_str( 210 std::string pattern_str(
205 CreatePatternString(primary_pattern, secondary_pattern)); 211 CreatePatternString(primary_pattern, secondary_pattern));
206 base::DictionaryValue* settings_dictionary = NULL; 212 base::DictionaryValue* settings_dictionary = NULL;
207 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( 213 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
208 pattern_str, &settings_dictionary); 214 pattern_str, &settings_dictionary);
209 215
210 if (!found) { 216 if (!found) {
211 settings_dictionary = new base::DictionaryValue; 217 settings_dictionary = new base::DictionaryValue;
212 pattern_pairs_settings->SetWithoutPathExpansion(pattern_str, 218 pattern_pairs_settings->SetWithoutPathExpansion(pattern_str,
213 settings_dictionary); 219 settings_dictionary);
214 } 220 }
215 221
216 base::DictionaryValue* last_used_dictionary = NULL; 222 settings_dictionary->SetWithoutPathExpansion(
217 found = settings_dictionary->GetDictionaryWithoutPathExpansion( 223 kLastUsed, new base::FundamentalValue(clock->Now().ToDoubleT()));
218 kLastUsed, &last_used_dictionary);
219
220 if (!found) {
221 last_used_dictionary = new base::DictionaryValue;
222 settings_dictionary->SetWithoutPathExpansion(kLastUsed,
223 last_used_dictionary);
224 }
225
226 std::string settings_path = GetTypeName(content_type);
227 last_used_dictionary->Set(
228 settings_path, new base::FundamentalValue(clock_->Now().ToDoubleT()));
229 } 224 }
230 } 225 }
231 226
232 base::Time ContentSettingsPref::GetLastUsage( 227 base::Time ContentSettingsPref::GetLastUsage(
233 const ContentSettingsPattern& primary_pattern, 228 const ContentSettingsPattern& primary_pattern,
234 const ContentSettingsPattern& secondary_pattern, 229 const ContentSettingsPattern& secondary_pattern) {
235 ContentSettingsType content_type) {
236 const base::DictionaryValue* pattern_pairs_settings = 230 const base::DictionaryValue* pattern_pairs_settings =
237 prefs_->GetDictionary(prefs::kContentSettingsPatternPairs); 231 prefs_->GetDictionary(pref_name_);
238 std::string pattern_str( 232 std::string pattern_str(
239 CreatePatternString(primary_pattern, secondary_pattern)); 233 CreatePatternString(primary_pattern, secondary_pattern));
240 234
241 const base::DictionaryValue* settings_dictionary = NULL; 235 const base::DictionaryValue* settings_dictionary = NULL;
242 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( 236 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
243 pattern_str, &settings_dictionary); 237 pattern_str, &settings_dictionary);
244 238
245 if (!found) 239 if (!found)
246 return base::Time(); 240 return base::Time();
247 241
248 const base::DictionaryValue* last_used_dictionary = NULL;
249 found = settings_dictionary->GetDictionaryWithoutPathExpansion(
250 kLastUsed, &last_used_dictionary);
251
252 if (!found)
253 return base::Time();
254
255 double last_used_time; 242 double last_used_time;
256 found = last_used_dictionary->GetDoubleWithoutPathExpansion( 243 found = settings_dictionary->GetDoubleWithoutPathExpansion(
257 GetTypeName(content_type), &last_used_time); 244 kLastUsed, &last_used_time);
258 245
259 if (!found) 246 if (!found)
260 return base::Time(); 247 return base::Time();
261 248
262 return base::Time::FromDoubleT(last_used_time); 249 return base::Time::FromDoubleT(last_used_time);
263 } 250 }
264 251
265 size_t ContentSettingsPref::GetNumExceptions() { 252 size_t ContentSettingsPref::GetNumExceptions() {
266 return value_map_.size(); 253 return value_map_.size();
267 } 254 }
268 255
269 void ContentSettingsPref::SetClockForTesting(base::Clock* clock) { 256 void ContentSettingsPref::ReadContentSettingsFromPrefAndWriteToOldPref() {
270 clock_ = clock;
271 }
272
273 void ContentSettingsPref::ReadContentSettingsFromPref() {
274 // |DictionaryPrefUpdate| sends out notifications when destructed. This 257 // |DictionaryPrefUpdate| sends out notifications when destructed. This
275 // construction order ensures |AutoLock| gets destroyed first and |lock_| is 258 // construction order ensures |AutoLock| gets destroyed first and |lock_| is
276 // not held when the notifications are sent. Also, |auto_reset| must be still 259 // not held when the notifications are sent. Also, |auto_reset| must be still
277 // valid when the notifications are sent, so that |Observe| skips the 260 // valid when the notifications are sent, so that |Observe| skips the
278 // notification. 261 // notification.
279 base::AutoReset<bool> auto_reset(&updating_preferences_, true); 262 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
280 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); 263 DictionaryPrefUpdate update(prefs_, pref_name_);
281 base::AutoLock auto_lock(lock_); 264 base::AutoLock auto_lock(lock_);
282 265
283 const base::DictionaryValue* all_settings_dictionary = 266 const base::DictionaryValue* all_settings_dictionary =
284 prefs_->GetDictionary(prefs::kContentSettingsPatternPairs); 267 prefs_->GetDictionary(pref_name_);
285 268
286 value_map_.clear(); 269 value_map_.clear();
287 270
271 // Clear the old preference, so we can copy the exceptions from the new
272 // preference into it. Note that copying in this direction is disallowed
273 // in incognito, to avoid the echo effect: New preference -> PrefProvider ->
274 // Old preference -> Incognito PrefProvider -> New preference -> etc.
275 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_))
276 ClearOldPreference();
277
288 // Careful: The returned value could be NULL if the pref has never been set. 278 // Careful: The returned value could be NULL if the pref has never been set.
289 if (!all_settings_dictionary) 279 if (!all_settings_dictionary)
290 return; 280 return;
291 281
292 base::DictionaryValue* mutable_settings; 282 base::DictionaryValue* mutable_settings;
293 scoped_ptr<base::DictionaryValue> mutable_settings_scope; 283 scoped_ptr<base::DictionaryValue> mutable_settings_scope;
294 284
295 if (!is_incognito_) { 285 if (!is_incognito_) {
296 mutable_settings = update.Get(); 286 mutable_settings = update.Get();
297 } else { 287 } else {
(...skipping 18 matching lines...) Expand all
316 LOG(ERROR) << "Invalid pattern strings: " << pattern_str; 306 LOG(ERROR) << "Invalid pattern strings: " << pattern_str;
317 continue; 307 continue;
318 } 308 }
319 309
320 // Get settings dictionary for the current pattern string, and read 310 // Get settings dictionary for the current pattern string, and read
321 // settings from the dictionary. 311 // settings from the dictionary.
322 const base::DictionaryValue* settings_dictionary = NULL; 312 const base::DictionaryValue* settings_dictionary = NULL;
323 bool is_dictionary = i.value().GetAsDictionary(&settings_dictionary); 313 bool is_dictionary = i.value().GetAsDictionary(&settings_dictionary);
324 DCHECK(is_dictionary); 314 DCHECK(is_dictionary);
325 315
326 for (size_t i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { 316 if (SupportsResourceIdentifiers(content_type_)) {
327 ContentSettingsType content_type = static_cast<ContentSettingsType>(i); 317 const base::DictionaryValue* resource_dictionary = NULL;
328 318 if (settings_dictionary->GetDictionary(
329 std::string res_dictionary_path; 319 kPerResourceIdentifierPrefName, &resource_dictionary)) {
330 if (GetResourceTypeName(content_type, &res_dictionary_path)) { 320 for (base::DictionaryValue::Iterator j(*resource_dictionary);
331 const base::DictionaryValue* resource_dictionary = NULL; 321 !j.IsAtEnd();
332 if (settings_dictionary->GetDictionary( 322 j.Advance()) {
333 res_dictionary_path, &resource_dictionary)) { 323 const std::string& resource_identifier(j.key());
334 for (base::DictionaryValue::Iterator j(*resource_dictionary); 324 int setting = CONTENT_SETTING_DEFAULT;
335 !j.IsAtEnd(); 325 bool is_integer = j.value().GetAsInteger(&setting);
336 j.Advance()) { 326 DCHECK(is_integer);
337 const std::string& resource_identifier(j.key());
338 int setting = CONTENT_SETTING_DEFAULT;
339 bool is_integer = j.value().GetAsInteger(&setting);
340 DCHECK(is_integer);
341 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
342 value_map_.SetValue(pattern_pair.first,
343 pattern_pair.second,
344 content_type,
345 resource_identifier,
346 new base::FundamentalValue(setting));
347 }
348 }
349 }
350 base::Value* value = NULL;
351 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type)) {
352 const base::DictionaryValue* setting = NULL;
353 // TODO(xians): Handle the non-dictionary types.
354 if (settings_dictionary->GetDictionaryWithoutPathExpansion(
355 GetTypeName(ContentSettingsType(i)), &setting)) {
356 DCHECK(!setting->empty());
357 value = setting->DeepCopy();
358 }
359 } else {
360 int setting = CONTENT_SETTING_DEFAULT;
361 if (settings_dictionary->GetIntegerWithoutPathExpansion(
362 GetTypeName(ContentSettingsType(i)), &setting)) {
363 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); 327 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
364 setting = FixObsoleteCookiePromptMode(content_type, 328 scoped_ptr<base::Value> setting_ptr(
365 ContentSetting(setting)); 329 new base::FundamentalValue(setting));
366 value = new base::FundamentalValue(setting); 330 value_map_.SetValue(pattern_pair.first,
367 } 331 pattern_pair.second,
368 } 332 content_type_,
369 333 resource_identifier,
370 // |value_map_| will take the ownership of |value|. 334 setting_ptr->DeepCopy());
371 if (value != NULL) { 335 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) {
372 value_map_.SetValue(pattern_pair.first, 336 UpdateOldPref(pattern_pair.first,
373 pattern_pair.second, 337 pattern_pair.second,
374 content_type, 338 resource_identifier,
375 ResourceIdentifier(), 339 setting_ptr.get());
raymes 2015/04/02 00:22:09 I think you might want setting_ptr.release() here
msramek 2015/04/02 16:22:55 UpdateOldPref() doesn't take ownership though. So
376 value);
377 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) {
378 ContentSetting s = ValueToContentSetting(value);
379 switch (s) {
380 case CONTENT_SETTING_ALLOW :
381 ++cookies_allow_exception_count;
382 break;
383 case CONTENT_SETTING_BLOCK :
384 ++cookies_block_exception_count;
385 break;
386 case CONTENT_SETTING_SESSION_ONLY :
387 ++cookies_session_only_exception_count;
388 break;
389 default:
390 NOTREACHED();
391 break;
392 } 340 }
393 } 341 }
394 } 342 }
395 } 343 }
344 base::Value* value = NULL;
345 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type_)) {
346 const base::DictionaryValue* setting = NULL;
347 // TODO(xians): Handle the non-dictionary types.
348 if (settings_dictionary->GetDictionaryWithoutPathExpansion(
349 kSettingPath, &setting)) {
350 DCHECK(!setting->empty());
351 value = setting->DeepCopy();
352 }
353 } else {
354 int setting = CONTENT_SETTING_DEFAULT;
355 if (settings_dictionary->GetIntegerWithoutPathExpansion(
356 kSettingPath, &setting)) {
357 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
358 setting = FixObsoleteCookiePromptMode(content_type_,
359 ContentSetting(setting));
360 value = new base::FundamentalValue(setting);
361 }
362 }
363
364 if (value != NULL) {
365 scoped_ptr<base::Value> value_ptr(value);
366 value_map_.SetValue(pattern_pair.first,
367 pattern_pair.second,
368 content_type_,
369 ResourceIdentifier(),
370 value->DeepCopy());
371 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) {
372 UpdateOldPref(pattern_pair.first,
373 pattern_pair.second,
374 ResourceIdentifier(),
375 value_ptr.get());
376 }
377 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) {
378 ContentSetting s = ValueToContentSetting(value);
379 switch (s) {
380 case CONTENT_SETTING_ALLOW :
381 ++cookies_allow_exception_count;
382 break;
383 case CONTENT_SETTING_BLOCK :
384 ++cookies_block_exception_count;
385 break;
386 case CONTENT_SETTING_SESSION_ONLY :
387 ++cookies_session_only_exception_count;
388 break;
389 default:
390 NOTREACHED();
391 break;
392 }
393 }
394 }
395
396 } 396 }
397 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfBlockCookiesExceptions", 397
398 cookies_block_exception_count); 398 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) {
399 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfAllowCookiesExceptions", 399 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfBlockCookiesExceptions",
400 cookies_allow_exception_count); 400 cookies_block_exception_count);
401 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfSessionOnlyCookiesExceptions", 401 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfAllowCookiesExceptions",
402 cookies_session_only_exception_count); 402 cookies_allow_exception_count);
403 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfSessionOnlyCookiesExceptions",
404 cookies_session_only_exception_count);
405 }
403 } 406 }
404 407
405 void ContentSettingsPref::OnContentSettingsPatternPairsChanged() { 408 void ContentSettingsPref::OnPrefChanged() {
406 DCHECK(thread_checker_.CalledOnValidThread()); 409 DCHECK(thread_checker_.CalledOnValidThread());
407 410
408 if (updating_preferences_) 411 if (updating_preferences_)
409 return; 412 return;
410 413
411 ReadContentSettingsFromPref(); 414 ReadContentSettingsFromPrefAndWriteToOldPref();
412 415
413 notify_callback_.Run(ContentSettingsPattern(), 416 notify_callback_.Run(ContentSettingsPattern(),
414 ContentSettingsPattern(), 417 ContentSettingsPattern(),
415 CONTENT_SETTINGS_TYPE_DEFAULT, 418 content_type_,
416 std::string()); 419 std::string());
417 } 420 }
418 421
419 void ContentSettingsPref::UpdatePref( 422 void ContentSettingsPref::UpdatePref(
420 const ContentSettingsPattern& primary_pattern, 423 const ContentSettingsPattern& primary_pattern,
421 const ContentSettingsPattern& secondary_pattern, 424 const ContentSettingsPattern& secondary_pattern,
422 ContentSettingsType content_type,
423 const ResourceIdentifier& resource_identifier, 425 const ResourceIdentifier& resource_identifier,
424 const base::Value* value) { 426 const base::Value* value) {
425 // Ensure that |lock_| is not held by this thread, since this function will 427 // Ensure that |lock_| is not held by this thread, since this function will
426 // send out notifications (by |~DictionaryPrefUpdate|). 428 // send out notifications (by |~DictionaryPrefUpdate|).
427 AssertLockNotHeld(); 429 AssertLockNotHeld();
428 430
429 base::AutoReset<bool> auto_reset(&updating_preferences_, true); 431 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
430 { 432 {
433 DictionaryPrefUpdate update(prefs_, pref_name_);
434 base::DictionaryValue* pattern_pairs_settings = update.Get();
435
436 // Get settings dictionary for the given patterns.
437 std::string pattern_str(CreatePatternString(primary_pattern,
438 secondary_pattern));
439 base::DictionaryValue* settings_dictionary = NULL;
440 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
441 pattern_str, &settings_dictionary);
442
443 if (!found && value) {
444 settings_dictionary = new base::DictionaryValue;
445 pattern_pairs_settings->SetWithoutPathExpansion(
446 pattern_str, settings_dictionary);
447 }
448
449 if (settings_dictionary) {
450 if (SupportsResourceIdentifiers(content_type_) &&
451 !resource_identifier.empty()) {
452 base::DictionaryValue* resource_dictionary = NULL;
453 found = settings_dictionary->GetDictionary(
454 kPerResourceIdentifierPrefName, &resource_dictionary);
455 if (!found) {
456 if (value == NULL)
457 return; // Nothing to remove. Exit early.
458 resource_dictionary = new base::DictionaryValue;
459 settings_dictionary->Set(
460 kPerResourceIdentifierPrefName, resource_dictionary);
461 }
462 // Update resource dictionary.
463 if (value == NULL) {
464 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
465 NULL);
466 if (resource_dictionary->empty()) {
467 settings_dictionary->RemoveWithoutPathExpansion(
468 kPerResourceIdentifierPrefName, NULL);
469 }
470 } else {
471 resource_dictionary->SetWithoutPathExpansion(
472 resource_identifier, value->DeepCopy());
473 }
474 } else {
475 // Update settings dictionary.
476 if (value == NULL) {
477 settings_dictionary->RemoveWithoutPathExpansion(kSettingPath, NULL);
478 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL);
479 } else {
480 settings_dictionary->SetWithoutPathExpansion(
481 kSettingPath, value->DeepCopy());
482 }
483 }
484 // Remove the settings dictionary if it is empty.
485 if (settings_dictionary->empty()) {
486 pattern_pairs_settings->RemoveWithoutPathExpansion(
487 pattern_str, NULL);
488 }
489 }
490 }
491 }
492
493 void ContentSettingsPref::UpdateOldPref(
494 const ContentSettingsPattern& primary_pattern,
495 const ContentSettingsPattern& secondary_pattern,
496 const ResourceIdentifier& resource_identifier,
497 const base::Value* value) {
498 DCHECK(IsContentSettingsTypeSyncable(content_type_));
499
500 // The incognito provider cannot write the settings to avoid echo effect:
501 // New preference -> PrefProvider -> Old preference ->
502 // -> Incognito PrefProvider -> New preference -> etc.
503 DCHECK(!is_incognito_);
504
505 if (*updating_old_preferences_)
506 return;
507
508 base::AutoReset<bool> auto_reset(updating_old_preferences_, true);
509 {
431 DictionaryPrefUpdate update(prefs_, 510 DictionaryPrefUpdate update(prefs_,
432 prefs::kContentSettingsPatternPairs); 511 prefs::kContentSettingsPatternPairs);
433 base::DictionaryValue* pattern_pairs_settings = update.Get(); 512 base::DictionaryValue* pattern_pairs_settings = update.Get();
434 513
435 // Get settings dictionary for the given patterns. 514 // Get settings dictionary for the given patterns.
436 std::string pattern_str(CreatePatternString(primary_pattern, 515 std::string pattern_str(CreatePatternString(primary_pattern,
437 secondary_pattern)); 516 secondary_pattern));
438 base::DictionaryValue* settings_dictionary = NULL; 517 base::DictionaryValue* settings_dictionary = NULL;
439 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( 518 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
440 pattern_str, &settings_dictionary); 519 pattern_str, &settings_dictionary);
441 520
442 if (!found && value) { 521 if (!found && value) {
443 settings_dictionary = new base::DictionaryValue; 522 settings_dictionary = new base::DictionaryValue;
444 pattern_pairs_settings->SetWithoutPathExpansion( 523 pattern_pairs_settings->SetWithoutPathExpansion(
445 pattern_str, settings_dictionary); 524 pattern_str, settings_dictionary);
446 } 525 }
447 526
448 if (settings_dictionary) { 527 if (settings_dictionary) {
449 std::string res_dictionary_path; 528 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS &&
450 if (GetResourceTypeName(content_type, &res_dictionary_path) &&
451 !resource_identifier.empty()) { 529 !resource_identifier.empty()) {
452 base::DictionaryValue* resource_dictionary = NULL; 530 base::DictionaryValue* resource_dictionary = NULL;
453 found = settings_dictionary->GetDictionary( 531 found = settings_dictionary->GetDictionary(
454 res_dictionary_path, &resource_dictionary); 532 kPerPluginPrefName, &resource_dictionary);
455 if (!found) { 533 if (!found) {
456 if (value == NULL) 534 if (value == NULL)
457 return; // Nothing to remove. Exit early. 535 return; // Nothing to remove. Exit early.
458 resource_dictionary = new base::DictionaryValue; 536 resource_dictionary = new base::DictionaryValue;
459 settings_dictionary->Set(res_dictionary_path, resource_dictionary); 537 settings_dictionary->Set(kPerPluginPrefName, resource_dictionary);
460 } 538 }
461 // Update resource dictionary. 539 // Update resource dictionary.
462 if (value == NULL) { 540 if (value == NULL) {
463 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier, 541 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
464 NULL); 542 NULL);
465 if (resource_dictionary->empty()) { 543 if (resource_dictionary->empty()) {
466 settings_dictionary->RemoveWithoutPathExpansion( 544 settings_dictionary->RemoveWithoutPathExpansion(
467 res_dictionary_path, NULL); 545 kPerPluginPrefName, NULL);
468 } 546 }
469 } else { 547 } else {
470 resource_dictionary->SetWithoutPathExpansion( 548 resource_dictionary->SetWithoutPathExpansion(
471 resource_identifier, value->DeepCopy()); 549 resource_identifier, value->DeepCopy());
472 } 550 }
473 } else { 551 } else {
474 // Update settings dictionary. 552 // Update settings dictionary.
475 std::string setting_path = GetTypeName(content_type); 553 std::string setting_path = GetTypeName(content_type_);
476 if (value == NULL) { 554 if (value == NULL) {
477 settings_dictionary->RemoveWithoutPathExpansion(setting_path, 555 settings_dictionary->RemoveWithoutPathExpansion(setting_path,
478 NULL); 556 NULL);
479 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL); 557 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL);
480 } else { 558 } else {
481 settings_dictionary->SetWithoutPathExpansion( 559 settings_dictionary->SetWithoutPathExpansion(
482 setting_path, value->DeepCopy()); 560 setting_path, value->DeepCopy());
483 } 561 }
484 } 562 }
485 // Remove the settings dictionary if it is empty. 563 // Remove the settings dictionary if it is empty.
486 if (settings_dictionary->empty()) { 564 if (settings_dictionary->empty()) {
487 pattern_pairs_settings->RemoveWithoutPathExpansion( 565 pattern_pairs_settings->RemoveWithoutPathExpansion(
488 pattern_str, NULL); 566 pattern_str, NULL);
489 } 567 }
490 } 568 }
491 } 569 }
492 } 570 }
493 571
572 void ContentSettingsPref::ClearOldPreference() {
573 DCHECK(IsContentSettingsTypeSyncable(content_type_));
574
575 if (*updating_old_preferences_)
576 return;
577
578 std::vector<std::string> keys;
579
580 base::AutoReset<bool> auto_reset(updating_old_preferences_, true);
581 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs);
582 base::DictionaryValue* old_dictionary = update.Get();
583
584 for (base::DictionaryValue::Iterator it(*old_dictionary);
585 !it.IsAtEnd(); it.Advance()) {
586 keys.push_back(it.key());
587 }
588
589 for (const std::string key : keys) {
raymes 2015/04/02 00:22:09 nit: can you use const std::string& key : keys?
msramek 2015/04/02 16:22:55 Done.
590 base::DictionaryValue* exception;
591 bool is_dictionary =
592 old_dictionary->GetDictionaryWithoutPathExpansion(key, &exception);
593 DCHECK(is_dictionary);
594
595 exception->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL);
596
597 base::DictionaryValue* last_used;
598 if (exception->GetDictionaryWithoutPathExpansion(kLastUsed, &last_used)) {
599 last_used->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL);
600
601 if (last_used->empty())
602 exception->RemoveWithoutPathExpansion(kLastUsed, NULL);
603 }
604
605 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS)
606 exception->RemoveWithoutPathExpansion(kPerPluginPrefName, NULL);
607
608 if (exception->empty())
609 old_dictionary->RemoveWithoutPathExpansion(key, NULL);
610 }
611
612 }
613
494 // static 614 // static
495 void ContentSettingsPref::CanonicalizeContentSettingsExceptions( 615 void ContentSettingsPref::CanonicalizeContentSettingsExceptions(
496 base::DictionaryValue* all_settings_dictionary) { 616 base::DictionaryValue* all_settings_dictionary) {
497 DCHECK(all_settings_dictionary); 617 DCHECK(all_settings_dictionary);
498 618
499 std::vector<std::string> remove_items; 619 std::vector<std::string> remove_items;
500 base::StringPairs move_items; 620 base::StringPairs move_items;
501 for (base::DictionaryValue::Iterator i(*all_settings_dictionary); 621 for (base::DictionaryValue::Iterator i(*all_settings_dictionary);
502 !i.IsAtEnd(); 622 !i.IsAtEnd();
503 i.Advance()) { 623 i.Advance()) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 669
550 void ContentSettingsPref::AssertLockNotHeld() const { 670 void ContentSettingsPref::AssertLockNotHeld() const {
551 #if !defined(NDEBUG) 671 #if !defined(NDEBUG)
552 // |Lock::Acquire()| will assert if the lock is held by this thread. 672 // |Lock::Acquire()| will assert if the lock is held by this thread.
553 lock_.Acquire(); 673 lock_.Acquire();
554 lock_.Release(); 674 lock_.Release();
555 #endif 675 #endif
556 } 676 }
557 677
558 } // namespace content_settings 678 } // namespace content_settings
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698