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