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