content_settings_policy_provider.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 "chrome/browser/content_settings/content_settings_policy_provider.h"
6
7#include <string>
8#include <vector>
9
10#include "base/json/json_reader.h"
11#include "base/prefs/pref_service.h"
12#include "base/values.h"
13#include "chrome/browser/chrome_notification_types.h"
14#include "chrome/browser/content_settings/content_settings_rule.h"
15#include "chrome/browser/content_settings/content_settings_utils.h"
16#include "chrome/common/content_settings_pattern.h"
17#include "chrome/common/pref_names.h"
18#include "components/user_prefs/pref_registry_syncable.h"
19#include "content/public/browser/browser_thread.h"
20#include "content/public/browser/notification_details.h"
21#include "content/public/browser/notification_source.h"
22
23using content::BrowserThread;
24
25namespace {
26
27// The preferences used to manage ContentSettingsTypes.
28const char* kPrefToManageType[] = {
29  prefs::kManagedDefaultCookiesSetting,
30  prefs::kManagedDefaultImagesSetting,
31  prefs::kManagedDefaultJavaScriptSetting,
32  prefs::kManagedDefaultPluginsSetting,
33  prefs::kManagedDefaultPopupsSetting,
34  prefs::kManagedDefaultGeolocationSetting,
35  prefs::kManagedDefaultNotificationsSetting,
36  NULL,  // No policy for default value of content type auto-select-certificate
37  NULL,  // No policy for default value of fullscreen requests
38  NULL,  // No policy for default value of mouse lock requests
39  NULL,  // No policy for default value of mixed script blocking
40  prefs::kManagedDefaultMediaStreamSetting,
41  NULL,  // No policy for default value of media stream mic
42  NULL,  // No policy for default value of media stream camera
43  NULL,  // No policy for default value of protocol handlers
44  NULL,  // No policy for default value of PPAPI broker
45  NULL,  // No policy for default value of multiple automatic downloads
46  NULL,  // No policy for default value of MIDI system exclusive requests
47  NULL,  // No policy for default value of save password
48#if defined(OS_WIN)
49  NULL,  // No policy for default value of "switch to desktop"
50#elif defined(OS_ANDROID) || defined(OS_CHROMEOS)
51  NULL,  // No policy for default value of protected media identifier
52#endif
53};
54COMPILE_ASSERT(arraysize(kPrefToManageType) == CONTENT_SETTINGS_NUM_TYPES,
55               managed_content_settings_pref_names_array_size_incorrect);
56
57struct PrefsForManagedContentSettingsMapEntry {
58  const char* pref_name;
59  ContentSettingsType content_type;
60  ContentSetting setting;
61};
62
63const PrefsForManagedContentSettingsMapEntry
64    kPrefsForManagedContentSettingsMap[] = {
65  {
66    prefs::kManagedCookiesAllowedForUrls,
67    CONTENT_SETTINGS_TYPE_COOKIES,
68    CONTENT_SETTING_ALLOW
69  }, {
70    prefs::kManagedCookiesSessionOnlyForUrls,
71    CONTENT_SETTINGS_TYPE_COOKIES,
72    CONTENT_SETTING_SESSION_ONLY
73  }, {
74    prefs::kManagedCookiesBlockedForUrls,
75    CONTENT_SETTINGS_TYPE_COOKIES,
76    CONTENT_SETTING_BLOCK
77  }, {
78    prefs::kManagedImagesAllowedForUrls,
79    CONTENT_SETTINGS_TYPE_IMAGES,
80    CONTENT_SETTING_ALLOW
81  }, {
82    prefs::kManagedImagesBlockedForUrls,
83    CONTENT_SETTINGS_TYPE_IMAGES,
84    CONTENT_SETTING_BLOCK
85  }, {
86    prefs::kManagedJavaScriptAllowedForUrls,
87    CONTENT_SETTINGS_TYPE_JAVASCRIPT,
88    CONTENT_SETTING_ALLOW
89  }, {
90    prefs::kManagedJavaScriptBlockedForUrls,
91    CONTENT_SETTINGS_TYPE_JAVASCRIPT,
92    CONTENT_SETTING_BLOCK
93  }, {
94    prefs::kManagedPluginsAllowedForUrls,
95    CONTENT_SETTINGS_TYPE_PLUGINS,
96    CONTENT_SETTING_ALLOW
97  }, {
98    prefs::kManagedPluginsBlockedForUrls,
99    CONTENT_SETTINGS_TYPE_PLUGINS,
100    CONTENT_SETTING_BLOCK
101  }, {
102    prefs::kManagedPopupsAllowedForUrls,
103    CONTENT_SETTINGS_TYPE_POPUPS,
104    CONTENT_SETTING_ALLOW
105  }, {
106    prefs::kManagedPopupsBlockedForUrls,
107    CONTENT_SETTINGS_TYPE_POPUPS,
108    CONTENT_SETTING_BLOCK
109  }, {
110    prefs::kManagedNotificationsAllowedForUrls,
111    CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
112    CONTENT_SETTING_ALLOW
113  }, {
114    prefs::kManagedNotificationsBlockedForUrls,
115    CONTENT_SETTINGS_TYPE_NOTIFICATIONS,
116    CONTENT_SETTING_BLOCK
117  }
118};
119
120}  // namespace
121
122namespace content_settings {
123
124// static
125void PolicyProvider::RegisterProfilePrefs(
126    user_prefs::PrefRegistrySyncable* registry) {
127  registry->RegisterListPref(prefs::kManagedAutoSelectCertificateForUrls,
128                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
129  registry->RegisterListPref(prefs::kManagedCookiesAllowedForUrls,
130                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
131  registry->RegisterListPref(prefs::kManagedCookiesBlockedForUrls,
132                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
133  registry->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls,
134                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
135  registry->RegisterListPref(prefs::kManagedImagesAllowedForUrls,
136                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
137  registry->RegisterListPref(prefs::kManagedImagesBlockedForUrls,
138                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
139  registry->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls,
140                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
141  registry->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls,
142                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
143  registry->RegisterListPref(prefs::kManagedPluginsAllowedForUrls,
144                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
145  registry->RegisterListPref(prefs::kManagedPluginsBlockedForUrls,
146                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
147  registry->RegisterListPref(prefs::kManagedPopupsAllowedForUrls,
148                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
149  registry->RegisterListPref(prefs::kManagedPopupsBlockedForUrls,
150                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
151  registry->RegisterListPref(prefs::kManagedNotificationsAllowedForUrls,
152                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
153  registry->RegisterListPref(prefs::kManagedNotificationsBlockedForUrls,
154                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
155  // Preferences for default content setting policies. If a policy is not set of
156  // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT.
157  registry->RegisterIntegerPref(
158      prefs::kManagedDefaultCookiesSetting,
159      CONTENT_SETTING_DEFAULT,
160      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
161  registry->RegisterIntegerPref(
162      prefs::kManagedDefaultImagesSetting,
163      CONTENT_SETTING_DEFAULT,
164      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
165  registry->RegisterIntegerPref(
166      prefs::kManagedDefaultJavaScriptSetting,
167      CONTENT_SETTING_DEFAULT,
168      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
169  registry->RegisterIntegerPref(
170      prefs::kManagedDefaultPluginsSetting,
171      CONTENT_SETTING_DEFAULT,
172      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
173  registry->RegisterIntegerPref(
174      prefs::kManagedDefaultPopupsSetting,
175      CONTENT_SETTING_DEFAULT,
176      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
177  registry->RegisterIntegerPref(
178      prefs::kManagedDefaultGeolocationSetting,
179      CONTENT_SETTING_DEFAULT,
180      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
181  registry->RegisterIntegerPref(
182      prefs::kManagedDefaultNotificationsSetting,
183      CONTENT_SETTING_DEFAULT,
184      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
185  registry->RegisterIntegerPref(
186      prefs::kManagedDefaultMediaStreamSetting,
187      CONTENT_SETTING_DEFAULT,
188      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
189}
190
191PolicyProvider::PolicyProvider(PrefService* prefs) : prefs_(prefs) {
192  ReadManagedDefaultSettings();
193  ReadManagedContentSettings(false);
194
195  pref_change_registrar_.Init(prefs_);
196  PrefChangeRegistrar::NamedChangeCallback callback =
197      base::Bind(&PolicyProvider::OnPreferenceChanged, base::Unretained(this));
198  pref_change_registrar_.Add(
199      prefs::kManagedAutoSelectCertificateForUrls, callback);
200  pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, callback);
201  pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, callback);
202  pref_change_registrar_.Add(
203      prefs::kManagedCookiesSessionOnlyForUrls, callback);
204  pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, callback);
205  pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, callback);
206  pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, callback);
207  pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, callback);
208  pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, callback);
209  pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, callback);
210  pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, callback);
211  pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, callback);
212  pref_change_registrar_.Add(
213      prefs::kManagedNotificationsAllowedForUrls, callback);
214  pref_change_registrar_.Add(
215      prefs::kManagedNotificationsBlockedForUrls, callback);
216  // The following preferences are only used to indicate if a
217  // default content setting is managed and to hold the managed default setting
218  // value. If the value for any of the following perferences is set then the
219  // corresponding default content setting is managed. These preferences exist
220  // in parallel to the preference default content settings.  If a
221  // default content settings type is managed any user defined excpetions
222  // (patterns) for this type are ignored.
223  pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, callback);
224  pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, callback);
225  pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, callback);
226  pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, callback);
227  pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, callback);
228  pref_change_registrar_.Add(
229      prefs::kManagedDefaultGeolocationSetting, callback);
230  pref_change_registrar_.Add(
231      prefs::kManagedDefaultNotificationsSetting, callback);
232  pref_change_registrar_.Add(
233      prefs::kManagedDefaultMediaStreamSetting, callback);
234}
235
236PolicyProvider::~PolicyProvider() {
237  DCHECK(!prefs_);
238}
239
240RuleIterator* PolicyProvider::GetRuleIterator(
241    ContentSettingsType content_type,
242    const ResourceIdentifier& resource_identifier,
243    bool incognito) const {
244  return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_);
245}
246
247void PolicyProvider::GetContentSettingsFromPreferences(
248    OriginIdentifierValueMap* value_map) {
249  for (size_t i = 0; i < arraysize(kPrefsForManagedContentSettingsMap); ++i) {
250    const char* pref_name = kPrefsForManagedContentSettingsMap[i].pref_name;
251    // Skip unset policies.
252    if (!prefs_->HasPrefPath(pref_name)) {
253      VLOG(2) << "Skipping unset preference: " << pref_name;
254      continue;
255    }
256
257    const PrefService::Preference* pref = prefs_->FindPreference(pref_name);
258    DCHECK(pref);
259    DCHECK(pref->IsManaged());
260
261    const base::ListValue* pattern_str_list = NULL;
262    if (!pref->GetValue()->GetAsList(&pattern_str_list)) {
263      NOTREACHED();
264      return;
265    }
266
267    for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) {
268      std::string original_pattern_str;
269      if (!pattern_str_list->GetString(j, &original_pattern_str)) {
270        NOTREACHED();
271        continue;
272      }
273
274      PatternPair pattern_pair = ParsePatternString(original_pattern_str);
275      // Ignore invalid patterns.
276      if (!pattern_pair.first.IsValid()) {
277        VLOG(1) << "Ignoring invalid content settings pattern: " <<
278                   original_pattern_str;
279        continue;
280      }
281
282      ContentSettingsType content_type =
283          kPrefsForManagedContentSettingsMap[i].content_type;
284      DCHECK_NE(content_type, CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE);
285      // If only one pattern was defined auto expand it to a pattern pair.
286      ContentSettingsPattern secondary_pattern =
287          !pattern_pair.second.IsValid() ? ContentSettingsPattern::Wildcard()
288                                         : pattern_pair.second;
289      value_map->SetValue(
290          pattern_pair.first,
291          secondary_pattern,
292          content_type,
293          NO_RESOURCE_IDENTIFIER,
294          base::Value::CreateIntegerValue(
295              kPrefsForManagedContentSettingsMap[i].setting));
296    }
297  }
298}
299
300void PolicyProvider::GetAutoSelectCertificateSettingsFromPreferences(
301    OriginIdentifierValueMap* value_map) {
302  const char* pref_name = prefs::kManagedAutoSelectCertificateForUrls;
303
304  if (!prefs_->HasPrefPath(pref_name)) {
305    VLOG(2) << "Skipping unset preference: " << pref_name;
306    return;
307  }
308
309  const PrefService::Preference* pref = prefs_->FindPreference(pref_name);
310  DCHECK(pref);
311  DCHECK(pref->IsManaged());
312
313  const base::ListValue* pattern_filter_str_list = NULL;
314  if (!pref->GetValue()->GetAsList(&pattern_filter_str_list)) {
315    NOTREACHED();
316    return;
317  }
318
319  // Parse the list of pattern filter strings. A pattern filter string has
320  // the following JSON format:
321  //
322  // {
323  //   "pattern": <content settings pattern string>,
324  //   "filter" : <certificate filter in JSON format>
325  // }
326  //
327  // e.g.
328  // {
329  //   "pattern": "[*.]example.com",
330  //   "filter": {
331  //      "ISSUER": {
332  //        "CN": "some name"
333  //      }
334  //   }
335  // }
336  for (size_t j = 0; j < pattern_filter_str_list->GetSize(); ++j) {
337    std::string pattern_filter_json;
338    if (!pattern_filter_str_list->GetString(j, &pattern_filter_json)) {
339      NOTREACHED();
340      continue;
341    }
342
343    scoped_ptr<base::Value> value(base::JSONReader::Read(pattern_filter_json,
344        base::JSON_ALLOW_TRAILING_COMMAS));
345    if (!value || !value->IsType(base::Value::TYPE_DICTIONARY)) {
346      VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:"
347                 " Invalid JSON object: " << pattern_filter_json;
348      continue;
349    }
350
351    scoped_ptr<base::DictionaryValue> pattern_filter_pair(
352        static_cast<base::DictionaryValue*>(value.release()));
353    std::string pattern_str;
354    bool pattern_read = pattern_filter_pair->GetString("pattern", &pattern_str);
355    scoped_ptr<base::Value> cert_filter;
356    bool filter_read = pattern_filter_pair->Remove("filter", &cert_filter);
357    if (!pattern_read || !filter_read ||
358        !cert_filter->IsType(base::Value::TYPE_DICTIONARY)) {
359      VLOG(1) << "Ignoring invalid certificate auto select setting. Reason:"
360                 " Missing pattern or filter.";
361      continue;
362    }
363
364    ContentSettingsPattern pattern =
365        ContentSettingsPattern::FromString(pattern_str);
366    // Ignore invalid patterns.
367    if (!pattern.IsValid()) {
368      VLOG(1) << "Ignoring invalid certificate auto select setting:"
369                 " Invalid content settings pattern: " << pattern;
370      continue;
371    }
372
373    value_map->SetValue(pattern,
374                        ContentSettingsPattern::Wildcard(),
375                        CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
376                        std::string(),
377                        cert_filter.release());
378  }
379}
380
381void PolicyProvider::ReadManagedDefaultSettings() {
382  for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) {
383    if (kPrefToManageType[type] == NULL) {
384      continue;
385    }
386    UpdateManagedDefaultSetting(ContentSettingsType(type));
387  }
388}
389
390void PolicyProvider::UpdateManagedDefaultSetting(
391    ContentSettingsType content_type) {
392  // If a pref to manage a default-content-setting was not set (NOTICE:
393  // "HasPrefPath" returns false if no value was set for a registered pref) then
394  // the default value of the preference is used. The default value of a
395  // preference to manage a default-content-settings is CONTENT_SETTING_DEFAULT.
396  // This indicates that no managed value is set. If a pref was set, than it
397  // MUST be managed.
398  DCHECK(!prefs_->HasPrefPath(kPrefToManageType[content_type]) ||
399          prefs_->IsManagedPreference(kPrefToManageType[content_type]));
400  base::AutoLock auto_lock(lock_);
401
402  int setting = prefs_->GetInteger(kPrefToManageType[content_type]);
403  if (setting == CONTENT_SETTING_DEFAULT) {
404    value_map_.DeleteValue(
405        ContentSettingsPattern::Wildcard(),
406        ContentSettingsPattern::Wildcard(),
407        content_type,
408        std::string());
409  } else {
410    value_map_.SetValue(
411        ContentSettingsPattern::Wildcard(),
412        ContentSettingsPattern::Wildcard(),
413        content_type,
414        std::string(),
415        Value::CreateIntegerValue(setting));
416  }
417}
418
419
420void PolicyProvider::ReadManagedContentSettings(bool overwrite) {
421  base::AutoLock auto_lock(lock_);
422  if (overwrite)
423    value_map_.clear();
424  GetContentSettingsFromPreferences(&value_map_);
425  GetAutoSelectCertificateSettingsFromPreferences(&value_map_);
426}
427
428// Since the PolicyProvider is a read only content settings provider, all
429// methodes of the ProviderInterface that set or delete any settings do nothing.
430bool PolicyProvider::SetWebsiteSetting(
431    const ContentSettingsPattern& primary_pattern,
432    const ContentSettingsPattern& secondary_pattern,
433    ContentSettingsType content_type,
434    const ResourceIdentifier& resource_identifier,
435    Value* value) {
436  return false;
437}
438
439void PolicyProvider::ClearAllContentSettingsRules(
440    ContentSettingsType content_type) {
441}
442
443void PolicyProvider::ShutdownOnUIThread() {
444  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
445  RemoveAllObservers();
446  if (!prefs_)
447    return;
448  pref_change_registrar_.RemoveAll();
449  prefs_ = NULL;
450}
451
452void PolicyProvider::OnPreferenceChanged(const std::string& name) {
453  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
454
455  if (name == prefs::kManagedDefaultCookiesSetting) {
456    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES);
457  } else if (name == prefs::kManagedDefaultImagesSetting) {
458    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_IMAGES);
459  } else if (name == prefs::kManagedDefaultJavaScriptSetting) {
460    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
461  } else if (name == prefs::kManagedDefaultPluginsSetting) {
462    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
463  } else if (name == prefs::kManagedDefaultPopupsSetting) {
464    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS);
465  } else if (name == prefs::kManagedDefaultGeolocationSetting) {
466    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_GEOLOCATION);
467  } else if (name == prefs::kManagedDefaultNotificationsSetting) {
468    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
469  } else if (name == prefs::kManagedDefaultMediaStreamSetting) {
470    UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
471  } else if (name == prefs::kManagedAutoSelectCertificateForUrls ||
472             name == prefs::kManagedCookiesAllowedForUrls ||
473             name == prefs::kManagedCookiesBlockedForUrls ||
474             name == prefs::kManagedCookiesSessionOnlyForUrls ||
475             name == prefs::kManagedImagesAllowedForUrls ||
476             name == prefs::kManagedImagesBlockedForUrls ||
477             name == prefs::kManagedJavaScriptAllowedForUrls ||
478             name == prefs::kManagedJavaScriptBlockedForUrls ||
479             name == prefs::kManagedPluginsAllowedForUrls ||
480             name == prefs::kManagedPluginsBlockedForUrls ||
481             name == prefs::kManagedPopupsAllowedForUrls ||
482             name == prefs::kManagedPopupsBlockedForUrls ||
483             name == prefs::kManagedNotificationsAllowedForUrls ||
484             name == prefs::kManagedNotificationsBlockedForUrls) {
485    ReadManagedContentSettings(true);
486    ReadManagedDefaultSettings();
487  }
488
489  NotifyObservers(ContentSettingsPattern(),
490                  ContentSettingsPattern(),
491                  CONTENT_SETTINGS_TYPE_DEFAULT,
492                  std::string());
493}
494
495}  // namespace content_settings
496