1 // Copyright (c) 2011 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/command_line.h"
11 #include "chrome/browser/content_settings/content_settings_details.h"
12 #include "chrome/browser/content_settings/content_settings_pattern.h"
13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/prefs/scoped_user_pref_update.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/pref_names.h"
17 #include "content/browser/browser_thread.h"
18 #include "content/common/notification_details.h"
19 #include "content/common/notification_service.h"
20 #include "content/common/notification_source.h"
21 #include "webkit/plugins/npapi/plugin_group.h"
22 #include "webkit/plugins/npapi/plugin_list.h"
23
24 namespace {
25
26 // Base pref path of the prefs that contain the managed default content
27 // settings values.
28 const std::string kManagedSettings =
29 "profile.managed_default_content_settings";
30
31 // The preferences used to manage ContentSettingsTypes.
32 const char* kPrefToManageType[CONTENT_SETTINGS_NUM_TYPES] = {
33 prefs::kManagedDefaultCookiesSetting,
34 prefs::kManagedDefaultImagesSetting,
35 prefs::kManagedDefaultJavaScriptSetting,
36 prefs::kManagedDefaultPluginsSetting,
37 prefs::kManagedDefaultPopupsSetting,
38 NULL, // Not used for Geolocation
39 NULL, // Not used for Notifications
40 };
41
42 struct PrefsForManagedContentSettingsMapEntry {
43 const char* pref_name;
44 ContentSettingsType content_type;
45 ContentSetting setting;
46 };
47
48 const PrefsForManagedContentSettingsMapEntry
49 kPrefsForManagedContentSettingsMap[] = {
50 {
51 prefs::kManagedCookiesAllowedForUrls,
52 CONTENT_SETTINGS_TYPE_COOKIES,
53 CONTENT_SETTING_ALLOW
54 }, {
55 prefs::kManagedCookiesSessionOnlyForUrls,
56 CONTENT_SETTINGS_TYPE_COOKIES,
57 CONTENT_SETTING_SESSION_ONLY
58 }, {
59 prefs::kManagedCookiesBlockedForUrls,
60 CONTENT_SETTINGS_TYPE_COOKIES,
61 CONTENT_SETTING_BLOCK
62 }, {
63 prefs::kManagedImagesAllowedForUrls,
64 CONTENT_SETTINGS_TYPE_IMAGES,
65 CONTENT_SETTING_ALLOW
66 }, {
67 prefs::kManagedImagesBlockedForUrls,
68 CONTENT_SETTINGS_TYPE_IMAGES,
69 CONTENT_SETTING_BLOCK
70 }, {
71 prefs::kManagedJavaScriptAllowedForUrls,
72 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
73 CONTENT_SETTING_ALLOW
74 }, {
75 prefs::kManagedJavaScriptBlockedForUrls,
76 CONTENT_SETTINGS_TYPE_JAVASCRIPT,
77 CONTENT_SETTING_BLOCK
78 }, {
79 prefs::kManagedPluginsAllowedForUrls,
80 CONTENT_SETTINGS_TYPE_PLUGINS,
81 CONTENT_SETTING_ALLOW
82 }, {
83 prefs::kManagedPluginsBlockedForUrls,
84 CONTENT_SETTINGS_TYPE_PLUGINS,
85 CONTENT_SETTING_BLOCK
86 }, {
87 prefs::kManagedPopupsAllowedForUrls,
88 CONTENT_SETTINGS_TYPE_POPUPS,
89 CONTENT_SETTING_ALLOW
90 }, {
91 prefs::kManagedPopupsBlockedForUrls,
92 CONTENT_SETTINGS_TYPE_POPUPS,
93 CONTENT_SETTING_BLOCK
94 }
95 };
96
97 } // namespace
98
99 namespace content_settings {
100
PolicyDefaultProvider(Profile * profile)101 PolicyDefaultProvider::PolicyDefaultProvider(Profile* profile)
102 : profile_(profile),
103 is_off_the_record_(profile_->IsOffTheRecord()) {
104 PrefService* prefs = profile->GetPrefs();
105
106 // Read global defaults.
107 DCHECK_EQ(arraysize(kPrefToManageType),
108 static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
109 ReadManagedDefaultSettings();
110
111 pref_change_registrar_.Init(prefs);
112 // The following preferences are only used to indicate if a
113 // default-content-setting is managed and to hold the managed default-setting
114 // value. If the value for any of the following perferences is set then the
115 // corresponding default-content-setting is managed. These preferences exist
116 // in parallel to the preference default-content-settings. If a
117 // default-content-settings-type is managed any user defined excpetions
118 // (patterns) for this type are ignored.
119 pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this);
120 pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this);
121 pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this);
122 pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this);
123 pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this);
124 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
125 Source<Profile>(profile_));
126 }
127
~PolicyDefaultProvider()128 PolicyDefaultProvider::~PolicyDefaultProvider() {
129 UnregisterObservers();
130 }
131
ProvideDefaultSetting(ContentSettingsType content_type) const132 ContentSetting PolicyDefaultProvider::ProvideDefaultSetting(
133 ContentSettingsType content_type) const {
134 base::AutoLock auto_lock(lock_);
135 return managed_default_content_settings_.settings[content_type];
136 }
137
UpdateDefaultSetting(ContentSettingsType content_type,ContentSetting setting)138 void PolicyDefaultProvider::UpdateDefaultSetting(
139 ContentSettingsType content_type,
140 ContentSetting setting) {
141 }
142
DefaultSettingIsManaged(ContentSettingsType content_type) const143 bool PolicyDefaultProvider::DefaultSettingIsManaged(
144 ContentSettingsType content_type) const {
145 base::AutoLock lock(lock_);
146 if (managed_default_content_settings_.settings[content_type] !=
147 CONTENT_SETTING_DEFAULT) {
148 return true;
149 } else {
150 return false;
151 }
152 }
153
ResetToDefaults()154 void PolicyDefaultProvider::ResetToDefaults() {
155 }
156
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)157 void PolicyDefaultProvider::Observe(NotificationType type,
158 const NotificationSource& source,
159 const NotificationDetails& details) {
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161
162 if (type == NotificationType::PREF_CHANGED) {
163 DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr());
164 std::string* name = Details<std::string>(details).ptr();
165 if (*name == prefs::kManagedDefaultCookiesSetting) {
166 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_COOKIES);
167 } else if (*name == prefs::kManagedDefaultImagesSetting) {
168 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_IMAGES);
169 } else if (*name == prefs::kManagedDefaultJavaScriptSetting) {
170 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
171 } else if (*name == prefs::kManagedDefaultPluginsSetting) {
172 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_PLUGINS);
173 } else if (*name == prefs::kManagedDefaultPopupsSetting) {
174 UpdateManagedDefaultSetting(CONTENT_SETTINGS_TYPE_POPUPS);
175 } else {
176 NOTREACHED() << "Unexpected preference observed";
177 return;
178 }
179
180 if (!is_off_the_record_) {
181 NotifyObservers(ContentSettingsDetails(
182 ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, ""));
183 }
184 } else if (type == NotificationType::PROFILE_DESTROYED) {
185 DCHECK_EQ(profile_, Source<Profile>(source).ptr());
186 UnregisterObservers();
187 } else {
188 NOTREACHED() << "Unexpected notification";
189 }
190 }
191
UnregisterObservers()192 void PolicyDefaultProvider::UnregisterObservers() {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194 if (!profile_)
195 return;
196 pref_change_registrar_.RemoveAll();
197 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
198 Source<Profile>(profile_));
199 profile_ = NULL;
200 }
201
202
NotifyObservers(const ContentSettingsDetails & details)203 void PolicyDefaultProvider::NotifyObservers(
204 const ContentSettingsDetails& details) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
206 if (profile_ == NULL)
207 return;
208 NotificationService::current()->Notify(
209 NotificationType::CONTENT_SETTINGS_CHANGED,
210 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()),
211 Details<const ContentSettingsDetails>(&details));
212 }
213
ReadManagedDefaultSettings()214 void PolicyDefaultProvider::ReadManagedDefaultSettings() {
215 for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) {
216 if (kPrefToManageType[type] == NULL) {
217 continue;
218 }
219 UpdateManagedDefaultSetting(ContentSettingsType(type));
220 }
221 }
222
UpdateManagedDefaultSetting(ContentSettingsType type)223 void PolicyDefaultProvider::UpdateManagedDefaultSetting(
224 ContentSettingsType type) {
225 // If a pref to manage a default-content-setting was not set (NOTICE:
226 // "HasPrefPath" returns false if no value was set for a registered pref) then
227 // the default value of the preference is used. The default value of a
228 // preference to manage a default-content-settings is CONTENT_SETTING_DEFAULT.
229 // This indicates that no managed value is set. If a pref was set, than it
230 // MUST be managed.
231 PrefService* prefs = profile_->GetPrefs();
232 DCHECK(!prefs->HasPrefPath(kPrefToManageType[type]) ||
233 prefs->IsManagedPreference(kPrefToManageType[type]));
234 base::AutoLock auto_lock(lock_);
235 managed_default_content_settings_.settings[type] = IntToContentSetting(
236 prefs->GetInteger(kPrefToManageType[type]));
237 }
238
239 // static
RegisterUserPrefs(PrefService * prefs)240 void PolicyDefaultProvider::RegisterUserPrefs(PrefService* prefs) {
241 // Preferences for default content setting policies. A policy is not set of
242 // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT.
243 prefs->RegisterIntegerPref(prefs::kManagedDefaultCookiesSetting,
244 CONTENT_SETTING_DEFAULT);
245 prefs->RegisterIntegerPref(prefs::kManagedDefaultImagesSetting,
246 CONTENT_SETTING_DEFAULT);
247 prefs->RegisterIntegerPref(prefs::kManagedDefaultJavaScriptSetting,
248 CONTENT_SETTING_DEFAULT);
249 prefs->RegisterIntegerPref(prefs::kManagedDefaultPluginsSetting,
250 CONTENT_SETTING_DEFAULT);
251 prefs->RegisterIntegerPref(prefs::kManagedDefaultPopupsSetting,
252 CONTENT_SETTING_DEFAULT);
253 }
254
255 // ////////////////////////////////////////////////////////////////////////////
256 // PolicyProvider
257
258 // static
RegisterUserPrefs(PrefService * prefs)259 void PolicyProvider::RegisterUserPrefs(PrefService* prefs) {
260 prefs->RegisterListPref(prefs::kManagedCookiesAllowedForUrls);
261 prefs->RegisterListPref(prefs::kManagedCookiesBlockedForUrls);
262 prefs->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls);
263 prefs->RegisterListPref(prefs::kManagedImagesAllowedForUrls);
264 prefs->RegisterListPref(prefs::kManagedImagesBlockedForUrls);
265 prefs->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls);
266 prefs->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls);
267 prefs->RegisterListPref(prefs::kManagedPluginsAllowedForUrls);
268 prefs->RegisterListPref(prefs::kManagedPluginsBlockedForUrls);
269 prefs->RegisterListPref(prefs::kManagedPopupsAllowedForUrls);
270 prefs->RegisterListPref(prefs::kManagedPopupsBlockedForUrls);
271 }
272
PolicyProvider(Profile * profile)273 PolicyProvider::PolicyProvider(Profile* profile)
274 : BaseProvider(profile->IsOffTheRecord()),
275 profile_(profile) {
276 Init();
277 }
278
~PolicyProvider()279 PolicyProvider::~PolicyProvider() {
280 UnregisterObservers();
281 }
282
ReadManagedContentSettingsTypes(ContentSettingsType content_type)283 void PolicyProvider::ReadManagedContentSettingsTypes(
284 ContentSettingsType content_type) {
285 PrefService* prefs = profile_->GetPrefs();
286 if (kPrefToManageType[content_type] == NULL) {
287 content_type_is_managed_[content_type] = false;
288 } else {
289 content_type_is_managed_[content_type] =
290 prefs->IsManagedPreference(kPrefToManageType[content_type]);
291 }
292 }
293
Init()294 void PolicyProvider::Init() {
295 PrefService* prefs = profile_->GetPrefs();
296
297 ReadManagedContentSettings(false);
298 for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i)
299 ReadManagedContentSettingsTypes(ContentSettingsType(i));
300
301 pref_change_registrar_.Init(prefs);
302 pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, this);
303 pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, this);
304 pref_change_registrar_.Add(prefs::kManagedCookiesSessionOnlyForUrls, this);
305 pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, this);
306 pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, this);
307 pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, this);
308 pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, this);
309 pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, this);
310 pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, this);
311 pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, this);
312 pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, this);
313
314 pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this);
315 pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this);
316 pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this);
317 pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this);
318 pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this);
319
320 notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED,
321 Source<Profile>(profile_));
322 }
323
ContentSettingsTypeIsManaged(ContentSettingsType content_type)324 bool PolicyProvider::ContentSettingsTypeIsManaged(
325 ContentSettingsType content_type) {
326 return content_type_is_managed_[content_type];
327 }
328
GetContentSettingsFromPreferences(PrefService * prefs,ContentSettingsRules * rules)329 void PolicyProvider::GetContentSettingsFromPreferences(
330 PrefService* prefs,
331 ContentSettingsRules* rules) {
332 for (size_t i = 0; i < arraysize(kPrefsForManagedContentSettingsMap); ++i) {
333 const char* pref_name = kPrefsForManagedContentSettingsMap[i].pref_name;
334 // Skip unset policies.
335 if (!prefs->HasPrefPath(pref_name)) {
336 VLOG(2) << "Skipping unset preference: " << pref_name;
337 continue;
338 }
339
340 const PrefService::Preference* pref = prefs->FindPreference(pref_name);
341 DCHECK(pref->IsManaged());
342 DCHECK_EQ(Value::TYPE_LIST, pref->GetType());
343
344 const ListValue* pattern_str_list =
345 static_cast<const ListValue*>(pref->GetValue());
346 for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) {
347 std::string original_pattern_str;
348 pattern_str_list->GetString(j, &original_pattern_str);
349 ContentSettingsPattern pattern(original_pattern_str);
350 // Ignore invalid patterns.
351 if (!pattern.IsValid()) {
352 VLOG(1) << "Ignoring invalid content settings pattern: " <<
353 pattern.AsString();
354 continue;
355 }
356 rules->push_back(MakeTuple(
357 pattern,
358 pattern,
359 kPrefsForManagedContentSettingsMap[i].content_type,
360 ProviderInterface::ResourceIdentifier(NO_RESOURCE_IDENTIFIER),
361 kPrefsForManagedContentSettingsMap[i].setting));
362 }
363 }
364 }
365
ReadManagedContentSettings(bool overwrite)366 void PolicyProvider::ReadManagedContentSettings(bool overwrite) {
367 ContentSettingsRules rules;
368 PrefService* prefs = profile_->GetPrefs();
369 GetContentSettingsFromPreferences(prefs, &rules);
370 {
371 base::AutoLock auto_lock(lock());
372 HostContentSettings* content_settings_map = host_content_settings();
373 if (overwrite)
374 content_settings_map->clear();
375 for (ContentSettingsRules::iterator rule = rules.begin();
376 rule != rules.end();
377 ++rule) {
378 DispatchToMethod(this, &PolicyProvider::UpdateContentSettingsMap, *rule);
379 }
380 }
381 }
382
383 // Since the PolicyProvider is a read only content settings provider, all
384 // methodes of the ProviderInterface that set or delete any settings do nothing.
SetContentSetting(const ContentSettingsPattern & requesting_pattern,const ContentSettingsPattern & embedding_pattern,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,ContentSetting content_setting)385 void PolicyProvider::SetContentSetting(
386 const ContentSettingsPattern& requesting_pattern,
387 const ContentSettingsPattern& embedding_pattern,
388 ContentSettingsType content_type,
389 const ResourceIdentifier& resource_identifier,
390 ContentSetting content_setting) {
391 }
392
GetContentSetting(const GURL & requesting_url,const GURL & embedding_url,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier) const393 ContentSetting PolicyProvider::GetContentSetting(
394 const GURL& requesting_url,
395 const GURL& embedding_url,
396 ContentSettingsType content_type,
397 const ResourceIdentifier& resource_identifier) const {
398 return BaseProvider::GetContentSetting(
399 requesting_url,
400 embedding_url,
401 content_type,
402 NO_RESOURCE_IDENTIFIER);
403 }
404
ClearAllContentSettingsRules(ContentSettingsType content_type)405 void PolicyProvider::ClearAllContentSettingsRules(
406 ContentSettingsType content_type) {
407 }
408
ResetToDefaults()409 void PolicyProvider::ResetToDefaults() {
410 }
411
UnregisterObservers()412 void PolicyProvider::UnregisterObservers() {
413 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
414 if (!profile_)
415 return;
416 pref_change_registrar_.RemoveAll();
417 notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED,
418 Source<Profile>(profile_));
419 profile_ = NULL;
420 }
421
NotifyObservers(const ContentSettingsDetails & details)422 void PolicyProvider::NotifyObservers(
423 const ContentSettingsDetails& details) {
424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
425 if (profile_ == NULL)
426 return;
427 NotificationService::current()->Notify(
428 NotificationType::CONTENT_SETTINGS_CHANGED,
429 Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()),
430 Details<const ContentSettingsDetails>(&details));
431 }
432
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)433 void PolicyProvider::Observe(NotificationType type,
434 const NotificationSource& source,
435 const NotificationDetails& details) {
436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
437
438 if (type == NotificationType::PREF_CHANGED) {
439 DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr());
440 std::string* name = Details<std::string>(details).ptr();
441 if (*name == prefs::kManagedCookiesAllowedForUrls ||
442 *name == prefs::kManagedCookiesBlockedForUrls ||
443 *name == prefs::kManagedCookiesSessionOnlyForUrls ||
444 *name == prefs::kManagedImagesAllowedForUrls ||
445 *name == prefs::kManagedImagesBlockedForUrls ||
446 *name == prefs::kManagedJavaScriptAllowedForUrls ||
447 *name == prefs::kManagedJavaScriptBlockedForUrls ||
448 *name == prefs::kManagedPluginsAllowedForUrls ||
449 *name == prefs::kManagedPluginsBlockedForUrls ||
450 *name == prefs::kManagedPopupsAllowedForUrls ||
451 *name == prefs::kManagedPopupsBlockedForUrls) {
452 ReadManagedContentSettings(true);
453 NotifyObservers(ContentSettingsDetails(
454 ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, ""));
455 // We do not want to sent a notification when managed default content
456 // settings change. The DefaultProvider will take care of that. We are
457 // only a passive observer.
458 // TODO(markusheintz): NOTICE: This is still work in progress and part of
459 // a larger refactoring. The code will change and be much cleaner and
460 // clearer in the end.
461 } else if (*name == prefs::kManagedDefaultCookiesSetting) {
462 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_COOKIES);
463 } else if (*name == prefs::kManagedDefaultImagesSetting) {
464 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_IMAGES);
465 } else if (*name == prefs::kManagedDefaultJavaScriptSetting) {
466 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_JAVASCRIPT);
467 } else if (*name == prefs::kManagedDefaultPluginsSetting) {
468 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_PLUGINS);
469 } else if (*name == prefs::kManagedDefaultPopupsSetting) {
470 ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_POPUPS);
471 }
472 } else if (type == NotificationType::PROFILE_DESTROYED) {
473 DCHECK_EQ(profile_, Source<Profile>(source).ptr());
474 UnregisterObservers();
475 } else {
476 NOTREACHED() << "Unexpected notification";
477 }
478 }
479
480 } // namespace content_settings
481