OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 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. |
| 4 |
| 5 #include "chrome/browser/content_settings/pref_content_settings_provider.h" |
| 6 |
| 7 #include "base/command_line.h" |
| 8 #include "chrome/browser/browser_thread.h" |
| 9 #include "chrome/browser/content_settings/content_settings_details.h" |
| 10 #include "chrome/browser/content_settings/content_settings_pattern.h" |
| 11 #include "chrome/browser/prefs/pref_service.h" |
| 12 #include "chrome/browser/prefs/scoped_pref_update.h" |
| 13 #include "chrome/browser/profiles/profile.h" |
| 14 #include "chrome/common/chrome_switches.h" |
| 15 #include "chrome/common/notification_details.h" |
| 16 #include "chrome/common/notification_service.h" |
| 17 #include "chrome/common/notification_source.h" |
| 18 #include "chrome/common/pref_names.h" |
| 19 |
| 20 namespace { |
| 21 |
| 22 // The default setting for each content type. |
| 23 const ContentSetting kDefaultSettings[CONTENT_SETTINGS_NUM_TYPES] = { |
| 24 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_COOKIES |
| 25 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_IMAGES |
| 26 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_JAVASCRIPT |
| 27 CONTENT_SETTING_ALLOW, // CONTENT_SETTINGS_TYPE_PLUGINS |
| 28 CONTENT_SETTING_BLOCK, // CONTENT_SETTINGS_TYPE_POPUPS |
| 29 CONTENT_SETTING_ASK, // Not used for Geolocation |
| 30 CONTENT_SETTING_ASK, // Not used for Notifications |
| 31 }; |
| 32 |
| 33 // The names of the ContentSettingsType values, for use with dictionary prefs. |
| 34 const char* kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = { |
| 35 "cookies", |
| 36 "images", |
| 37 "javascript", |
| 38 "plugins", |
| 39 "popups", |
| 40 NULL, // Not used for Geolocation |
| 41 NULL, // Not used for Notifications |
| 42 }; |
| 43 |
| 44 |
| 45 // Map ASK for the plugins content type to BLOCK if click-to-play is |
| 46 // not enabled. |
| 47 ContentSetting ClickToPlayFixup(ContentSettingsType content_type, |
| 48 ContentSetting setting) { |
| 49 if (setting == CONTENT_SETTING_ASK && |
| 50 content_type == CONTENT_SETTINGS_TYPE_PLUGINS && |
| 51 !CommandLine::ForCurrentProcess()->HasSwitch( |
| 52 switches::kEnableClickToPlay)) { |
| 53 return CONTENT_SETTING_BLOCK; |
| 54 } |
| 55 return setting; |
| 56 } |
| 57 |
| 58 } // namespace |
| 59 |
| 60 PrefContentSettingsProvider::PrefContentSettingsProvider(Profile* profile) |
| 61 : profile_(profile), |
| 62 is_off_the_record_(profile_->IsOffTheRecord()), |
| 63 updating_preferences_(false) { |
| 64 PrefService* prefs = profile->GetPrefs(); |
| 65 |
| 66 // Read global defaults. |
| 67 DCHECK_EQ(arraysize(kTypeNames), |
| 68 static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); |
| 69 ReadDefaultSettings(true); |
| 70 |
| 71 pref_change_registrar_.Init(prefs); |
| 72 pref_change_registrar_.Add(prefs::kDefaultContentSettings, this); |
| 73 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, |
| 74 Source<Profile>(profile_)); |
| 75 } |
| 76 |
| 77 PrefContentSettingsProvider::~PrefContentSettingsProvider() { |
| 78 UnregisterObservers(); |
| 79 } |
| 80 |
| 81 bool PrefContentSettingsProvider::CanProvideDefaultSetting( |
| 82 ContentSettingsType content_type) const { |
| 83 return true; |
| 84 } |
| 85 |
| 86 ContentSetting PrefContentSettingsProvider::ProvideDefaultSetting( |
| 87 ContentSettingsType content_type) const { |
| 88 AutoLock lock(lock_); |
| 89 return default_content_settings_.settings[content_type]; |
| 90 } |
| 91 |
| 92 void PrefContentSettingsProvider::UpdateDefaultSetting( |
| 93 ContentSettingsType content_type, |
| 94 ContentSetting setting) { |
| 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 96 DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation. |
| 97 DCHECK(content_type != CONTENT_SETTINGS_TYPE_PLUGINS || |
| 98 setting != CONTENT_SETTING_ASK || |
| 99 CommandLine::ForCurrentProcess()->HasSwitch( |
| 100 switches::kEnableClickToPlay)); |
| 101 |
| 102 // The default settings may not be directly modified for OTR sessions. |
| 103 // Instead, they are synced to the main profile's setting. |
| 104 if (is_off_the_record_) |
| 105 return; |
| 106 |
| 107 PrefService* prefs = profile_->GetPrefs(); |
| 108 |
| 109 DictionaryValue* default_settings_dictionary = |
| 110 prefs->GetMutableDictionary(prefs::kDefaultContentSettings); |
| 111 std::string dictionary_path(kTypeNames[content_type]); |
| 112 updating_preferences_ = true; |
| 113 { |
| 114 AutoLock lock(lock_); |
| 115 ScopedPrefUpdate update(prefs, prefs::kDefaultContentSettings); |
| 116 if ((setting == CONTENT_SETTING_DEFAULT) || |
| 117 (setting == kDefaultSettings[content_type])) { |
| 118 default_content_settings_.settings[content_type] = |
| 119 kDefaultSettings[content_type]; |
| 120 default_settings_dictionary->RemoveWithoutPathExpansion(dictionary_path, |
| 121 NULL); |
| 122 } else { |
| 123 default_content_settings_.settings[content_type] = setting; |
| 124 default_settings_dictionary->SetWithoutPathExpansion( |
| 125 dictionary_path, Value::CreateIntegerValue(setting)); |
| 126 } |
| 127 } |
| 128 updating_preferences_ = false; |
| 129 |
| 130 NotifyObservers( |
| 131 ContentSettingsDetails(ContentSettingsPattern(), content_type, "")); |
| 132 } |
| 133 |
| 134 bool PrefContentSettingsProvider::DefaultSettingIsManaged( |
| 135 ContentSettingsType content_type) const { |
| 136 return false; |
| 137 } |
| 138 |
| 139 void PrefContentSettingsProvider::ResetToDefaults() { |
| 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 141 AutoLock lock(lock_); |
| 142 default_content_settings_ = ContentSettings(); |
| 143 ForceDefaultsToBeExplicit(); |
| 144 |
| 145 if (!is_off_the_record_) { |
| 146 PrefService* prefs = profile_->GetPrefs(); |
| 147 updating_preferences_ = true; |
| 148 prefs->ClearPref(prefs::kDefaultContentSettings); |
| 149 updating_preferences_ = false; |
| 150 } |
| 151 } |
| 152 |
| 153 void PrefContentSettingsProvider::Observe(NotificationType type, |
| 154 const NotificationSource& source, |
| 155 const NotificationDetails& details) { |
| 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 157 |
| 158 if (type == NotificationType::PREF_CHANGED) { |
| 159 DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); |
| 160 if (updating_preferences_) |
| 161 return; |
| 162 |
| 163 std::string* name = Details<std::string>(details).ptr(); |
| 164 if (*name == prefs::kDefaultContentSettings) { |
| 165 ReadDefaultSettings(true); |
| 166 } else { |
| 167 NOTREACHED() << "Unexpected preference observed"; |
| 168 return; |
| 169 } |
| 170 |
| 171 if (!is_off_the_record_) { |
| 172 NotifyObservers(ContentSettingsDetails( |
| 173 ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); |
| 174 } |
| 175 } else if (type == NotificationType::PROFILE_DESTROYED) { |
| 176 DCHECK_EQ(profile_, Source<Profile>(source).ptr()); |
| 177 UnregisterObservers(); |
| 178 } else { |
| 179 NOTREACHED() << "Unexpected notification"; |
| 180 } |
| 181 } |
| 182 |
| 183 void PrefContentSettingsProvider::UnregisterObservers() { |
| 184 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 185 if (!profile_) |
| 186 return; |
| 187 pref_change_registrar_.RemoveAll(); |
| 188 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, |
| 189 Source<Profile>(profile_)); |
| 190 profile_ = NULL; |
| 191 } |
| 192 |
| 193 void PrefContentSettingsProvider::ReadDefaultSettings(bool overwrite) { |
| 194 PrefService* prefs = profile_->GetPrefs(); |
| 195 const DictionaryValue* default_settings_dictionary = |
| 196 prefs->GetDictionary(prefs::kDefaultContentSettings); |
| 197 |
| 198 AutoLock lock(lock_); |
| 199 |
| 200 if (overwrite) |
| 201 default_content_settings_ = ContentSettings(); |
| 202 |
| 203 // Careful: The returned value could be NULL if the pref has never been set. |
| 204 if (default_settings_dictionary != NULL) { |
| 205 GetSettingsFromDictionary(default_settings_dictionary, |
| 206 &default_content_settings_); |
| 207 } |
| 208 ForceDefaultsToBeExplicit(); |
| 209 } |
| 210 |
| 211 void PrefContentSettingsProvider::ForceDefaultsToBeExplicit() { |
| 212 DCHECK_EQ(arraysize(kDefaultSettings), |
| 213 static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES)); |
| 214 |
| 215 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { |
| 216 if (default_content_settings_.settings[i] == CONTENT_SETTING_DEFAULT) |
| 217 default_content_settings_.settings[i] = kDefaultSettings[i]; |
| 218 } |
| 219 } |
| 220 |
| 221 void PrefContentSettingsProvider::GetSettingsFromDictionary( |
| 222 const DictionaryValue* dictionary, |
| 223 ContentSettings* settings) { |
| 224 for (DictionaryValue::key_iterator i(dictionary->begin_keys()); |
| 225 i != dictionary->end_keys(); ++i) { |
| 226 const std::string& content_type(*i); |
| 227 for (size_t type = 0; type < arraysize(kTypeNames); ++type) { |
| 228 if ((kTypeNames[type] != NULL) && (kTypeNames[type] == content_type)) { |
| 229 int setting = CONTENT_SETTING_DEFAULT; |
| 230 bool found = dictionary->GetIntegerWithoutPathExpansion(content_type, |
| 231 &setting); |
| 232 DCHECK(found); |
| 233 settings->settings[type] = IntToContentSetting(setting); |
| 234 break; |
| 235 } |
| 236 } |
| 237 } |
| 238 // Migrate obsolete cookie prompt mode. |
| 239 if (settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] == |
| 240 CONTENT_SETTING_ASK) |
| 241 settings->settings[CONTENT_SETTINGS_TYPE_COOKIES] = CONTENT_SETTING_BLOCK; |
| 242 |
| 243 settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS] = |
| 244 ClickToPlayFixup(CONTENT_SETTINGS_TYPE_PLUGINS, |
| 245 settings->settings[CONTENT_SETTINGS_TYPE_PLUGINS]); |
| 246 } |
| 247 |
| 248 void PrefContentSettingsProvider::NotifyObservers( |
| 249 const ContentSettingsDetails& details) { |
| 250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 251 if (profile_ == NULL) |
| 252 return; |
| 253 NotificationService::current()->Notify( |
| 254 NotificationType::CONTENT_SETTINGS_CHANGED, |
| 255 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), |
| 256 Details<const ContentSettingsDetails>(&details)); |
| 257 } |
| 258 |
| 259 |
| 260 // static |
| 261 void PrefContentSettingsProvider::RegisterUserPrefs(PrefService* prefs) { |
| 262 prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings); |
| 263 } |
OLD | NEW |