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