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.
4
5 #include "components/content_settings/core/browser/content_settings_default_provider.h"
6
7 #include <memory>
8 #include <string>
9 #include <vector>
10
11 #include "base/auto_reset.h"
12 #include "base/bind.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "components/content_settings/core/browser/content_settings_info.h"
16 #include "components/content_settings/core/browser/content_settings_registry.h"
17 #include "components/content_settings/core/browser/content_settings_rule.h"
18 #include "components/content_settings/core/browser/content_settings_utils.h"
19 #include "components/content_settings/core/browser/website_settings_info.h"
20 #include "components/content_settings/core/browser/website_settings_registry.h"
21 #include "components/content_settings/core/common/content_settings.h"
22 #include "components/content_settings/core/common/content_settings_pattern.h"
23 #include "components/content_settings/core/common/content_settings_utils.h"
24 #include "components/content_settings/core/common/pref_names.h"
25 #include "components/pref_registry/pref_registry_syncable.h"
26 #include "components/prefs/pref_registry.h"
27 #include "components/prefs/pref_service.h"
28 #include "components/prefs/scoped_user_pref_update.h"
29 #include "url/gurl.h"
30
31 namespace content_settings {
32
33 namespace {
34
35 // These settings are no longer used, and should be deleted on profile startup.
36 #if !defined(OS_IOS)
37 const char kObsoleteFullscreenDefaultPref[] =
38 "profile.default_content_setting_values.fullscreen";
39 #if !defined(OS_ANDROID)
40 const char kObsoleteMouseLockDefaultPref[] =
41 "profile.default_content_setting_values.mouselock";
42 #endif // !defined(OS_ANDROID)
43 #endif // !defined(OS_IOS)
44
GetDefaultValue(const WebsiteSettingsInfo * info)45 ContentSetting GetDefaultValue(const WebsiteSettingsInfo* info) {
46 const base::Value* initial_default = info->initial_default_value();
47 if (!initial_default)
48 return CONTENT_SETTING_DEFAULT;
49 int result = 0;
50 bool success = initial_default->GetAsInteger(&result);
51 DCHECK(success);
52 return static_cast<ContentSetting>(result);
53 }
54
GetDefaultValue(ContentSettingsType type)55 ContentSetting GetDefaultValue(ContentSettingsType type) {
56 return GetDefaultValue(WebsiteSettingsRegistry::GetInstance()->Get(type));
57 }
58
GetPrefName(ContentSettingsType type)59 const std::string& GetPrefName(ContentSettingsType type) {
60 return WebsiteSettingsRegistry::GetInstance()
61 ->Get(type)
62 ->default_value_pref_name();
63 }
64
65 class DefaultRuleIterator : public RuleIterator {
66 public:
DefaultRuleIterator(const base::Value * value)67 explicit DefaultRuleIterator(const base::Value* value) {
68 if (value)
69 value_ = value->Clone();
70 else
71 is_done_ = true;
72 }
73
HasNext() const74 bool HasNext() const override { return !is_done_; }
75
Next()76 Rule Next() override {
77 DCHECK(HasNext());
78 is_done_ = true;
79 return Rule(ContentSettingsPattern::Wildcard(),
80 ContentSettingsPattern::Wildcard(), std::move(value_));
81 }
82
83 private:
84 bool is_done_ = false;
85 base::Value value_;
86
87 DISALLOW_COPY_AND_ASSIGN(DefaultRuleIterator);
88 };
89
90 } // namespace
91
92 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)93 void DefaultProvider::RegisterProfilePrefs(
94 user_prefs::PrefRegistrySyncable* registry) {
95 // Register the default settings' preferences.
96 WebsiteSettingsRegistry* website_settings =
97 WebsiteSettingsRegistry::GetInstance();
98 for (const WebsiteSettingsInfo* info : *website_settings) {
99 registry->RegisterIntegerPref(info->default_value_pref_name(),
100 GetDefaultValue(info),
101 info->GetPrefRegistrationFlags());
102 }
103
104 // Obsolete prefs -------------------------------------------------------
105
106 // These prefs have been removed, but need to be registered so they can
107 // be deleted on startup.
108 #if !defined(OS_IOS)
109 registry->RegisterIntegerPref(
110 kObsoleteFullscreenDefaultPref, 0,
111 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
112 #if !defined(OS_ANDROID)
113 registry->RegisterIntegerPref(
114 kObsoleteMouseLockDefaultPref, 0,
115 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
116 #endif // !defined(OS_ANDROID)
117 #endif // !defined(OS_IOS)
118 }
119
DefaultProvider(PrefService * prefs,bool incognito)120 DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito)
121 : prefs_(prefs),
122 is_incognito_(incognito),
123 updating_preferences_(false) {
124 DCHECK(prefs_);
125
126 // Remove the obsolete preferences from the pref file.
127 DiscardObsoletePreferences();
128
129 // Read global defaults.
130 ReadDefaultSettings();
131
132 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultCookiesSetting",
133 IntToContentSetting(prefs_->GetInteger(
134 GetPrefName(ContentSettingsType::COOKIES))),
135 CONTENT_SETTING_NUM_SETTINGS);
136 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultPopupsSetting",
137 IntToContentSetting(prefs_->GetInteger(
138 GetPrefName(ContentSettingsType::POPUPS))),
139 CONTENT_SETTING_NUM_SETTINGS);
140 #if !defined(OS_IOS) && !defined(OS_ANDROID)
141 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultImagesSetting",
142 IntToContentSetting(prefs_->GetInteger(
143 GetPrefName(ContentSettingsType::IMAGES))),
144 CONTENT_SETTING_NUM_SETTINGS);
145 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultPluginsSetting",
146 IntToContentSetting(prefs_->GetInteger(
147 GetPrefName(ContentSettingsType::PLUGINS))),
148 CONTENT_SETTING_NUM_SETTINGS);
149 #endif
150
151 #if !defined(OS_IOS)
152 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultJavaScriptSetting",
153 IntToContentSetting(prefs_->GetInteger(
154 GetPrefName(ContentSettingsType::JAVASCRIPT))),
155 CONTENT_SETTING_NUM_SETTINGS);
156
157 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultLocationSetting",
158 IntToContentSetting(prefs_->GetInteger(
159 GetPrefName(ContentSettingsType::GEOLOCATION))),
160 CONTENT_SETTING_NUM_SETTINGS);
161 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultNotificationsSetting",
162 IntToContentSetting(prefs_->GetInteger(GetPrefName(
163 ContentSettingsType::NOTIFICATIONS))),
164 CONTENT_SETTING_NUM_SETTINGS);
165
166 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultMediaStreamMicSetting",
167 IntToContentSetting(prefs_->GetInteger(GetPrefName(
168 ContentSettingsType::MEDIASTREAM_MIC))),
169 CONTENT_SETTING_NUM_SETTINGS);
170 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultMediaStreamCameraSetting",
171 IntToContentSetting(prefs_->GetInteger(GetPrefName(
172 ContentSettingsType::MEDIASTREAM_CAMERA))),
173 CONTENT_SETTING_NUM_SETTINGS);
174 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultMIDISysExSetting",
175 IntToContentSetting(prefs_->GetInteger(
176 GetPrefName(ContentSettingsType::MIDI_SYSEX))),
177 CONTENT_SETTING_NUM_SETTINGS);
178 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultWebBluetoothGuardSetting",
179 IntToContentSetting(prefs_->GetInteger(GetPrefName(
180 ContentSettingsType::BLUETOOTH_GUARD))),
181 CONTENT_SETTING_NUM_SETTINGS);
182 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultAutoplaySetting",
183 IntToContentSetting(prefs_->GetInteger(
184 GetPrefName(ContentSettingsType::AUTOPLAY))),
185 CONTENT_SETTING_NUM_SETTINGS);
186 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultSubresourceFilterSetting",
187 IntToContentSetting(prefs_->GetInteger(
188 GetPrefName(ContentSettingsType::ADS))),
189 CONTENT_SETTING_NUM_SETTINGS);
190 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultSoundSetting",
191 IntToContentSetting(prefs_->GetInteger(
192 GetPrefName(ContentSettingsType::SOUND))),
193 CONTENT_SETTING_NUM_SETTINGS);
194 UMA_HISTOGRAM_ENUMERATION("ContentSettings.DefaultUsbGuardSetting",
195 IntToContentSetting(prefs_->GetInteger(
196 GetPrefName(ContentSettingsType::USB_GUARD))),
197 CONTENT_SETTING_NUM_SETTINGS);
198 #endif
199 pref_change_registrar_.Init(prefs_);
200 PrefChangeRegistrar::NamedChangeCallback callback = base::BindRepeating(
201 &DefaultProvider::OnPreferenceChanged, base::Unretained(this));
202 WebsiteSettingsRegistry* website_settings =
203 WebsiteSettingsRegistry::GetInstance();
204 for (const WebsiteSettingsInfo* info : *website_settings)
205 pref_change_registrar_.Add(info->default_value_pref_name(), callback);
206 }
207
~DefaultProvider()208 DefaultProvider::~DefaultProvider() {
209 }
210
SetWebsiteSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,std::unique_ptr<base::Value> && in_value)211 bool DefaultProvider::SetWebsiteSetting(
212 const ContentSettingsPattern& primary_pattern,
213 const ContentSettingsPattern& secondary_pattern,
214 ContentSettingsType content_type,
215 const ResourceIdentifier& resource_identifier,
216 std::unique_ptr<base::Value>&& in_value) {
217 DCHECK(CalledOnValidThread());
218 DCHECK(prefs_);
219
220 // Ignore non default settings
221 if (primary_pattern != ContentSettingsPattern::Wildcard() ||
222 secondary_pattern != ContentSettingsPattern::Wildcard()) {
223 return false;
224 }
225
226 // Put |in_value| in a scoped pointer to ensure that it gets cleaned up
227 // properly if we don't pass on the ownership.
228 std::unique_ptr<base::Value> value(std::move(in_value));
229
230 // The default settings may not be directly modified for OTR sessions.
231 // Instead, they are synced to the main profile's setting.
232 if (is_incognito_)
233 return true;
234
235 {
236 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
237 // Lock the memory map access, so that values are not read by
238 // |GetRuleIterator| at the same time as they are written here. Do not lock
239 // the preference access though; preference updates send out notifications
240 // whose callbacks may try to reacquire the lock on the same thread.
241 {
242 base::AutoLock lock(lock_);
243 ChangeSetting(content_type, value.get());
244 }
245 WriteToPref(content_type, value.get());
246 }
247
248 NotifyObservers(ContentSettingsPattern(),
249 ContentSettingsPattern(),
250 content_type,
251 ResourceIdentifier());
252
253 return true;
254 }
255
GetRuleIterator(ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,bool incognito) const256 std::unique_ptr<RuleIterator> DefaultProvider::GetRuleIterator(
257 ContentSettingsType content_type,
258 const ResourceIdentifier& resource_identifier,
259 bool incognito) const {
260 // The default provider never has incognito-specific settings.
261 if (incognito)
262 return nullptr;
263
264 base::AutoLock lock(lock_);
265 if (!resource_identifier.empty())
266 return nullptr;
267
268 auto it = default_settings_.find(content_type);
269 if (it == default_settings_.end()) {
270 NOTREACHED();
271 return nullptr;
272 }
273 return std::make_unique<DefaultRuleIterator>(it->second.get());
274 }
275
ClearAllContentSettingsRules(ContentSettingsType content_type)276 void DefaultProvider::ClearAllContentSettingsRules(
277 ContentSettingsType content_type) {
278 // TODO(markusheintz): This method is only called when the
279 // |DesktopNotificationService| calls |ClearAllSettingsForType| method on the
280 // |HostContentSettingsMap|. Don't implement this method yet, otherwise the
281 // default notification settings will be cleared as well.
282 }
283
ShutdownOnUIThread()284 void DefaultProvider::ShutdownOnUIThread() {
285 DCHECK(CalledOnValidThread());
286 DCHECK(prefs_);
287 RemoveAllObservers();
288 pref_change_registrar_.RemoveAll();
289 prefs_ = nullptr;
290 }
291
ReadDefaultSettings()292 void DefaultProvider::ReadDefaultSettings() {
293 base::AutoLock lock(lock_);
294 WebsiteSettingsRegistry* website_settings =
295 WebsiteSettingsRegistry::GetInstance();
296 for (const WebsiteSettingsInfo* info : *website_settings)
297 ChangeSetting(info->type(), ReadFromPref(info->type()).get());
298 }
299
IsValueEmptyOrDefault(ContentSettingsType content_type,base::Value * value)300 bool DefaultProvider::IsValueEmptyOrDefault(ContentSettingsType content_type,
301 base::Value* value) {
302 return !value ||
303 ValueToContentSetting(value) == GetDefaultValue(content_type);
304 }
305
ChangeSetting(ContentSettingsType content_type,base::Value * value)306 void DefaultProvider::ChangeSetting(ContentSettingsType content_type,
307 base::Value* value) {
308 const ContentSettingsInfo* info =
309 ContentSettingsRegistry::GetInstance()->Get(content_type);
310 DCHECK(!info || !value ||
311 info->IsDefaultSettingValid(ValueToContentSetting(value)));
312 default_settings_[content_type] =
313 value ? base::WrapUnique(value->DeepCopy())
314 : ContentSettingToValue(GetDefaultValue(content_type));
315 }
316
WriteToPref(ContentSettingsType content_type,base::Value * value)317 void DefaultProvider::WriteToPref(ContentSettingsType content_type,
318 base::Value* value) {
319 if (IsValueEmptyOrDefault(content_type, value)) {
320 prefs_->ClearPref(GetPrefName(content_type));
321 return;
322 }
323
324 int int_value = GetDefaultValue(content_type);
325 bool is_integer = value->GetAsInteger(&int_value);
326 DCHECK(is_integer);
327 prefs_->SetInteger(GetPrefName(content_type), int_value);
328 }
329
OnPreferenceChanged(const std::string & name)330 void DefaultProvider::OnPreferenceChanged(const std::string& name) {
331 DCHECK(CalledOnValidThread());
332 if (updating_preferences_)
333 return;
334
335 // Find out which content setting the preference corresponds to.
336 ContentSettingsType content_type = ContentSettingsType::DEFAULT;
337
338 WebsiteSettingsRegistry* website_settings =
339 WebsiteSettingsRegistry::GetInstance();
340 for (const WebsiteSettingsInfo* info : *website_settings) {
341 if (info->default_value_pref_name() == name) {
342 content_type = info->type();
343 break;
344 }
345 }
346
347 if (content_type == ContentSettingsType::DEFAULT) {
348 NOTREACHED() << "A change of the preference " << name << " was observed, "
349 "but the preference could not be mapped to a content "
350 "settings type.";
351 return;
352 }
353
354 {
355 base::AutoReset<bool> auto_reset(&updating_preferences_, true);
356 // Lock the memory map access, so that values are not read by
357 // |GetRuleIterator| at the same time as they are written here. Do not lock
358 // the preference access though; preference updates send out notifications
359 // whose callbacks may try to reacquire the lock on the same thread.
360 {
361 base::AutoLock lock(lock_);
362 ChangeSetting(content_type, ReadFromPref(content_type).get());
363 }
364 }
365
366 NotifyObservers(ContentSettingsPattern(),
367 ContentSettingsPattern(),
368 content_type,
369 ResourceIdentifier());
370 }
371
ReadFromPref(ContentSettingsType content_type)372 std::unique_ptr<base::Value> DefaultProvider::ReadFromPref(
373 ContentSettingsType content_type) {
374 int int_value = prefs_->GetInteger(GetPrefName(content_type));
375 return ContentSettingToValue(IntToContentSetting(int_value));
376 }
377
DiscardObsoletePreferences()378 void DefaultProvider::DiscardObsoletePreferences() {
379 if (is_incognito_)
380 return;
381 // These prefs were never stored on iOS/Android so they don't need to be
382 // deleted.
383 #if !defined(OS_IOS)
384 prefs_->ClearPref(kObsoleteFullscreenDefaultPref);
385 #if !defined(OS_ANDROID)
386 prefs_->ClearPref(kObsoleteMouseLockDefaultPref);
387
388 // ALLOW-by-default is an obsolete pref value for plugins (Flash). Erase that
389 // pref and fall back to the default behavior - but preserve other values.
390 const std::string& plugins_pref = GetPrefName(ContentSettingsType::PLUGINS);
391 if (IntToContentSetting(prefs_->GetInteger(plugins_pref)) ==
392 ContentSetting::CONTENT_SETTING_ALLOW) {
393 prefs_->ClearPref(plugins_pref);
394 }
395 #endif // !defined(OS_ANDROID)
396 #endif // !defined(OS_IOS)
397 }
398
399 } // namespace content_settings
400