summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/host_content_settings_map.cc139
-rw-r--r--chrome/browser/host_content_settings_map.h24
-rw-r--r--chrome/browser/sync/glue/synchronized_preferences.h2
3 files changed, 130 insertions, 35 deletions
diff --git a/chrome/browser/host_content_settings_map.cc b/chrome/browser/host_content_settings_map.cc
index fd7517a..bd30cf7 100644
--- a/chrome/browser/host_content_settings_map.cc
+++ b/chrome/browser/host_content_settings_map.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/scoped_pref_update.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
@@ -102,7 +103,8 @@ const ContentSetting
HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
: profile_(profile),
- block_third_party_cookies_(false) {
+ block_third_party_cookies_(false),
+ updating_preferences_(false) {
PrefService* prefs = profile_->GetPrefs();
// Migrate obsolete cookie pref.
@@ -160,14 +162,7 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
// Read global defaults.
DCHECK_EQ(arraysize(kTypeNames),
static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
- const DictionaryValue* default_settings_dictionary =
- prefs->GetDictionary(prefs::kDefaultContentSettings);
- // Careful: The returned value could be NULL if the pref has never been set.
- if (default_settings_dictionary != NULL) {
- GetSettingsFromDictionary(default_settings_dictionary,
- &default_content_settings_);
- }
- ForceDefaultsToBeExplicit();
+ ReadDefaultSettings(false);
// Read misc. global settings.
block_third_party_cookies_ =
@@ -185,24 +180,13 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
}
// Read exceptions.
- const DictionaryValue* all_settings_dictionary =
- prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
- // Careful: The returned value could be NULL if the pref has never been set.
- if (all_settings_dictionary != NULL) {
- for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
- i != all_settings_dictionary->end_keys(); ++i) {
- std::wstring wide_pattern(*i);
- if (!Pattern(WideToUTF8(wide_pattern)).IsValid())
- LOG(WARNING) << "Invalid pattern stored in content settings";
- DictionaryValue* pattern_settings_dictionary = NULL;
- bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
- wide_pattern, &pattern_settings_dictionary);
- DCHECK(found);
- ContentSettings settings;
- GetSettingsFromDictionary(pattern_settings_dictionary, &settings);
- host_content_settings_[WideToUTF8(wide_pattern)] = settings;
- }
- }
+ ReadExceptions(false);
+
+ prefs->AddPrefObserver(prefs::kDefaultContentSettings, this);
+ prefs->AddPrefObserver(prefs::kContentSettingsPatterns, this);
+ prefs->AddPrefObserver(prefs::kBlockThirdPartyCookies, this);
+ notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
+ NotificationService::AllSources());
}
// static
@@ -295,13 +279,15 @@ void HostContentSettingsMap::SetDefaultContentSetting(
ContentSetting setting) {
DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ PrefService* prefs = profile_->GetPrefs();
DictionaryValue* default_settings_dictionary =
- profile_->GetPrefs()->GetMutableDictionary(
- prefs::kDefaultContentSettings);
+ prefs->GetMutableDictionary(prefs::kDefaultContentSettings);
std::wstring dictionary_path(kTypeNames[content_type]);
+ updating_preferences_ = true;
{
AutoLock auto_lock(lock_);
+ ScopedPrefUpdate update(prefs, prefs::kDefaultContentSettings);
if ((setting == CONTENT_SETTING_DEFAULT) ||
(setting == kDefaultSettings[content_type])) {
default_content_settings_.settings[content_type] =
@@ -314,6 +300,7 @@ void HostContentSettingsMap::SetDefaultContentSetting(
dictionary_path, Value::CreateIntegerValue(setting));
}
}
+ updating_preferences_ = false;
NotifyObservers(ContentSettingsDetails(true));
}
@@ -323,12 +310,12 @@ void HostContentSettingsMap::SetContentSetting(const Pattern& pattern,
ContentSetting setting) {
DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ PrefService* prefs = profile_->GetPrefs();
bool early_exit = false;
std::wstring wide_pattern(UTF8ToWide(pattern.AsString()));
DictionaryValue* all_settings_dictionary =
- profile_->GetPrefs()->GetMutableDictionary(
- prefs::kContentSettingsPatterns);
+ prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
{
AutoLock auto_lock(lock_);
if (!host_content_settings_.count(pattern.AsString()))
@@ -367,22 +354,30 @@ void HostContentSettingsMap::SetContentSetting(const Pattern& pattern,
}
}
+ updating_preferences_ = true;
+ {
+ ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
+ }
+ updating_preferences_ = false;
+
NotifyObservers(ContentSettingsDetails(pattern));
}
void HostContentSettingsMap::ClearSettingsForOneType(
ContentSettingsType content_type) {
DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
+ PrefService* prefs = profile_->GetPrefs();
+ updating_preferences_ = true;
{
AutoLock auto_lock(lock_);
+ ScopedPrefUpdate update(prefs, prefs::kContentSettingsPatterns);
for (HostContentSettings::iterator i(host_content_settings_.begin());
i != host_content_settings_.end(); ) {
if (i->second.settings[content_type] != CONTENT_SETTING_DEFAULT) {
i->second.settings[content_type] = CONTENT_SETTING_DEFAULT;
std::wstring wide_host(UTF8ToWide(i->first));
DictionaryValue* all_settings_dictionary =
- profile_->GetPrefs()->GetMutableDictionary(
- prefs::kContentSettingsPatterns);
+ prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
if (AllDefault(i->second)) {
all_settings_dictionary->RemoveWithoutPathExpansion(wide_host, NULL);
host_content_settings_.erase(i++);
@@ -401,6 +396,7 @@ void HostContentSettingsMap::ClearSettingsForOneType(
}
}
}
+ updating_preferences_ = false;
NotifyObservers(ContentSettingsDetails(true));
}
@@ -432,13 +428,52 @@ void HostContentSettingsMap::ResetToDefaults() {
}
PrefService* prefs = profile_->GetPrefs();
+ updating_preferences_ = true;
prefs->ClearPref(prefs::kDefaultContentSettings);
prefs->ClearPref(prefs::kContentSettingsPatterns);
prefs->ClearPref(prefs::kBlockThirdPartyCookies);
+ updating_preferences_ = false;
NotifyObservers(ContentSettingsDetails(true));
}
+void HostContentSettingsMap::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+ if (NotificationType::PREF_CHANGED == type) {
+ if (updating_preferences_)
+ return;
+
+ std::wstring* name = Details<std::wstring>(details).ptr();
+ if (prefs::kDefaultContentSettings == *name) {
+ ReadDefaultSettings(true);
+ } else if (prefs::kContentSettingsPatterns == *name) {
+ ReadExceptions(true);
+ } else if (prefs::kBlockThirdPartyCookies == *name) {
+ updating_preferences_ = true;
+ SetBlockThirdPartyCookies(profile_->GetPrefs()->GetBoolean(
+ prefs::kBlockThirdPartyCookies));
+ updating_preferences_ = false;
+ } else {
+ NOTREACHED() << "Unexpected preference observed";
+ return;
+ }
+
+ NotifyObservers(ContentSettingsDetails(true));
+ } else if (NotificationType::PROFILE_DESTROYED == type) {
+ PrefService* prefs = profile_->GetPrefs();
+ prefs->RemovePrefObserver(prefs::kDefaultContentSettings, this);
+ prefs->RemovePrefObserver(prefs::kContentSettingsPatterns, this);
+ prefs->RemovePrefObserver(prefs::kBlockThirdPartyCookies, this);
+ notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
+ NotificationService::AllSources());
+ } else {
+ NOTREACHED() << "Unexpected notification";
+ }
+}
+
HostContentSettingsMap::~HostContentSettingsMap() {
}
@@ -489,6 +524,44 @@ bool HostContentSettingsMap::AllDefault(const ContentSettings& settings) const {
return true;
}
+void HostContentSettingsMap::ReadDefaultSettings(bool overwrite) {
+ PrefService* prefs = profile_->GetPrefs();
+ const DictionaryValue* default_settings_dictionary =
+ prefs->GetDictionary(prefs::kDefaultContentSettings);
+ // Careful: The returned value could be NULL if the pref has never been set.
+ if (default_settings_dictionary != NULL) {
+ if (overwrite)
+ default_content_settings_ = ContentSettings();
+ GetSettingsFromDictionary(default_settings_dictionary,
+ &default_content_settings_);
+ }
+ ForceDefaultsToBeExplicit();
+}
+
+void HostContentSettingsMap::ReadExceptions(bool overwrite) {
+ PrefService* prefs = profile_->GetPrefs();
+ const DictionaryValue* all_settings_dictionary =
+ prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
+ // Careful: The returned value could be NULL if the pref has never been set.
+ if (all_settings_dictionary != NULL) {
+ if (overwrite)
+ host_content_settings_.clear();
+ for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
+ i != all_settings_dictionary->end_keys(); ++i) {
+ std::wstring wide_pattern(*i);
+ if (!Pattern(WideToUTF8(wide_pattern)).IsValid())
+ LOG(WARNING) << "Invalid pattern stored in content settings";
+ DictionaryValue* pattern_settings_dictionary = NULL;
+ bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+ wide_pattern, &pattern_settings_dictionary);
+ DCHECK(found);
+ ContentSettings settings;
+ GetSettingsFromDictionary(pattern_settings_dictionary, &settings);
+ host_content_settings_[WideToUTF8(wide_pattern)] = settings;
+ }
+ }
+}
+
void HostContentSettingsMap::NotifyObservers(
const ContentSettingsDetails& details) {
NotificationService::current()->Notify(
diff --git a/chrome/browser/host_content_settings_map.h b/chrome/browser/host_content_settings_map.h
index babc769..97a1c1b 100644
--- a/chrome/browser/host_content_settings_map.h
+++ b/chrome/browser/host_content_settings_map.h
@@ -17,6 +17,8 @@
#include "base/lock.h"
#include "base/ref_counted.h"
#include "chrome/common/content_settings.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
class DictionaryValue;
class GURL;
@@ -24,7 +26,8 @@ class PrefService;
class Profile;
class HostContentSettingsMap
- : public base::RefCountedThreadSafe<HostContentSettingsMap> {
+ : public NotificationObserver,
+ public base::RefCountedThreadSafe<HostContentSettingsMap> {
public:
// A hostname pattern. See |IsValid| for a description of possible patterns.
class Pattern {
@@ -148,6 +151,11 @@ class HostContentSettingsMap
// This should only be called on the UI thread.
void ResetToDefaults();
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
private:
friend class base::RefCountedThreadSafe<HostContentSettingsMap>;
@@ -177,6 +185,14 @@ class HostContentSettingsMap
// Returns true if |settings| consists entirely of CONTENT_SETTING_DEFAULT.
bool AllDefault(const ContentSettings& settings) const;
+ // Reads the default settings from the prefereces service. If |overwrite| is
+ // true and the preference is missing, the local copy will be cleared as well.
+ void ReadDefaultSettings(bool overwrite);
+
+ // Reads the host exceptions from the prefereces service. If |overwrite| is
+ // true and the preference is missing, the local copy will be cleared as well.
+ void ReadExceptions(bool overwrite);
+
// Informs observers that content settings have changed. Make sure that
// |lock_| is not held when calling this, as listeners will usually call one
// of the GetSettings functions in response, which would then lead to a
@@ -186,6 +202,8 @@ class HostContentSettingsMap
// The profile we're associated with.
Profile* profile_;
+ NotificationRegistrar notification_registrar_;
+
// Copies of the pref data, so that we can read it on the IO thread.
ContentSettings default_content_settings_;
HostContentSettings host_content_settings_;
@@ -196,6 +214,10 @@ class HostContentSettingsMap
// Used around accesses to the settings objects to guarantee thread safety.
mutable Lock lock_;
+ // Whether we are currently updating preferences, this is used to ignore
+ // notifications from the preferences service that we triggered ourself.
+ bool updating_preferences_;
+
DISALLOW_COPY_AND_ASSIGN(HostContentSettingsMap);
};
diff --git a/chrome/browser/sync/glue/synchronized_preferences.h b/chrome/browser/sync/glue/synchronized_preferences.h
index ecc16bf..556720a 100644
--- a/chrome/browser/sync/glue/synchronized_preferences.h
+++ b/chrome/browser/sync/glue/synchronized_preferences.h
@@ -52,7 +52,7 @@ static const wchar_t* kSynchronizedPreferences[] = {
prefs::kNTPPromoImageRemaining,
prefs::kNTPPromoLineRemaining,
prefs::kPasswordManagerEnabled,
- prefs::kPerHostContentSettings,
+ prefs::kContentSettingsPatterns,
prefs::kPerHostZoomLevels,
prefs::kPinnedTabs,
prefs::kPrintingPageFooterCenter,