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