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

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

Issue 1257093002: Remove the migration code from content_settings::PrefProvider. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Lock testing function. Created 5 years, 4 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_macros.h" 10 #include "base/metrics/histogram_macros.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 const char kSettingPath[] = "setting"; 24 const char kSettingPath[] = "setting";
25 const char kPerResourceIdentifierPrefName[] = "per_resource"; 25 const char kPerResourceIdentifierPrefName[] = "per_resource";
26 const char kPerPluginPrefName[] = "per_plugin";
27 const char kLastUsed[] = "last_used"; 26 const char kLastUsed[] = "last_used";
28 27
29 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type, 28 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type,
30 ContentSetting setting) { 29 ContentSetting setting) {
31 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && 30 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
32 setting == CONTENT_SETTING_ASK) { 31 setting == CONTENT_SETTING_ASK) {
33 return CONTENT_SETTING_BLOCK; 32 return CONTENT_SETTING_BLOCK;
34 } 33 }
35 return setting; 34 return setting;
36 } 35 }
37 36
38 // If the given content type supports resource identifiers in user preferences, 37 // 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 38 // returns true and sets |pref_key| to the key in the content settings
40 // dictionary under which per-resource content settings are stored. 39 // dictionary under which per-resource content settings are stored.
41 // Otherwise, returns false. 40 // Otherwise, returns false.
42 bool SupportsResourceIdentifiers(ContentSettingsType content_type) { 41 bool SupportsResourceIdentifiers(ContentSettingsType content_type) {
43 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; 42 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS;
44 } 43 }
45 44
46 } // namespace 45 } // namespace
47 46
48 namespace content_settings { 47 namespace content_settings {
49 48
50 ContentSettingsPref::ContentSettingsPref( 49 ContentSettingsPref::ContentSettingsPref(
51 ContentSettingsType content_type, 50 ContentSettingsType content_type,
52 PrefService* prefs, 51 PrefService* prefs,
53 PrefChangeRegistrar* registrar, 52 PrefChangeRegistrar* registrar,
54 const char* pref_name, 53 const char* pref_name,
55 bool incognito, 54 bool incognito,
56 bool* updating_old_preferences_flag,
57 NotifyObserversCallback notify_callback) 55 NotifyObserversCallback notify_callback)
58 : content_type_(content_type), 56 : content_type_(content_type),
59 prefs_(prefs), 57 prefs_(prefs),
60 registrar_(registrar), 58 registrar_(registrar),
61 pref_name_(pref_name), 59 pref_name_(pref_name),
62 is_incognito_(incognito), 60 is_incognito_(incognito),
63 updating_preferences_(false), 61 updating_preferences_(false),
64 updating_old_preferences_(updating_old_preferences_flag),
65 notify_callback_(notify_callback) { 62 notify_callback_(notify_callback) {
66 DCHECK(prefs_); 63 DCHECK(prefs_);
67 64
68 // If the migration hasn't happened yet, or if this content setting 65 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). Since copying between preferences is disallowed
74 // in incognito, |ContentSettingsPref| needs to be initialized from the new
75 // preference in incognito as well.
76 if ((prefs_->GetBoolean(prefs::kMigratedContentSettingsPatternPairs) &&
77 !IsContentSettingsTypeSyncable(content_type_))
78 || is_incognito_) {
79 ReadContentSettingsFromPrefAndWriteToOldPref();
80 }
81 66
82 registrar_->Add( 67 registrar_->Add(
83 pref_name_, 68 pref_name_,
84 base::Bind(&ContentSettingsPref::OnPrefChanged, base::Unretained(this))); 69 base::Bind(&ContentSettingsPref::OnPrefChanged, base::Unretained(this)));
85 } 70 }
86 71
87 ContentSettingsPref::~ContentSettingsPref() { 72 ContentSettingsPref::~ContentSettingsPref() {
88 } 73 }
89 74
90 RuleIterator* ContentSettingsPref::GetRuleIterator( 75 RuleIterator* ContentSettingsPref::GetRuleIterator(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 content_type_, 117 content_type_,
133 resource_identifier); 118 resource_identifier);
134 } 119 }
135 } 120 }
136 // Update the content settings preference. 121 // Update the content settings preference.
137 if (!is_incognito_) { 122 if (!is_incognito_) {
138 UpdatePref(primary_pattern, 123 UpdatePref(primary_pattern,
139 secondary_pattern, 124 secondary_pattern,
140 resource_identifier, 125 resource_identifier,
141 value.get()); 126 value.get());
142 if (IsContentSettingsTypeSyncable(content_type_)) {
143 UpdateOldPref(primary_pattern,
144 secondary_pattern,
145 resource_identifier,
146 value.get());
147 }
148 } 127 }
149 128
150 notify_callback_.Run( 129 notify_callback_.Run(
151 primary_pattern, secondary_pattern, content_type_, resource_identifier); 130 primary_pattern, secondary_pattern, content_type_, resource_identifier);
152 131
153 return true; 132 return true;
154 } 133 }
155 134
156 void ContentSettingsPref::ClearAllContentSettingsRules() { 135 void ContentSettingsPref::ClearAllContentSettingsRules() {
157 DCHECK(thread_checker_.CalledOnValidThread()); 136 DCHECK(thread_checker_.CalledOnValidThread());
158 DCHECK(prefs_); 137 DCHECK(prefs_);
159 138
160 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; 139 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_;
161 if (!is_incognito_) 140 if (!is_incognito_)
162 map_to_modify = &value_map_; 141 map_to_modify = &value_map_;
163 142
164 { 143 {
165 base::AutoLock auto_lock(lock_); 144 base::AutoLock auto_lock(lock_);
166 map_to_modify->clear(); 145 map_to_modify->clear();
167 } 146 }
168 147
169 if (!is_incognito_) { 148 if (!is_incognito_) {
170 // Clear the new preference. 149 // Clear the preference.
171 { 150 {
172 base::AutoReset<bool> auto_reset(&updating_preferences_, true); 151 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
173 DictionaryPrefUpdate update(prefs_, pref_name_); 152 DictionaryPrefUpdate update(prefs_, pref_name_);
174 base::DictionaryValue* pattern_pairs_settings = update.Get(); 153 base::DictionaryValue* pattern_pairs_settings = update.Get();
175 pattern_pairs_settings->Clear(); 154 pattern_pairs_settings->Clear();
176 } 155 }
177
178 if (IsContentSettingsTypeSyncable(content_type_))
179 ClearOldPreference();
180 } 156 }
181 157
182 notify_callback_.Run(ContentSettingsPattern(), 158 notify_callback_.Run(ContentSettingsPattern(),
183 ContentSettingsPattern(), 159 ContentSettingsPattern(),
184 content_type_, 160 content_type_,
185 ResourceIdentifier()); 161 ResourceIdentifier());
186 } 162 }
187 163
188 void ContentSettingsPref::UpdateLastUsage( 164 void ContentSettingsPref::UpdateLastUsage(
189 const ContentSettingsPattern& primary_pattern, 165 const ContentSettingsPattern& primary_pattern,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 if (!found) 218 if (!found)
243 return base::Time(); 219 return base::Time();
244 220
245 return base::Time::FromDoubleT(last_used_time); 221 return base::Time::FromDoubleT(last_used_time);
246 } 222 }
247 223
248 size_t ContentSettingsPref::GetNumExceptions() { 224 size_t ContentSettingsPref::GetNumExceptions() {
249 return value_map_.size(); 225 return value_map_.size();
250 } 226 }
251 227
252 void ContentSettingsPref::ReadContentSettingsFromPrefAndWriteToOldPref() { 228 bool ContentSettingsPref::TryLockForTesting() const {
253 // Clear the old preference, so we can copy the exceptions from the new 229 if (!lock_.Try())
254 // preference into it. Note that copying in this direction is disallowed 230 return false;
255 // in incognito, to avoid the echo effect: New preference -> PrefProvider -> 231 lock_.Release();
256 // Old preference -> Incognito PrefProvider -> New preference -> etc. 232 return true;
257 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) 233 }
258 ClearOldPreference();
259 234
235 void ContentSettingsPref::ReadContentSettingsFromPref() {
260 // |DictionaryPrefUpdate| sends out notifications when destructed. This 236 // |DictionaryPrefUpdate| sends out notifications when destructed. This
261 // construction order ensures |AutoLock| gets destroyed first and |lock_| is 237 // construction order ensures |AutoLock| gets destroyed first and |lock_| is
262 // not held when the notifications are sent. Also, |auto_reset| must be still 238 // not held when the notifications are sent. Also, |auto_reset| must be still
263 // valid when the notifications are sent, so that |Observe| skips the 239 // valid when the notifications are sent, so that |Observe| skips the
264 // notification. 240 // notification.
265 base::AutoReset<bool> auto_reset(&updating_preferences_, true); 241 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
266 DictionaryPrefUpdate update(prefs_, pref_name_); 242 DictionaryPrefUpdate update(prefs_, pref_name_);
267 base::AutoLock auto_lock(lock_); 243 base::AutoLock auto_lock(lock_);
268 244
269 const base::DictionaryValue* all_settings_dictionary = 245 const base::DictionaryValue* all_settings_dictionary =
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 bool is_integer = j.value().GetAsInteger(&setting); 297 bool is_integer = j.value().GetAsInteger(&setting);
322 DCHECK(is_integer); 298 DCHECK(is_integer);
323 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); 299 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting);
324 scoped_ptr<base::Value> setting_ptr( 300 scoped_ptr<base::Value> setting_ptr(
325 new base::FundamentalValue(setting)); 301 new base::FundamentalValue(setting));
326 value_map_.SetValue(pattern_pair.first, 302 value_map_.SetValue(pattern_pair.first,
327 pattern_pair.second, 303 pattern_pair.second,
328 content_type_, 304 content_type_,
329 resource_identifier, 305 resource_identifier,
330 setting_ptr->DeepCopy()); 306 setting_ptr->DeepCopy());
331 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) {
332 UpdateOldPref(pattern_pair.first,
333 pattern_pair.second,
334 resource_identifier,
335 setting_ptr.get());
336 }
337 } 307 }
338 } 308 }
339 } 309 }
340 base::Value* value = NULL; 310 base::Value* value = NULL;
341 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type_)) { 311 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type_)) {
342 const base::DictionaryValue* setting = NULL; 312 const base::DictionaryValue* setting = NULL;
343 // TODO(xians): Handle the non-dictionary types. 313 // TODO(xians): Handle the non-dictionary types.
344 if (settings_dictionary->GetDictionaryWithoutPathExpansion( 314 if (settings_dictionary->GetDictionaryWithoutPathExpansion(
345 kSettingPath, &setting)) { 315 kSettingPath, &setting)) {
346 DCHECK(!setting->empty()); 316 DCHECK(!setting->empty());
(...skipping 10 matching lines...) Expand all
357 } 327 }
358 } 328 }
359 329
360 if (value != NULL) { 330 if (value != NULL) {
361 scoped_ptr<base::Value> value_ptr(value); 331 scoped_ptr<base::Value> value_ptr(value);
362 value_map_.SetValue(pattern_pair.first, 332 value_map_.SetValue(pattern_pair.first,
363 pattern_pair.second, 333 pattern_pair.second,
364 content_type_, 334 content_type_,
365 ResourceIdentifier(), 335 ResourceIdentifier(),
366 value->DeepCopy()); 336 value->DeepCopy());
367 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) {
368 UpdateOldPref(pattern_pair.first,
369 pattern_pair.second,
370 ResourceIdentifier(),
371 value_ptr.get());
372 }
373 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) { 337 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) {
374 ContentSetting s = ValueToContentSetting(value); 338 ContentSetting s = ValueToContentSetting(value);
375 switch (s) { 339 switch (s) {
376 case CONTENT_SETTING_ALLOW : 340 case CONTENT_SETTING_ALLOW :
377 ++cookies_allow_exception_count; 341 ++cookies_allow_exception_count;
378 break; 342 break;
379 case CONTENT_SETTING_BLOCK : 343 case CONTENT_SETTING_BLOCK :
380 ++cookies_block_exception_count; 344 ++cookies_block_exception_count;
381 break; 345 break;
382 case CONTENT_SETTING_SESSION_ONLY : 346 case CONTENT_SETTING_SESSION_ONLY :
(...skipping 17 matching lines...) Expand all
400 cookies_session_only_exception_count); 364 cookies_session_only_exception_count);
401 } 365 }
402 } 366 }
403 367
404 void ContentSettingsPref::OnPrefChanged() { 368 void ContentSettingsPref::OnPrefChanged() {
405 DCHECK(thread_checker_.CalledOnValidThread()); 369 DCHECK(thread_checker_.CalledOnValidThread());
406 370
407 if (updating_preferences_) 371 if (updating_preferences_)
408 return; 372 return;
409 373
410 ReadContentSettingsFromPrefAndWriteToOldPref(); 374 ReadContentSettingsFromPref();
411 375
412 notify_callback_.Run(ContentSettingsPattern(), 376 notify_callback_.Run(ContentSettingsPattern(),
413 ContentSettingsPattern(), 377 ContentSettingsPattern(),
414 content_type_, 378 content_type_,
415 ResourceIdentifier()); 379 ResourceIdentifier());
416 } 380 }
417 381
418 void ContentSettingsPref::UpdatePref( 382 void ContentSettingsPref::UpdatePref(
419 const ContentSettingsPattern& primary_pattern, 383 const ContentSettingsPattern& primary_pattern,
420 const ContentSettingsPattern& secondary_pattern, 384 const ContentSettingsPattern& secondary_pattern,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 } 443 }
480 // Remove the settings dictionary if it is empty. 444 // Remove the settings dictionary if it is empty.
481 if (settings_dictionary->empty()) { 445 if (settings_dictionary->empty()) {
482 pattern_pairs_settings->RemoveWithoutPathExpansion( 446 pattern_pairs_settings->RemoveWithoutPathExpansion(
483 pattern_str, NULL); 447 pattern_str, NULL);
484 } 448 }
485 } 449 }
486 } 450 }
487 } 451 }
488 452
489 void ContentSettingsPref::UpdateOldPref(
490 const ContentSettingsPattern& primary_pattern,
491 const ContentSettingsPattern& secondary_pattern,
492 const ResourceIdentifier& resource_identifier,
493 const base::Value* value) {
494 DCHECK(IsContentSettingsTypeSyncable(content_type_));
495
496 // The incognito provider cannot write the settings to avoid echo effect:
497 // New preference -> PrefProvider -> Old preference ->
498 // -> Incognito PrefProvider -> New preference -> etc.
499 DCHECK(!is_incognito_);
500
501 if (*updating_old_preferences_)
502 return;
503
504 base::AutoReset<bool> auto_reset(updating_old_preferences_, true);
505 {
506 DictionaryPrefUpdate update(prefs_,
507 prefs::kContentSettingsPatternPairs);
508 base::DictionaryValue* pattern_pairs_settings = update.Get();
509
510 // Get settings dictionary for the given patterns.
511 std::string pattern_str(CreatePatternString(primary_pattern,
512 secondary_pattern));
513 base::DictionaryValue* settings_dictionary = NULL;
514 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion(
515 pattern_str, &settings_dictionary);
516
517 if (!found && value) {
518 settings_dictionary = new base::DictionaryValue;
519 pattern_pairs_settings->SetWithoutPathExpansion(
520 pattern_str, settings_dictionary);
521 }
522
523 if (settings_dictionary) {
524 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS &&
525 !resource_identifier.empty()) {
526 base::DictionaryValue* resource_dictionary = NULL;
527 found = settings_dictionary->GetDictionary(
528 kPerPluginPrefName, &resource_dictionary);
529 if (!found) {
530 if (value == NULL)
531 return; // Nothing to remove. Exit early.
532 resource_dictionary = new base::DictionaryValue;
533 settings_dictionary->Set(kPerPluginPrefName, resource_dictionary);
534 }
535 // Update resource dictionary.
536 if (value == NULL) {
537 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier,
538 NULL);
539 if (resource_dictionary->empty()) {
540 settings_dictionary->RemoveWithoutPathExpansion(
541 kPerPluginPrefName, NULL);
542 }
543 } else {
544 resource_dictionary->SetWithoutPathExpansion(
545 resource_identifier, value->DeepCopy());
546 }
547 } else {
548 // Update settings dictionary.
549 std::string setting_path = GetTypeName(content_type_);
550 if (value == NULL) {
551 settings_dictionary->RemoveWithoutPathExpansion(setting_path,
552 NULL);
553 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL);
554 } else {
555 settings_dictionary->SetWithoutPathExpansion(
556 setting_path, value->DeepCopy());
557 }
558 }
559 // Remove the settings dictionary if it is empty.
560 if (settings_dictionary->empty()) {
561 pattern_pairs_settings->RemoveWithoutPathExpansion(
562 pattern_str, NULL);
563 }
564 }
565 }
566 }
567
568 void ContentSettingsPref::ClearOldPreference() {
569 DCHECK(IsContentSettingsTypeSyncable(content_type_));
570
571 if (*updating_old_preferences_)
572 return;
573
574 std::vector<std::string> keys;
575
576 base::AutoReset<bool> auto_reset(updating_old_preferences_, true);
577 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs);
578 base::DictionaryValue* old_dictionary = update.Get();
579
580 for (base::DictionaryValue::Iterator it(*old_dictionary);
581 !it.IsAtEnd(); it.Advance()) {
582 keys.push_back(it.key());
583 }
584
585 for (const std::string& key : keys) {
586 base::DictionaryValue* exception;
587 bool is_dictionary =
588 old_dictionary->GetDictionaryWithoutPathExpansion(key, &exception);
589 DCHECK(is_dictionary);
590
591 exception->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL);
592
593 base::DictionaryValue* last_used;
594 if (exception->GetDictionaryWithoutPathExpansion(kLastUsed, &last_used)) {
595 last_used->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL);
596
597 if (last_used->empty())
598 exception->RemoveWithoutPathExpansion(kLastUsed, NULL);
599 }
600
601 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS)
602 exception->RemoveWithoutPathExpansion(kPerPluginPrefName, NULL);
603
604 if (exception->empty())
605 old_dictionary->RemoveWithoutPathExpansion(key, NULL);
606 }
607
608 }
609
610 // static 453 // static
611 void ContentSettingsPref::CanonicalizeContentSettingsExceptions( 454 void ContentSettingsPref::CanonicalizeContentSettingsExceptions(
612 base::DictionaryValue* all_settings_dictionary) { 455 base::DictionaryValue* all_settings_dictionary) {
613 DCHECK(all_settings_dictionary); 456 DCHECK(all_settings_dictionary);
614 457
615 std::vector<std::string> remove_items; 458 std::vector<std::string> remove_items;
616 base::StringPairs move_items; 459 base::StringPairs move_items;
617 for (base::DictionaryValue::Iterator i(*all_settings_dictionary); 460 for (base::DictionaryValue::Iterator i(*all_settings_dictionary);
618 !i.IsAtEnd(); 461 !i.IsAtEnd();
619 i.Advance()) { 462 i.Advance()) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 508
666 void ContentSettingsPref::AssertLockNotHeld() const { 509 void ContentSettingsPref::AssertLockNotHeld() const {
667 #if !defined(NDEBUG) 510 #if !defined(NDEBUG)
668 // |Lock::Acquire()| will assert if the lock is held by this thread. 511 // |Lock::Acquire()| will assert if the lock is held by this thread.
669 lock_.Acquire(); 512 lock_.Acquire();
670 lock_.Release(); 513 lock_.Release();
671 #endif 514 #endif
672 } 515 }
673 516
674 } // namespace content_settings 517 } // namespace content_settings
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698