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