Chromium Code Reviews| Index: chrome/browser/content_settings/content_settings_policy_provider.cc |
| diff --git a/chrome/browser/content_settings/content_settings_policy_provider.cc b/chrome/browser/content_settings/content_settings_policy_provider.cc |
| index 1055cee611fc2a920eb479918c2ae8590288efdd..6aabc6febeddbcadea08aa6aa34543cd9a32a329 100644 |
| --- a/chrome/browser/content_settings/content_settings_policy_provider.cc |
| +++ b/chrome/browser/content_settings/content_settings_policy_provider.cc |
| @@ -7,6 +7,7 @@ |
| #include <string> |
| #include "base/command_line.h" |
| +#include "base/tuple.h" |
| #include "chrome/browser/browser_thread.h" |
| #include "chrome/browser/content_settings/content_settings_details.h" |
| #include "chrome/browser/content_settings/content_settings_pattern.h" |
| @@ -18,6 +19,9 @@ |
| #include "chrome/common/notification_source.h" |
| #include "chrome/common/pref_names.h" |
| +#include "webkit/plugins/npapi/plugin_group.h" |
| +#include "webkit/plugins/npapi/plugin_list.h" |
| + |
| namespace { |
| // Base pref path of the prefs that contain the managed default content |
| @@ -36,6 +40,65 @@ const char* kPrefToManageType[CONTENT_SETTINGS_NUM_TYPES] = { |
| NULL, // Not used for Notifications |
| }; |
| +struct PrefsForManagedContentSettingsMapEntry { |
| + const char* pref_name; |
| + ContentSettingsType content_type; |
| + ContentSetting setting; |
| +}; |
| + |
| +const PrefsForManagedContentSettingsMapEntry |
| + kPrefsForManagedContentSettingsMap[] = { |
| + { |
| + prefs::kManagedCookiesAllowedForUrls, |
| + CONTENT_SETTINGS_TYPE_COOKIES, |
| + CONTENT_SETTING_ALLOW |
| + }, { |
| + prefs::kManagedCookiesBlockedForUrls, |
| + CONTENT_SETTINGS_TYPE_COOKIES, |
| + CONTENT_SETTING_BLOCK |
| + }, { |
| + prefs::kManagedCookiesSessionOnlyForUrls, |
| + CONTENT_SETTINGS_TYPE_COOKIES, |
| + CONTENT_SETTING_SESSION_ONLY |
| + }, { |
| + prefs::kManagedImagesAllowedForUrls, |
| + CONTENT_SETTINGS_TYPE_IMAGES, |
| + CONTENT_SETTING_ALLOW |
| + }, { |
| + prefs::kManagedImagesBlockedForUrls, |
| + CONTENT_SETTINGS_TYPE_IMAGES, |
| + CONTENT_SETTING_BLOCK |
| + }, { |
| + prefs::kManagedJavaScriptAllowedForUrls, |
| + CONTENT_SETTINGS_TYPE_JAVASCRIPT, |
| + CONTENT_SETTING_ALLOW |
| + }, { |
| + prefs::kManagedJavaScriptBlockedForUrls, |
| + CONTENT_SETTINGS_TYPE_JAVASCRIPT, |
| + CONTENT_SETTING_BLOCK |
| + }, { |
| + prefs::kManagedPluginsAllowedForUrls, |
| + CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_ALLOW |
| + }, { |
| + prefs::kManagedPluginsBlockedForUrls, |
| + CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_BLOCK |
| + }, { |
| + prefs::kManagedPluginsAskForUrls, |
| + CONTENT_SETTINGS_TYPE_PLUGINS, |
| + CONTENT_SETTING_ASK |
| + }, { |
| + prefs::kManagedPopupsAllowedForUrls, |
| + CONTENT_SETTINGS_TYPE_POPUPS, |
| + CONTENT_SETTING_ALLOW |
| + }, { |
| + prefs::kManagedPopupsBlockedForUrls, |
| + CONTENT_SETTINGS_TYPE_POPUPS, |
| + CONTENT_SETTING_BLOCK |
| + } |
| +}; |
| + |
| } // namespace |
| namespace content_settings { |
| @@ -156,7 +219,6 @@ void PolicyDefaultProvider::NotifyObservers( |
| void PolicyDefaultProvider::ReadManagedDefaultSettings() { |
| for (size_t type = 0; type < arraysize(kPrefToManageType); ++type) { |
| if (kPrefToManageType[type] == NULL) { |
| - // TODO(markusheintz): Handle Geolocation and notification separately. |
| continue; |
| } |
| UpdateManagedDefaultSetting(ContentSettingsType(type)); |
| @@ -195,4 +257,321 @@ void PolicyDefaultProvider::RegisterUserPrefs(PrefService* prefs) { |
| CONTENT_SETTING_DEFAULT); |
| } |
| +// //////////////////////////////////////////////////////////////////////////// |
| +// PolicyProvider |
| + |
| +// static |
| +void PolicyProvider::RegisterUserPrefs(PrefService* prefs) { |
| + prefs->RegisterListPref(prefs::kManagedCookiesAllowedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedCookiesBlockedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls); |
| + prefs->RegisterListPref(prefs::kManagedImagesAllowedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedImagesBlockedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedPluginsAllowedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedPluginsBlockedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedPluginsAskForUrls); |
| + prefs->RegisterListPref(prefs::kManagedPopupsAllowedForUrls); |
| + prefs->RegisterListPref(prefs::kManagedPopupsBlockedForUrls); |
| +} |
| + |
| +PolicyProvider::PolicyProvider(Profile* profile) |
| + : BaseProvider(profile->IsOffTheRecord()), |
| + profile_(profile) { |
| + Init(); |
| +} |
| + |
| +PolicyProvider::~PolicyProvider() { |
| + UnregisterObservers(); |
| +} |
| + |
| +void PolicyProvider::ReadManagedContentSettingsTypes( |
| + ContentSettingsType content_type) { |
| + PrefService* prefs = profile_->GetPrefs(); |
| + if (kPrefToManageType[content_type] == NULL) { |
| + content_type_is_managed_[content_type] = false; |
| + } else { |
| + content_type_is_managed_[content_type] = |
| + prefs->IsManagedPreference(kPrefToManageType[content_type]); |
| + } |
| +} |
| + |
| +void PolicyProvider::Init() { |
| + PrefService* prefs = profile_->GetPrefs(); |
| + |
| + ReadManagedContentSettings(false); |
| + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) |
| + ReadManagedContentSettingsTypes(ContentSettingsType(i)); |
| + |
| + pref_change_registrar_.Init(prefs); |
| + pref_change_registrar_.Add(prefs::kManagedCookiesBlockedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedCookiesAllowedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedCookiesSessionOnlyForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedImagesBlockedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedImagesAllowedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedJavaScriptBlockedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedJavaScriptAllowedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedPluginsBlockedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedPluginsAllowedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedPluginsAskForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedPopupsBlockedForUrls, this); |
| + pref_change_registrar_.Add(prefs::kManagedPopupsAllowedForUrls, this); |
| + |
| + pref_change_registrar_.Add(prefs::kManagedDefaultCookiesSetting, this); |
| + pref_change_registrar_.Add(prefs::kManagedDefaultImagesSetting, this); |
| + pref_change_registrar_.Add(prefs::kManagedDefaultJavaScriptSetting, this); |
| + pref_change_registrar_.Add(prefs::kManagedDefaultPluginsSetting, this); |
| + pref_change_registrar_.Add(prefs::kManagedDefaultPopupsSetting, this); |
| + |
| + notification_registrar_.Add(this, NotificationType::PROFILE_DESTROYED, |
| + Source<Profile>(profile_)); |
| +} |
| + |
| +bool PolicyProvider::ContentSettingsTypeIsManaged( |
| + ContentSettingsType content_type) { |
| + return content_type_is_managed_[content_type]; |
| +} |
| + |
| +namespace { |
| + |
| +typedef Tuple5< |
| + ContentSettingsPattern, |
| + ContentSettingsPattern, |
| + ContentSettingsType, |
| + ProviderInterface::ResourceIdentifier, |
| + ContentSetting> ContentSettingsRule; |
| + |
| +typedef std::vector<ContentSettingsRule> ContentSettingsRules; |
| + |
| +const std::string WILDCARD = "*"; |
| +const std::string SEPERATOR = ":"; |
| +const std::string NO_IDENTIFIER = ""; |
| + |
| +} // namespace |
| + |
| + |
| +void PolicyProvider::ReadManagedContentSettings(bool overwrite) { |
| + ContentSettingsRules rules; |
| + |
| + // Load managed content settings patterns from preferences. |
| + PrefService* prefs = profile_->GetPrefs(); |
| + for (size_t i = 0; i < arraysize(kPrefsForManagedContentSettingsMap); ++i) { |
| + const char* pref_name = kPrefsForManagedContentSettingsMap[i].pref_name; |
| + // Skip unset policies. |
| + if (!prefs->HasPrefPath(pref_name)) |
| + continue; |
| + |
| + const PrefService::Preference* pref = prefs->FindPreference(pref_name); |
| + DCHECK(pref->IsManaged()); |
| + DCHECK_EQ(Value::TYPE_LIST, pref->GetType()); |
| + |
| + const ListValue* pattern_str_list = |
| + static_cast<const ListValue*>(pref->GetValue()); |
| + for (size_t j = 0; j < pattern_str_list->GetSize(); ++j) { |
| + std::string original_pattern_str; |
| + pattern_str_list->GetString(j, &original_pattern_str); |
| + |
| + // Check if a resource identifier is in the pattern string. |
| + |
| + // For content_types that require a resource identifier extract the |
| + // resource identifier from the pattern. |
| + // <resource_identifier>:<content_settings_pattern> |
| + std::string resource_identifier(NO_IDENTIFIER); |
| + size_t separator_pos = original_pattern_str.find(SEPERATOR); |
| + if (!separator_pos == std::string::npos) { |
| + int resource_identifier_length = separator_pos + 1; |
| + resource_identifier = |
| + original_pattern_str.substr(0, resource_identifier_length); |
| + // TODO(markusheintz): Normalize resource_identifier. |
| + original_pattern_str.erase(0, resource_identifier_length); |
| + } |
| + |
| + // If a resource identifier is required but no resource identifier is |
| + // specified use the wildcard identifier. |
| + if (RequiresResourceIdentifier( |
| + kPrefsForManagedContentSettingsMap[i].content_type) && |
| + resource_identifier == NO_IDENTIFIER) { |
| + resource_identifier = WILDCARD; |
| + LOG(WARNING) << "Managed content settings for " |
| + << original_pattern_str << ": Content type " |
| + << kPrefsForManagedContentSettingsMap[i].content_type |
| + << " requires a resource identifer, but none was" |
| + << "specified. Useing resource identifier wildcard."; |
| + } |
| + |
| + // TODO(markusheintz): If a resource identifier is not required but |
| + // specified, collapse the rules for different resource identifiers into |
| + // one single rule and use the most restrictive content setting. |
| + if (!RequiresResourceIdentifier( |
| + kPrefsForManagedContentSettingsMap[i].content_type) && |
| + resource_identifier != NO_IDENTIFIER) { |
| + // Ignore rule for now. |
| + LOG(WARNING) << "Ignoring content settings pattern " |
| + << original_pattern_str |
| + << " because a resource identifier is given but not" |
| + << " required"; |
| + continue; |
| + } |
| + |
| + ContentSettingsPattern pattern(original_pattern_str); |
| + if (!pattern.IsValid()) { |
| + // Ignore invalid patterns |
| + LOG(WARNING) << "Ignoring invalid content settings pattern: " |
| + << pattern.AsString(); |
| + } else { |
| + rules.push_back(MakeTuple( |
| + pattern, |
| + pattern, |
| + kPrefsForManagedContentSettingsMap[i].content_type, |
| + resource_identifier, |
| + kPrefsForManagedContentSettingsMap[i].setting)); |
| + } |
| + } |
| + } |
| + |
| + // Perform wildcard expansions for CONTENT_SETTINGS_TYPE_PLUGINS. |
| + ContentSettingsRules rules_to_add; |
| + for (ContentSettingsRules::iterator rule = rules.begin(); |
| + rule != rules.end();) { |
| + if ((*rule).c == CONTENT_SETTINGS_TYPE_PLUGINS && |
|
Bernhard Bauer
2011/02/23 13:18:53
Nit: |rule->c| et al.
markusheintz_
2011/02/23 18:42:09
Obsolete now.
|
| + (*rule).d == WILDCARD) { |
| + // Expand wildcard resource_identifier |
| + // TODO(markusheintz): Must not be called on the UI THREAD |
| + webkit::npapi::PluginList* plugin_list = |
| + webkit::npapi::PluginList::Singleton(); |
| + std::vector<webkit::npapi::PluginGroup> plugin_groups; |
| + plugin_list->GetPluginGroups(true, &plugin_groups); |
|
Bernhard Bauer
2011/02/23 13:18:53
As discussed offline, we should do this with a di
markusheintz_
2011/02/23 18:42:09
Agree.
|
| + for (std::vector<webkit::npapi::PluginGroup>::iterator plugin_group = plugin_groups.begin(); |
| + plugin_group != plugin_groups.end(); |
| + ++plugin_group) { |
| + rules_to_add.push_back(MakeTuple( |
| + (*rule).a, |
| + (*rule).b, |
| + (*rule).c, |
| + plugin_group->identifier(), |
| + (*rule).e)); |
| + LOG(WARNING) << "Adding rule: (" |
| + << (*rule).a << ", " |
| + << (*rule).b << ", " |
| + << (*rule).c << ", " |
| + << plugin_group->identifier() << ", " |
| + << (*rule).e <<")"; |
| + } |
| + |
| + // Remove expanded rule and increment iterator. |
| + rule = rules.erase(rule); |
| + } else { |
| + ++rule; |
| + } |
| + } |
| + rules.insert(rules.end(), rules_to_add.begin(), rules_to_add.end()); |
| + |
| + // Update the host_content_settings; |
| + { |
| + base::AutoLock(lock()); |
| + HostContentSettings* content_settings_map = host_content_settings(); |
| + if (overwrite) |
| + content_settings_map->clear(); |
| + |
| + for (ContentSettingsRules::iterator rule = rules.begin(); |
| + rule != rules.end(); |
| + ++rule) { |
| + DispatchToMethod(this, &PolicyProvider::UpdateContentSettingsMap, *rule); |
| + } |
| + } |
| +} |
| + |
| +// Since the PolicyProvider is a read only content settings provider, all |
| +// methodes of the ProviderInterface that set or delete any settings do nothing. |
| +void PolicyProvider::SetContentSetting( |
| + const ContentSettingsPattern& requesting_pattern, |
| + const ContentSettingsPattern& embedding_pattern, |
| + ContentSettingsType content_type, |
| + const ResourceIdentifier& resource_identifier, |
| + ContentSetting content_setting) { |
| +} |
| + |
| +void PolicyProvider::ClearAllContentSettingsRules( |
| + ContentSettingsType content_type) { |
| +} |
| + |
| +void PolicyProvider::ResetToDefaults() { |
| +} |
| + |
| +void PolicyProvider::UnregisterObservers() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + if (!profile_) |
| + return; |
| + pref_change_registrar_.RemoveAll(); |
| + notification_registrar_.Remove(this, NotificationType::PROFILE_DESTROYED, |
| + Source<Profile>(profile_)); |
| + profile_ = NULL; |
| +} |
| + |
| +void PolicyProvider::NotifyObservers( |
| + const ContentSettingsDetails& details) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + if (profile_ == NULL) |
| + return; |
| + NotificationService::current()->Notify( |
| + NotificationType::CONTENT_SETTINGS_CHANGED, |
| + Source<HostContentSettingsMap>(profile_->GetHostContentSettingsMap()), |
| + Details<const ContentSettingsDetails>(&details)); |
| +} |
| + |
| +void PolicyProvider::Observe(NotificationType type, |
| + const NotificationSource& source, |
| + const NotificationDetails& details) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + if (type == NotificationType::PREF_CHANGED) { |
| + DCHECK_EQ(profile_->GetPrefs(), Source<PrefService>(source).ptr()); |
| + std::string* name = Details<std::string>(details).ptr(); |
| + if (*name == prefs::kManagedCookiesAllowedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedCookiesBlockedForUrls) { |
|
Bernhard Bauer
2011/02/23 13:18:53
Collapse these into one big expression?
markusheintz_
2011/02/23 18:42:09
Done.
|
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedCookiesSessionOnlyForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedImagesAllowedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedImagesBlockedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedJavaScriptAllowedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedJavaScriptBlockedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedPluginsAllowedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedPluginsBlockedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedPluginsAskForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedPopupsAllowedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedPopupsBlockedForUrls) { |
| + ReadManagedContentSettings(true); |
| + } else if (*name == prefs::kManagedDefaultCookiesSetting) { |
| + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_COOKIES); |
| + } else if (*name == prefs::kManagedDefaultImagesSetting) { |
| + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_IMAGES); |
| + } else if (*name == prefs::kManagedDefaultJavaScriptSetting) { |
| + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_JAVASCRIPT); |
| + } else if (*name == prefs::kManagedDefaultPluginsSetting) { |
| + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_PLUGINS); |
| + } else if (*name == prefs::kManagedDefaultPopupsSetting) { |
| + ReadManagedContentSettingsTypes(CONTENT_SETTINGS_TYPE_POPUPS); |
| + } |
| + |
| + NotifyObservers(ContentSettingsDetails( |
| + ContentSettingsPattern(), CONTENT_SETTINGS_TYPE_DEFAULT, "")); |
| + } else if (type == NotificationType::PROFILE_DESTROYED) { |
| + DCHECK_EQ(profile_, Source<Profile>(source).ptr()); |
| + UnregisterObservers(); |
| + } else { |
| + NOTREACHED() << "Unexpected notification"; |
| + } |
| +} |
| + |
| } // namespace content_settings |