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_pref_provider.h"
11 #include "base/auto_reset.h"
12 #include "base/command_line.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/metrics/histogram.h"
15 #include "chrome/browser/content_settings/content_settings_rule.h"
16 #include "chrome/browser/content_settings/content_settings_utils.h"
17 #include "chrome/browser/content_settings/host_content_settings_map.h"
18 #include "chrome/browser/prefs/pref_service.h"
19 #include "chrome/browser/prefs/scoped_user_pref_update.h"
20 #include "chrome/common/chrome_notification_types.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/content_settings.h"
23 #include "chrome/common/content_settings_pattern.h"
24 #include "chrome/common/pref_names.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/user_metrics.h"
29 #include "googleurl/src/gurl.h"
31 using content::BrowserThread
;
32 using content::UserMetricsAction
;
36 typedef std::pair
<std::string
, std::string
> StringPair
;
37 typedef std::map
<std::string
, std::string
> StringMap
;
39 const char kPerPluginPrefName
[] = "per_plugin";
41 ContentSetting
FixObsoleteCookiePromptMode(ContentSettingsType content_type
,
42 ContentSetting setting
) {
43 if (content_type
== CONTENT_SETTINGS_TYPE_COOKIES
&&
44 setting
== CONTENT_SETTING_ASK
) {
45 return CONTENT_SETTING_BLOCK
;
50 // If the given content type supports resource identifiers in user preferences,
51 // returns true and sets |pref_key| to the key in the content settings
52 // dictionary under which per-resource content settings are stored.
53 // Otherwise, returns false.
54 bool GetResourceTypeName(ContentSettingsType content_type
,
55 std::string
* pref_key
) {
56 if (content_type
== CONTENT_SETTINGS_TYPE_PLUGINS
) {
57 *pref_key
= kPerPluginPrefName
;
65 namespace content_settings
{
67 // ////////////////////////////////////////////////////////////////////////////
72 void PrefProvider::RegisterUserPrefs(PrefService
* prefs
) {
73 prefs
->RegisterIntegerPref(
74 prefs::kContentSettingsVersion
,
75 ContentSettingsPattern::kContentSettingsPatternVersion
,
76 PrefService::UNSYNCABLE_PREF
);
77 prefs
->RegisterDictionaryPref(prefs::kContentSettingsPatternPairs
,
78 PrefService::SYNCABLE_PREF
);
80 // Obsolete prefs, for migration:
81 prefs
->RegisterDictionaryPref(prefs::kGeolocationContentSettings
,
82 PrefService::UNSYNCABLE_PREF
);
83 prefs
->RegisterDictionaryPref(prefs::kContentSettingsPatterns
,
84 PrefService::UNSYNCABLE_PREF
);
85 prefs
->RegisterListPref(prefs::kDesktopNotificationAllowedOrigins
,
86 PrefService::UNSYNCABLE_PREF
);
87 prefs
->RegisterListPref(prefs::kDesktopNotificationDeniedOrigins
,
88 PrefService::UNSYNCABLE_PREF
);
91 PrefProvider::PrefProvider(PrefService
* prefs
,
94 is_incognito_(incognito
),
95 updating_preferences_(false) {
98 // Migrate obsolete preferences.
99 MigrateObsoleteContentSettingsPatternPref();
100 MigrateObsoleteGeolocationPref();
101 MigrateObsoleteNotificationsPrefs();
104 // Verify preferences version.
105 if (!prefs_
->HasPrefPath(prefs::kContentSettingsVersion
)) {
106 prefs_
->SetInteger(prefs::kContentSettingsVersion
,
107 ContentSettingsPattern::kContentSettingsPatternVersion
);
109 if (prefs_
->GetInteger(prefs::kContentSettingsVersion
) >
110 ContentSettingsPattern::kContentSettingsPatternVersion
) {
114 // Read content settings exceptions.
115 ReadContentSettingsFromPref(false);
117 if (!is_incognito_
) {
118 UMA_HISTOGRAM_COUNTS("ContentSettings.NumberOfExceptions",
122 pref_change_registrar_
.Init(prefs_
);
123 pref_change_registrar_
.Add(
124 prefs::kContentSettingsPatternPairs
,
125 base::Bind(&PrefProvider::OnContentSettingsPatternPairsChanged
,
126 base::Unretained(this)));
129 bool PrefProvider::SetWebsiteSetting(
130 const ContentSettingsPattern
& primary_pattern
,
131 const ContentSettingsPattern
& secondary_pattern
,
132 ContentSettingsType content_type
,
133 const ResourceIdentifier
& resource_identifier
,
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
137 // Default settings are set using a wildcard pattern for both
138 // |primary_pattern| and |secondary_pattern|. Don't store default settings in
139 // the |PrefProvider|. The |PrefProvider| handles settings for specific
140 // sites/origins defined by the |primary_pattern| and the |secondary_pattern|.
141 // Default settings are handled by the |DefaultProvider|.
142 if (primary_pattern
== ContentSettingsPattern::Wildcard() &&
143 secondary_pattern
== ContentSettingsPattern::Wildcard() &&
144 resource_identifier
.empty()) {
148 // At this point take the ownership of the |in_value|.
149 scoped_ptr
<base::Value
> value(in_value
);
150 // Update in memory value map.
151 OriginIdentifierValueMap
* map_to_modify
= &incognito_value_map_
;
153 map_to_modify
= &value_map_
;
156 base::AutoLock
auto_lock(lock_
);
158 map_to_modify
->SetValue(
165 map_to_modify
->DeleteValue(
169 resource_identifier
);
172 // Update the content settings preference.
173 if (!is_incognito_
) {
174 UpdatePref(primary_pattern
,
182 primary_pattern
, secondary_pattern
, content_type
, resource_identifier
);
187 void PrefProvider::ClearAllContentSettingsRules(
188 ContentSettingsType content_type
) {
189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
192 OriginIdentifierValueMap
* map_to_modify
= &incognito_value_map_
;
194 map_to_modify
= &value_map_
;
196 std::vector
<Rule
> rules_to_delete
;
198 base::AutoLock
auto_lock(lock_
);
199 scoped_ptr
<RuleIterator
> rule_iterator(
200 map_to_modify
->GetRuleIterator(content_type
, "", NULL
));
201 // Copy the rules; we cannot call |UpdatePref| while holding |lock_|.
202 while (rule_iterator
->HasNext())
203 rules_to_delete
.push_back(rule_iterator
->Next());
205 map_to_modify
->DeleteValues(content_type
, "");
208 for (std::vector
<Rule
>::const_iterator it
= rules_to_delete
.begin();
209 it
!= rules_to_delete
.end(); ++it
) {
212 it
->secondary_pattern
,
217 NotifyObservers(ContentSettingsPattern(),
218 ContentSettingsPattern(),
223 PrefProvider::~PrefProvider() {
227 RuleIterator
* PrefProvider::GetRuleIterator(
228 ContentSettingsType content_type
,
229 const ResourceIdentifier
& resource_identifier
,
230 bool incognito
) const {
232 return incognito_value_map_
.GetRuleIterator(content_type
,
235 return value_map_
.GetRuleIterator(content_type
, resource_identifier
, &lock_
);
238 // ////////////////////////////////////////////////////////////////////////////
241 void PrefProvider::UpdatePref(
242 const ContentSettingsPattern
& primary_pattern
,
243 const ContentSettingsPattern
& secondary_pattern
,
244 ContentSettingsType content_type
,
245 const ResourceIdentifier
& resource_identifier
,
246 const base::Value
* value
) {
247 // Ensure that |lock_| is not held by this thread, since this function will
248 // send out notifications (by |~DictionaryPrefUpdate|).
251 AutoReset
<bool> auto_reset(&updating_preferences_
, true);
253 DictionaryPrefUpdate
update(prefs_
,
254 prefs::kContentSettingsPatternPairs
);
255 DictionaryValue
* pattern_pairs_settings
= update
.Get();
256 UpdatePatternPairsSettings(primary_pattern
,
261 pattern_pairs_settings
);
265 void PrefProvider::ReadContentSettingsFromPref(bool overwrite
) {
266 // |DictionaryPrefUpdate| sends out notifications when destructed. This
267 // construction order ensures |AutoLock| gets destroyed first and |lock_| is
268 // not held when the notifications are sent. Also, |auto_reset| must be still
269 // valid when the notifications are sent, so that |Observe| skips the
271 AutoReset
<bool> auto_reset(&updating_preferences_
, true);
272 DictionaryPrefUpdate
update(prefs_
, prefs::kContentSettingsPatternPairs
);
273 base::AutoLock
auto_lock(lock_
);
275 const DictionaryValue
* all_settings_dictionary
=
276 prefs_
->GetDictionary(prefs::kContentSettingsPatternPairs
);
281 // Careful: The returned value could be NULL if the pref has never been set.
282 if (!all_settings_dictionary
)
285 DictionaryValue
* mutable_settings
;
286 scoped_ptr
<DictionaryValue
> mutable_settings_scope
;
288 if (!is_incognito_
) {
289 mutable_settings
= update
.Get();
291 // Create copy as we do not want to persist anything in OTR prefs.
292 mutable_settings
= all_settings_dictionary
->DeepCopy();
293 mutable_settings_scope
.reset(mutable_settings
);
295 // Convert all Unicode patterns into punycode form, then read.
296 CanonicalizeContentSettingsExceptions(mutable_settings
);
298 for (DictionaryValue::key_iterator
i(mutable_settings
->begin_keys());
299 i
!= mutable_settings
->end_keys(); ++i
) {
300 const std::string
& pattern_str(*i
);
301 std::pair
<ContentSettingsPattern
, ContentSettingsPattern
> pattern_pair
=
302 ParsePatternString(pattern_str
);
303 if (!pattern_pair
.first
.IsValid() ||
304 !pattern_pair
.second
.IsValid()) {
305 LOG(DFATAL
) << "Invalid pattern strings: " << pattern_str
;
309 // Get settings dictionary for the current pattern string, and read
310 // settings from the dictionary.
311 DictionaryValue
* settings_dictionary
= NULL
;
312 bool found
= mutable_settings
->GetDictionaryWithoutPathExpansion(
313 pattern_str
, &settings_dictionary
);
316 for (size_t i
= 0; i
< CONTENT_SETTINGS_NUM_TYPES
; ++i
) {
317 ContentSettingsType content_type
= static_cast<ContentSettingsType
>(i
);
319 std::string res_dictionary_path
;
320 if (GetResourceTypeName(content_type
, &res_dictionary_path
)) {
321 DictionaryValue
* resource_dictionary
= NULL
;
322 if (settings_dictionary
->GetDictionary(
323 res_dictionary_path
, &resource_dictionary
)) {
324 for (DictionaryValue::key_iterator
j(
325 resource_dictionary
->begin_keys());
326 j
!= resource_dictionary
->end_keys();
328 const std::string
& resource_identifier(*j
);
329 int setting
= CONTENT_SETTING_DEFAULT
;
330 found
= resource_dictionary
->GetIntegerWithoutPathExpansion(
331 resource_identifier
, &setting
);
332 DCHECK_NE(CONTENT_SETTING_DEFAULT
, setting
);
333 value_map_
.SetValue(pattern_pair
.first
,
337 Value::CreateIntegerValue(setting
));
342 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type
)) {
343 DictionaryValue
* setting
= NULL
;
344 // TODO(xians): Handle the non-dictionary types.
345 if (settings_dictionary
->GetDictionaryWithoutPathExpansion(
346 GetTypeName(ContentSettingsType(i
)), &setting
)) {
347 DCHECK(!setting
->empty());
348 value
= setting
->DeepCopy();
351 int setting
= CONTENT_SETTING_DEFAULT
;
352 if (settings_dictionary
->GetIntegerWithoutPathExpansion(
353 GetTypeName(ContentSettingsType(i
)), &setting
)) {
354 DCHECK_NE(CONTENT_SETTING_DEFAULT
, setting
);
355 setting
= FixObsoleteCookiePromptMode(content_type
,
356 ContentSetting(setting
));
357 value
= Value::CreateIntegerValue(setting
);
361 // |value_map_| will take the ownership of |value|.
363 value_map_
.SetValue(pattern_pair
.first
,
366 ResourceIdentifier(""),
373 void PrefProvider::OnContentSettingsPatternPairsChanged() {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
376 if (updating_preferences_
)
379 ReadContentSettingsFromPref(true);
381 NotifyObservers(ContentSettingsPattern(),
382 ContentSettingsPattern(),
383 CONTENT_SETTINGS_TYPE_DEFAULT
,
387 void PrefProvider::UpdatePatternPairsSettings(
388 const ContentSettingsPattern
& primary_pattern
,
389 const ContentSettingsPattern
& secondary_pattern
,
390 ContentSettingsType content_type
,
391 const ResourceIdentifier
& resource_identifier
,
392 const base::Value
* value
,
393 DictionaryValue
* pattern_pairs_settings
) {
394 // Get settings dictionary for the given patterns.
395 std::string
pattern_str(CreatePatternString(primary_pattern
,
397 DictionaryValue
* settings_dictionary
= NULL
;
398 bool found
= pattern_pairs_settings
->GetDictionaryWithoutPathExpansion(
399 pattern_str
, &settings_dictionary
);
401 if (!found
&& value
) {
402 settings_dictionary
= new DictionaryValue
;
403 pattern_pairs_settings
->SetWithoutPathExpansion(
404 pattern_str
, settings_dictionary
);
407 if (settings_dictionary
) {
408 std::string res_dictionary_path
;
409 if (GetResourceTypeName(content_type
, &res_dictionary_path
) &&
410 !resource_identifier
.empty()) {
411 DictionaryValue
* resource_dictionary
= NULL
;
412 found
= settings_dictionary
->GetDictionary(
413 res_dictionary_path
, &resource_dictionary
);
416 return; // Nothing to remove. Exit early.
417 resource_dictionary
= new DictionaryValue
;
418 settings_dictionary
->Set(res_dictionary_path
, resource_dictionary
);
420 // Update resource dictionary.
422 resource_dictionary
->RemoveWithoutPathExpansion(resource_identifier
,
424 if (resource_dictionary
->empty()) {
425 settings_dictionary
->RemoveWithoutPathExpansion(
426 res_dictionary_path
, NULL
);
429 resource_dictionary
->SetWithoutPathExpansion(
430 resource_identifier
, value
->DeepCopy());
433 // Update settings dictionary.
434 std::string setting_path
= GetTypeName(content_type
);
436 settings_dictionary
->RemoveWithoutPathExpansion(setting_path
,
439 settings_dictionary
->SetWithoutPathExpansion(
440 setting_path
, value
->DeepCopy());
443 // Remove the settings dictionary if it is empty.
444 if (settings_dictionary
->empty()) {
445 pattern_pairs_settings
->RemoveWithoutPathExpansion(
452 void PrefProvider::CanonicalizeContentSettingsExceptions(
453 DictionaryValue
* all_settings_dictionary
) {
454 DCHECK(all_settings_dictionary
);
456 std::vector
<std::string
> remove_items
;
457 std::vector
<std::pair
<std::string
, std::string
> > move_items
;
458 for (DictionaryValue::key_iterator
i(all_settings_dictionary
->begin_keys());
459 i
!= all_settings_dictionary
->end_keys(); ++i
) {
460 const std::string
& pattern_str(*i
);
461 std::pair
<ContentSettingsPattern
, ContentSettingsPattern
> pattern_pair
=
462 ParsePatternString(pattern_str
);
463 if (!pattern_pair
.first
.IsValid() ||
464 !pattern_pair
.second
.IsValid()) {
465 LOG(ERROR
) << "Invalid pattern strings: " << pattern_str
;
469 const std::string canonicalized_pattern_str
= CreatePatternString(
470 pattern_pair
.first
, pattern_pair
.second
);
472 if (canonicalized_pattern_str
.empty() ||
473 canonicalized_pattern_str
== pattern_str
)
476 // Clear old pattern if prefs already have canonicalized pattern.
477 DictionaryValue
* new_pattern_settings_dictionary
= NULL
;
478 if (all_settings_dictionary
->GetDictionaryWithoutPathExpansion(
479 canonicalized_pattern_str
, &new_pattern_settings_dictionary
)) {
480 remove_items
.push_back(pattern_str
);
484 // Move old pattern to canonicalized pattern.
485 DictionaryValue
* old_pattern_settings_dictionary
= NULL
;
486 if (all_settings_dictionary
->GetDictionaryWithoutPathExpansion(
487 pattern_str
, &old_pattern_settings_dictionary
)) {
488 move_items
.push_back(
489 std::make_pair(pattern_str
, canonicalized_pattern_str
));
493 for (size_t i
= 0; i
< remove_items
.size(); ++i
) {
494 all_settings_dictionary
->RemoveWithoutPathExpansion(remove_items
[i
], NULL
);
497 for (size_t i
= 0; i
< move_items
.size(); ++i
) {
498 Value
* pattern_settings_dictionary
= NULL
;
499 all_settings_dictionary
->RemoveWithoutPathExpansion(
500 move_items
[i
].first
, &pattern_settings_dictionary
);
501 all_settings_dictionary
->SetWithoutPathExpansion(
502 move_items
[i
].second
, pattern_settings_dictionary
);
506 void PrefProvider::ShutdownOnUIThread() {
507 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
509 RemoveAllObservers();
510 pref_change_registrar_
.RemoveAll();
514 void PrefProvider::MigrateObsoleteContentSettingsPatternPref() {
515 // Ensure that |lock_| is not held by this thread, since this function will
516 // send out notifications (by |~DictionaryPrefUpdate|).
519 if (!prefs_
->HasPrefPath(prefs::kContentSettingsPatterns
))
522 const DictionaryValue
* patterns_dictionary
=
523 prefs_
->GetDictionary(prefs::kContentSettingsPatterns
);
525 DictionaryPrefUpdate
update(prefs_
, prefs::kContentSettingsPatternPairs
);
526 DictionaryValue
* pattern_pairs_dictionary
= update
.Get();
527 for (DictionaryValue::key_iterator
i(
528 patterns_dictionary
->begin_keys());
529 i
!= patterns_dictionary
->end_keys();
531 const std::string
& key(*i
);
532 // In the past a bug once corrupted dictionary keys. Test if the |key| is
533 // corrupted and skip a corrupted key. A dictionary |key| can contain two
534 // content settings patterns, a primary pattern and a secondary pattern.
535 // If the |key| contains two patterns than they are concataneted with a
537 size_t sep_pos
= key
.find(",");
538 ContentSettingsPattern pattern
=
539 ContentSettingsPattern::FromString(key
.substr(0, sep_pos
));
540 // Skip the current |key| if the primary |pattern| is invalid.
541 if (!pattern
.IsValid())
543 // If the |key| contains a secondary pattern, and the obsolete pref
544 // dictionary also contains a key that equals the primary |pattern| then
545 // skip the current |key|.
546 if (sep_pos
!= std::string::npos
&&
547 patterns_dictionary
->HasKey(pattern
.ToString())) {
551 // Copy the legacy content settings for the current |key| from the
552 // obsolete pref prefs::kContentSettingsPatterns to the pref
553 // prefs::kContentSettingsPatternPairs.
554 const DictionaryValue
* dictionary
= NULL
;
555 bool found
= patterns_dictionary
->GetDictionaryWithoutPathExpansion(
558 std::string new_key
= CreatePatternString(
559 pattern
, ContentSettingsPattern::Wildcard());
560 // Existing values are overwritten.
561 pattern_pairs_dictionary
->SetWithoutPathExpansion(
562 new_key
, dictionary
->DeepCopy());
565 prefs_
->ClearPref(prefs::kContentSettingsPatterns
);
568 void PrefProvider::MigrateObsoleteGeolocationPref() {
569 // Ensure that |lock_| is not held by this thread, since this function will
570 // send out notifications (by |~DictionaryPrefUpdate|).
573 if (!prefs_
->HasPrefPath(prefs::kGeolocationContentSettings
))
576 DictionaryPrefUpdate
update(prefs_
,
577 prefs::kContentSettingsPatternPairs
);
578 DictionaryValue
* pattern_pairs_settings
= update
.Get();
580 const DictionaryValue
* geolocation_settings
=
581 prefs_
->GetDictionary(prefs::kGeolocationContentSettings
);
583 std::vector
<std::pair
<std::string
, std::string
> > corrupted_keys
;
584 for (DictionaryValue::key_iterator i
=
585 geolocation_settings
->begin_keys();
586 i
!= geolocation_settings
->end_keys();
588 const std::string
& primary_key(*i
);
589 GURL
primary_url(primary_key
);
590 DCHECK(primary_url
.is_valid());
592 const DictionaryValue
* requesting_origin_settings
= NULL
;
593 // The method GetDictionaryWithoutPathExpansion() returns false if the
594 // value for the given key is not a |DictionaryValue|. If the value for the
595 // |primary_key| is not a |DictionaryValue| then the location settings for
596 // this key are corrupted. Therefore they are ignored.
597 if (!geolocation_settings
->GetDictionaryWithoutPathExpansion(
598 primary_key
, &requesting_origin_settings
))
601 for (DictionaryValue::key_iterator j
=
602 requesting_origin_settings
->begin_keys();
603 j
!= requesting_origin_settings
->end_keys();
605 const std::string
& secondary_key(*j
);
606 GURL
secondary_url(secondary_key
);
607 // Save corrupted keys to remove them later.
608 if (!secondary_url
.is_valid()) {
609 corrupted_keys
.push_back(std::make_pair(primary_key
, secondary_key
));
613 const base::Value
* value
= NULL
;
614 bool found
= requesting_origin_settings
->GetWithoutPathExpansion(
615 secondary_key
, &value
);
618 ContentSettingsPattern primary_pattern
=
619 ContentSettingsPattern::FromURLNoWildcard(primary_url
);
620 ContentSettingsPattern secondary_pattern
=
621 ContentSettingsPattern::FromURLNoWildcard(secondary_url
);
622 DCHECK(primary_pattern
.IsValid() && secondary_pattern
.IsValid());
624 UpdatePatternPairsSettings(primary_pattern
,
626 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
629 pattern_pairs_settings
);
633 prefs_
->ClearPref(prefs::kGeolocationContentSettings
);
636 void PrefProvider::MigrateObsoleteNotificationsPrefs() {
637 // Ensure that |lock_| is not held by this thread, since this function will
638 // send out notifications (by |~DictionaryPrefUpdate|).
641 if (!prefs_
->HasPrefPath(prefs::kDesktopNotificationAllowedOrigins
) &&
642 !prefs_
->HasPrefPath(prefs::kDesktopNotificationDeniedOrigins
)) {
646 DictionaryPrefUpdate
update(prefs_
, prefs::kContentSettingsPatternPairs
);
647 DictionaryValue
* pattern_pairs_settings
= update
.Get();
649 const ListValue
* allowed_origins
=
650 prefs_
->GetList(prefs::kDesktopNotificationAllowedOrigins
);
651 for (size_t i
= 0; i
< allowed_origins
->GetSize(); ++i
) {
652 std::string url_string
;
653 bool status
= allowed_origins
->GetString(i
, &url_string
);
655 ContentSettingsPattern primary_pattern
=
656 ContentSettingsPattern::FromURLNoWildcard(GURL(url_string
));
657 DCHECK(primary_pattern
.IsValid());
658 scoped_ptr
<base::Value
> value(
659 Value::CreateIntegerValue(CONTENT_SETTING_ALLOW
));
660 UpdatePatternPairsSettings(primary_pattern
,
661 ContentSettingsPattern::Wildcard(),
662 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
665 pattern_pairs_settings
);
668 const ListValue
* denied_origins
=
669 prefs_
->GetList(prefs::kDesktopNotificationDeniedOrigins
);
670 for (size_t i
= 0; i
< denied_origins
->GetSize(); ++i
) {
671 std::string url_string
;
672 bool status
= denied_origins
->GetString(i
, &url_string
);
674 ContentSettingsPattern primary_pattern
=
675 ContentSettingsPattern::FromURLNoWildcard(GURL(url_string
));
676 DCHECK(primary_pattern
.IsValid());
677 scoped_ptr
<base::Value
> value(
678 Value::CreateIntegerValue(CONTENT_SETTING_BLOCK
));
679 UpdatePatternPairsSettings(primary_pattern
,
680 ContentSettingsPattern::Wildcard(),
681 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
684 pattern_pairs_settings
);
687 prefs_
->ClearPref(prefs::kDesktopNotificationAllowedOrigins
);
688 prefs_
->ClearPref(prefs::kDesktopNotificationDeniedOrigins
);
691 void PrefProvider::AssertLockNotHeld() const {
693 // |Lock::Acquire()| will assert if the lock is held by this thread.
699 } // namespace content_settings