summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 09:42:23 +0000
committerbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-15 09:42:23 +0000
commit3eff9e2e46c00ec5c0316fef6c44355793f1906d (patch)
treeb4a346aefc756be26707cfa00952d906df8c95ba /webkit
parent682ef685be471686d07513f4e44e59c9a71cf356 (diff)
downloadchromium_src-3eff9e2e46c00ec5c0316fef6c44355793f1906d.zip
chromium_src-3eff9e2e46c00ec5c0316fef6c44355793f1906d.tar.gz
chromium_src-3eff9e2e46c00ec5c0316fef6c44355793f1906d.tar.bz2
Revert 101269 - Store plug-in enabled/disabled state in PluginPrefs instead of WebPluginInfo, to allow different sets of enabled/disabled plug-ins to be specified per profile.
BUG=80794 TEST=Open two profiles, disable different plugins in them. Review URL: http://codereview.chromium.org/7848025 TBR=bauerb@chromium.org Review URL: http://codereview.chromium.org/7901015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101272 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/plugins/npapi/plugin_group.cc366
-rw-r--r--webkit/plugins/npapi/plugin_group.h102
-rw-r--r--webkit/plugins/npapi/plugin_group_unittest.cc220
-rw-r--r--webkit/plugins/npapi/plugin_lib_mac.mm1
-rw-r--r--webkit/plugins/npapi/plugin_lib_posix.cc1
-rw-r--r--webkit/plugins/npapi/plugin_lib_win.cc3
-rw-r--r--webkit/plugins/npapi/plugin_list.cc113
-rw-r--r--webkit/plugins/npapi/plugin_list.h50
-rw-r--r--webkit/plugins/npapi/plugin_list_mac.mm2
-rw-r--r--webkit/plugins/npapi/plugin_list_posix.cc4
-rw-r--r--webkit/plugins/npapi/plugin_list_unittest.cc72
-rw-r--r--webkit/plugins/npapi/plugin_list_win.cc6
-rw-r--r--webkit/plugins/webplugininfo.cc11
-rw-r--r--webkit/plugins/webplugininfo.h32
-rw-r--r--webkit/support/webkit_support_glue.cc1
-rw-r--r--webkit/tools/test_shell/test_shell.cc1
16 files changed, 932 insertions, 53 deletions
diff --git a/webkit/plugins/npapi/plugin_group.cc b/webkit/plugins/npapi/plugin_group.cc
index b0c89f4..1f5745e 100644
--- a/webkit/plugins/npapi/plugin_group.cc
+++ b/webkit/plugins/npapi/plugin_group.cc
@@ -27,6 +27,83 @@ const char* PluginGroup::kRealPlayerGroupName = "RealPlayer";
const char* PluginGroup::kSilverlightGroupName = "Silverlight";
const char* PluginGroup::kWindowsMediaPlayerGroupName = "Windows Media Player";
+/*static*/
+std::set<string16>* PluginGroup::policy_disabled_plugin_patterns_;
+/*static*/
+std::set<string16>* PluginGroup::policy_disabled_plugin_exception_patterns_;
+/*static*/
+std::set<string16>* PluginGroup::policy_enabled_plugin_patterns_;
+
+/*static*/
+void PluginGroup::SetPolicyEnforcedPluginPatterns(
+ const std::set<string16>& plugins_disabled,
+ const std::set<string16>& plugins_disabled_exceptions,
+ const std::set<string16>& plugins_enabled) {
+ if (!policy_disabled_plugin_patterns_)
+ policy_disabled_plugin_patterns_ = new std::set<string16>(plugins_disabled);
+ else
+ *policy_disabled_plugin_patterns_ = plugins_disabled;
+
+ if (!policy_disabled_plugin_exception_patterns_)
+ policy_disabled_plugin_exception_patterns_ =
+ new std::set<string16>(plugins_disabled_exceptions);
+ else
+ *policy_disabled_plugin_exception_patterns_ = plugins_disabled_exceptions;
+
+ if (!policy_enabled_plugin_patterns_)
+ policy_enabled_plugin_patterns_ = new std::set<string16>(plugins_enabled);
+ else
+ *policy_enabled_plugin_patterns_ = plugins_enabled;
+}
+
+/*static*/
+bool PluginGroup::IsStringMatchedInSet(const string16& name,
+ const std::set<string16>* pattern_set) {
+ if (!pattern_set)
+ return false;
+
+ std::set<string16>::const_iterator pattern(pattern_set->begin());
+ while (pattern != pattern_set->end()) {
+ if (MatchPattern(name, *pattern))
+ return true;
+ ++pattern;
+ }
+
+ return false;
+}
+
+/*static*/
+bool PluginGroup::IsPluginNameDisabledByPolicy(const string16& plugin_name) {
+ // A plugin that matches some "disabled" pattern but also matches an "enabled"
+ // pattern will be enabled. Example: disable "*", enable "Flash, Java".
+ // Same for matching an "exception" pattern.
+ return IsStringMatchedInSet(plugin_name, policy_disabled_plugin_patterns_) &&
+ !IsStringMatchedInSet(plugin_name, policy_enabled_plugin_patterns_) &&
+ !IsStringMatchedInSet(plugin_name,
+ policy_disabled_plugin_exception_patterns_);
+}
+
+/*static*/
+bool PluginGroup::IsPluginFileNameDisabledByPolicy(const string16& plugin_name,
+ const string16& group_name) {
+ // This handles a specific plugin within a group that is allowed,
+ // but whose name matches a disabled pattern.
+ // Example: disable "*", exception "Java".
+ bool group_has_exception = IsStringMatchedInSet(
+ group_name,
+ policy_disabled_plugin_exception_patterns_);
+
+ return !IsPluginNameEnabledByPolicy(plugin_name) &&
+ !group_has_exception &&
+ IsPluginNameDisabledByPolicy(plugin_name);
+}
+
+/*static*/
+bool PluginGroup::IsPluginNameEnabledByPolicy(const string16& plugin_name) {
+ // There are no exceptions to enabled plugins.
+ return IsStringMatchedInSet(plugin_name, policy_enabled_plugin_patterns_);
+}
+
VersionRange::VersionRange(const VersionRangeDefinition& definition)
: low_str(definition.version_matcher_low),
high_str(definition.version_matcher_high),
@@ -68,15 +145,20 @@ PluginGroup::PluginGroup(const string16& group_name,
: identifier_(identifier),
group_name_(group_name),
name_matcher_(name_matcher),
- update_url_(update_url) {
+ update_url_(update_url),
+ enabled_(false),
+ version_(Version::GetVersionFromString("0")) {
}
void PluginGroup::InitFrom(const PluginGroup& other) {
identifier_ = other.identifier_;
group_name_ = other.group_name_;
name_matcher_ = other.name_matcher_;
+ description_ = other.description_;
update_url_ = other.update_url_;
+ enabled_ = other.enabled_;
version_ranges_ = other.version_ranges_;
+ version_.reset(other.version_->Clone());
web_plugin_infos_ = other.web_plugin_infos_;
}
@@ -174,6 +256,33 @@ Version* PluginGroup::CreateVersionFromString(const string16& version_string) {
return Version::GetVersionFromString(version);
}
+void PluginGroup::UpdateActivePlugin(const WebPluginInfo& plugin) {
+ // A group is enabled if any of the files are enabled.
+ if (IsPluginEnabled(plugin)) {
+ // The description of the group needs update either when it's state is
+ // about to change to enabled or if has never been set.
+ if (!enabled_ || description_.empty())
+ UpdateDescriptionAndVersion(plugin);
+ // In case an enabled plugin has been added to a group that is currently
+ // disabled then we should enable the group.
+ if (!enabled_)
+ enabled_ = true;
+ } else {
+ // If this is the first plugin and it's disabled,
+ // use its description for now.
+ if (description_.empty())
+ UpdateDescriptionAndVersion(plugin);
+ }
+}
+
+void PluginGroup::UpdateDescriptionAndVersion(const WebPluginInfo& plugin) {
+ description_ = plugin.desc;
+ if (Version* new_version = CreateVersionFromString(plugin.version))
+ version_.reset(new_version);
+ else
+ version_.reset(Version::GetVersionFromString("0"));
+}
+
void PluginGroup::AddPlugin(const WebPluginInfo& plugin) {
// Check if this group already contains this plugin.
for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
@@ -183,21 +292,58 @@ void PluginGroup::AddPlugin(const WebPluginInfo& plugin) {
}
}
web_plugin_infos_.push_back(plugin);
+ UpdateActivePlugin(web_plugin_infos_.back());
}
bool PluginGroup::RemovePlugin(const FilePath& filename) {
bool did_remove = false;
+ ResetGroupState();
for (size_t i = 0; i < web_plugin_infos_.size();) {
if (web_plugin_infos_[i].path == filename) {
web_plugin_infos_.erase(web_plugin_infos_.begin() + i);
did_remove = true;
} else {
+ UpdateActivePlugin(web_plugin_infos_[i]);
i++;
}
}
return did_remove;
}
+bool PluginGroup::EnablePlugin(const FilePath& filename) {
+ bool did_enable = false;
+ ResetGroupState();
+ for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
+ if (web_plugin_infos_[i].path == filename) {
+ did_enable = Enable(
+ &web_plugin_infos_[i],
+ IsPluginNameEnabledByPolicy(web_plugin_infos_[i].name) ?
+ WebPluginInfo::USER_ENABLED_POLICY_ENABLED :
+ WebPluginInfo::USER_ENABLED);
+ }
+ UpdateActivePlugin(web_plugin_infos_[i]);
+ }
+ return did_enable;
+}
+
+bool PluginGroup::DisablePlugin(const FilePath& filename) {
+ bool did_disable = false;
+ ResetGroupState();
+ for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
+ if (web_plugin_infos_[i].path == filename) {
+ // We are only called for user intervention however we should respect a
+ // policy that might as well be active on this plugin.
+ did_disable = Disable(
+ &web_plugin_infos_[i],
+ IsPluginNameDisabledByPolicy(web_plugin_infos_[i].name) ?
+ WebPluginInfo::USER_DISABLED_POLICY_DISABLED :
+ WebPluginInfo::USER_DISABLED);
+ }
+ UpdateActivePlugin(web_plugin_infos_[i]);
+ }
+ return did_disable;
+}
+
string16 PluginGroup::GetGroupName() const {
if (!group_name_.empty())
return group_name_;
@@ -219,6 +365,91 @@ bool PluginGroup::ContainsPlugin(const FilePath& path) const {
return false;
}
+
+DictionaryValue* PluginGroup::GetSummary() const {
+ DictionaryValue* result = new DictionaryValue();
+ result->SetString("name", GetGroupName());
+ result->SetBoolean("enabled", enabled_);
+ return result;
+}
+
+DictionaryValue* PluginGroup::GetDataForUI() const {
+ string16 name = GetGroupName();
+ DictionaryValue* result = new DictionaryValue();
+ result->SetString("name", name);
+ result->SetString("description", description_);
+ result->SetString("version", version_->GetString());
+ result->SetString("update_url", update_url_);
+ result->SetBoolean("critical", IsVulnerable());
+
+ bool group_disabled_by_policy = IsPluginNameDisabledByPolicy(name);
+ bool group_enabled_by_policy = IsPluginNameEnabledByPolicy(name);
+ ListValue* plugin_files = new ListValue();
+ bool all_plugins_disabled_by_policy = true;
+ bool all_plugins_enabled_by_policy = true;
+ for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
+ DictionaryValue* plugin_file = new DictionaryValue();
+ plugin_file->SetString("name", web_plugin_infos_[i].name);
+ plugin_file->SetString("description", web_plugin_infos_[i].desc);
+ plugin_file->SetString("path", web_plugin_infos_[i].path.value());
+ plugin_file->SetString("version", web_plugin_infos_[i].version);
+
+ bool plugin_disabled_by_policy = group_disabled_by_policy ||
+ ((web_plugin_infos_[i].enabled & WebPluginInfo::POLICY_DISABLED) != 0);
+ bool plugin_enabled_by_policy = group_enabled_by_policy ||
+ ((web_plugin_infos_[i].enabled & WebPluginInfo::POLICY_ENABLED) != 0);
+
+ if (!plugin_disabled_by_policy)
+ all_plugins_disabled_by_policy = false;
+ if (!plugin_enabled_by_policy)
+ all_plugins_enabled_by_policy = false;
+
+ if (plugin_disabled_by_policy) {
+ plugin_file->SetString("enabledMode", "disabledByPolicy");
+ } else if (plugin_enabled_by_policy) {
+ plugin_file->SetString("enabledMode", "enabledByPolicy");
+ } else {
+ plugin_file->SetString(
+ "enabledMode", IsPluginEnabled(web_plugin_infos_[i]) ?
+ "enabledByUser" : "disabledByUser");
+ }
+
+ ListValue* mime_types = new ListValue();
+ const std::vector<WebPluginMimeType>& plugin_mime_types =
+ web_plugin_infos_[i].mime_types;
+ for (size_t j = 0; j < plugin_mime_types.size(); ++j) {
+ DictionaryValue* mime_type = new DictionaryValue();
+ mime_type->SetString("mimeType", plugin_mime_types[j].mime_type);
+ mime_type->SetString("description", plugin_mime_types[j].description);
+
+ ListValue* file_extensions = new ListValue();
+ const std::vector<std::string>& mime_file_extensions =
+ plugin_mime_types[j].file_extensions;
+ for (size_t k = 0; k < mime_file_extensions.size(); ++k)
+ file_extensions->Append(new StringValue(mime_file_extensions[k]));
+ mime_type->Set("fileExtensions", file_extensions);
+
+ mime_types->Append(mime_type);
+ }
+ plugin_file->Set("mimeTypes", mime_types);
+
+ plugin_files->Append(plugin_file);
+ }
+
+ if (group_disabled_by_policy || all_plugins_disabled_by_policy) {
+ result->SetString("enabledMode", "disabledByPolicy");
+ } else if (group_enabled_by_policy || all_plugins_enabled_by_policy) {
+ result->SetString("enabledMode", "enabledByPolicy");
+ } else {
+ result->SetString("enabledMode", enabled_ ?
+ "enabledByUser" :
+ "disabledByUser");
+ }
+ result->Set("plugin_files", plugin_files);
+
+ return result;
+}
+
/*static*/
bool PluginGroup::IsVersionInRange(const Version& version,
const VersionRange& range) {
@@ -241,26 +472,34 @@ bool PluginGroup::IsPluginOutdated(const Version& plugin_version,
return false;
}
+bool PluginGroup::IsWhitelisted() const {
+ for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
+ if (web_plugin_infos_[i].enabled & WebPluginInfo::POLICY_ENABLED)
+ return true;
+ }
+ return false;
+}
+
// Returns true if the latest version of this plugin group is vulnerable.
-bool PluginGroup::IsVulnerable(const WebPluginInfo& plugin) const {
- scoped_ptr<Version> version(CreateVersionFromString(plugin.version));
- if (!version.get())
+bool PluginGroup::IsVulnerable() const {
+ // A plugin isn't considered vulnerable if it's explicitly whitelisted.
+ if (IsWhitelisted())
return false;
for (size_t i = 0; i < version_ranges_.size(); ++i) {
- if (IsPluginOutdated(*version, version_ranges_[i]))
+ if (IsPluginOutdated(*version_, version_ranges_[i]))
return true;
}
return false;
}
-bool PluginGroup::RequiresAuthorization(const WebPluginInfo& plugin) const {
- scoped_ptr<Version> version(CreateVersionFromString(plugin.version));
- if (!version.get())
+bool PluginGroup::RequiresAuthorization() const {
+ // A plugin doesn't require authorization if it's explicitly whitelisted.
+ if (IsWhitelisted())
return false;
for (size_t i = 0; i < version_ranges_.size(); ++i) {
- if (IsVersionInRange(*version, version_ranges_[i]) &&
+ if (IsVersionInRange(*version_, version_ranges_[i]) &&
version_ranges_[i].requires_authorization)
return true;
}
@@ -271,5 +510,114 @@ bool PluginGroup::IsEmpty() const {
return web_plugin_infos_.empty();
}
+bool PluginGroup::EnableGroup(bool enable) {
+ bool group_disabled_by_policy = IsPluginNameDisabledByPolicy(group_name_);
+ bool group_enabled_by_policy = IsPluginNameEnabledByPolicy(group_name_);
+
+ // We can't enable nor disable groups controlled by policy.
+ if ((group_disabled_by_policy && enable) ||
+ (group_enabled_by_policy && !enable))
+ return false;
+
+ ResetGroupState();
+ for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
+ bool policy_enabled =
+ IsPluginNameEnabledByPolicy(web_plugin_infos_[i].name);
+ bool policy_disabled =
+ IsPluginFileNameDisabledByPolicy(web_plugin_infos_[i].name,
+ group_name_);
+ if (policy_disabled) {
+ Disable(&web_plugin_infos_[i], WebPluginInfo::POLICY_DISABLED);
+ } else if (policy_enabled) {
+ Enable(&web_plugin_infos_[i], WebPluginInfo::POLICY_ENABLED);
+ } else if (enable) {
+ Enable(&web_plugin_infos_[i], WebPluginInfo::USER_ENABLED);
+ } else {
+ Disable(&web_plugin_infos_[i], WebPluginInfo::USER_DISABLED);
+ }
+ UpdateActivePlugin(web_plugin_infos_[i]);
+ }
+ return enabled_ == enable;
+}
+
+void PluginGroup::EnforceGroupPolicy() {
+ bool group_disabled_by_policy = IsPluginNameDisabledByPolicy(group_name_);
+ bool group_enabled_by_policy = IsPluginNameEnabledByPolicy(group_name_);
+
+ ResetGroupState();
+ for (size_t i = 0; i < web_plugin_infos_.size(); ++i) {
+ bool policy_enabled =
+ group_enabled_by_policy ||
+ IsPluginNameEnabledByPolicy(web_plugin_infos_[i].name);
+ bool policy_disabled =
+ !policy_enabled &&
+ (group_disabled_by_policy ||
+ IsPluginFileNameDisabledByPolicy(web_plugin_infos_[i].name,
+ group_name_));
+ if (policy_disabled) {
+ Disable(&web_plugin_infos_[i], WebPluginInfo::POLICY_DISABLED);
+ } else if (policy_enabled) {
+ Enable(&web_plugin_infos_[i], WebPluginInfo::POLICY_ENABLED);
+ } else {
+ // If not managed, use the user's preference.
+ if ((web_plugin_infos_[i].enabled & WebPluginInfo::USER_MASK) ==
+ WebPluginInfo::USER_ENABLED) {
+ Enable(&web_plugin_infos_[i], WebPluginInfo::POLICY_UNMANAGED);
+ } else {
+ Disable(&web_plugin_infos_[i], WebPluginInfo::POLICY_UNMANAGED);
+ }
+ }
+ UpdateActivePlugin(web_plugin_infos_[i]);
+ }
+}
+
+void PluginGroup::ResetGroupState() {
+ enabled_ = false;
+ description_.clear();
+ version_.reset(Version::GetVersionFromString("0"));
+}
+
+/*static*/
+bool PluginGroup::SetPluginState(WebPluginInfo* plugin,
+ int new_reason,
+ bool state_changes) {
+ // If we are only stripping the policy then mask the policy bits.
+ if (new_reason == WebPluginInfo::POLICY_UNMANAGED) {
+ plugin->enabled &= WebPluginInfo::USER_MASK;
+ return true;
+ }
+ if (new_reason & WebPluginInfo::MANAGED_MASK) {
+ // Policy-enforced change: preserve the user's preference, and override
+ // a possible previous policy flag.
+ plugin->enabled = (plugin->enabled & WebPluginInfo::USER_MASK) | new_reason;
+ } else if (state_changes && (plugin->enabled & WebPluginInfo::MANAGED_MASK)) {
+ // Refuse change when managed.
+ return false;
+ } else {
+ // Accept the user update, but keep the policy flag if present.
+ plugin->enabled = (plugin->enabled & WebPluginInfo::MANAGED_MASK) |
+ new_reason;
+ }
+ return true;
+}
+
+/*static*/
+bool PluginGroup::Enable(WebPluginInfo* plugin, int new_reason) {
+ DCHECK(new_reason == WebPluginInfo::USER_ENABLED ||
+ new_reason == WebPluginInfo::POLICY_ENABLED ||
+ new_reason == WebPluginInfo::USER_ENABLED_POLICY_ENABLED ||
+ new_reason == WebPluginInfo::POLICY_UNMANAGED);
+ return SetPluginState(plugin, new_reason, !IsPluginEnabled(*plugin));
+}
+
+/*static*/
+bool PluginGroup::Disable(WebPluginInfo* plugin, int new_reason) {
+ DCHECK(new_reason == WebPluginInfo::USER_DISABLED ||
+ new_reason == WebPluginInfo::POLICY_DISABLED ||
+ new_reason == WebPluginInfo::USER_DISABLED_POLICY_DISABLED ||
+ new_reason == WebPluginInfo::POLICY_UNMANAGED);
+ return SetPluginState(plugin, new_reason, IsPluginEnabled(*plugin));
+}
+
} // namespace npapi
} // namespace webkit
diff --git a/webkit/plugins/npapi/plugin_group.h b/webkit/plugins/npapi/plugin_group.h
index e721b3b..da80db8 100644
--- a/webkit/plugins/npapi/plugin_group.h
+++ b/webkit/plugins/npapi/plugin_group.h
@@ -6,6 +6,8 @@
#define WEBKIT_PLUGINS_NPAPI_PLUGIN_GROUP_H_
#pragma once
+#include <map>
+#include <set>
#include <string>
#include <vector>
@@ -95,6 +97,24 @@ class PluginGroup {
PluginGroup& operator=(const PluginGroup& other);
+ // Configures the set of plugin name patterns for enabling and disabling
+ // plugins via enterprise configuration management.
+ static void SetPolicyEnforcedPluginPatterns(
+ const std::set<string16>& plugins_disabled,
+ const std::set<string16>& plugins_disabled_exceptions,
+ const std::set<string16>& plugins_enabled);
+
+ // Tests whether |plugin_name| is disabled by policy.
+ static bool IsPluginNameDisabledByPolicy(const string16& plugin_name);
+
+ // Tests whether |plugin_name| within the plugin group |group_name| is
+ // disabled by policy.
+ static bool IsPluginFileNameDisabledByPolicy(const string16& plugin_name,
+ const string16& group_name);
+
+ // Tests whether |plugin_name| is enabled by policy.
+ static bool IsPluginNameEnabledByPolicy(const string16& plugin_name);
+
// Returns true if the given plugin matches this group.
bool Match(const webkit::WebPluginInfo& plugin) const;
@@ -104,6 +124,24 @@ class PluginGroup {
// Removes a plugin from the group by its path.
bool RemovePlugin(const FilePath& filename);
+ // The two following functions enable/disable a plugin given its filename. The
+ // function returns true if the plugin could be enabled/disabled. Plugins
+ // might not get enabled/disabled if they are controlled by policy or are
+ // already in the wanted state.
+ bool EnablePlugin(const FilePath& filename);
+ bool DisablePlugin(const FilePath& filename);
+
+ // Enables/disables this group. This enables/disables all plugins in the
+ // group.
+ bool EnableGroup(bool enable);
+
+ // Checks whether the group should be disabled/enabled by a policy and puts
+ // it in the needed state. Updates all contained plugins too.
+ void EnforceGroupPolicy();
+
+ // Returns whether the plugin group is enabled or not.
+ bool Enabled() const { return enabled_; }
+
// Returns a unique identifier for this group, if one is defined, or the empty
// string otherwise.
const std::string& identifier() const { return identifier_; }
@@ -117,21 +155,36 @@ class PluginGroup {
// is empty.
string16 GetGroupName() const;
+ // Returns all plugins added to the group.
+ const std::vector<webkit::WebPluginInfo>& web_plugins_info() const {
+ return web_plugin_infos_;
+ }
+
// Checks whether a plugin exists in the group with the given path.
bool ContainsPlugin(const FilePath& path) const;
+ // Returns the description of the highest-priority plug-in in the group.
+ const string16& description() const { return description_; }
+
+ // Returns a DictionaryValue with data to display in the UI.
+ base::DictionaryValue* GetDataForUI() const;
+
+ // Returns a DictionaryValue with data to save in the preferences.
+ base::DictionaryValue* GetSummary() const;
+
// Returns the update URL.
std::string GetUpdateURL() const { return update_url_; }
// Returns true if this plugin group is whitelisted.
bool IsWhitelisted() const;
- // Returns true if |plugin| in this group has known security problems.
- bool IsVulnerable(const WebPluginInfo& plugin) const;
+ // Returns true if the highest-priority plugin in this group has known
+ // security problems.
+ bool IsVulnerable() const;
- // Returns true if |plugin| in this plug-in group always requires user
- // authorization to run.
- bool RequiresAuthorization(const WebPluginInfo& plugin) const;
+ // Returns true if this plug-in group always requires user authorization
+ // to run.
+ bool RequiresAuthorization() const;
// Check if the group has no plugins. Could happen after a reload if the plug-
// in has disappeared from the pc (or in the process of updating).
@@ -141,7 +194,7 @@ class PluginGroup {
// in accepting weird version strings than Version::GetFromString().
static Version* CreateVersionFromString(const string16& version_string);
- const std::vector<webkit::WebPluginInfo>& web_plugin_infos() const {
+ std::vector<webkit::WebPluginInfo> web_plugin_infos() {
return web_plugin_infos_;
}
@@ -184,17 +237,54 @@ class PluginGroup {
void InitFrom(const PluginGroup& other);
+ // Set the description and version for this plugin group from the
+ // given plug-in.
+ void UpdateDescriptionAndVersion(const webkit::WebPluginInfo& plugin);
+
+ // Updates the active plugin in the group. The active plugin is the first
+ // enabled one, or if all plugins are disabled, simply the first one.
+ void UpdateActivePlugin(const webkit::WebPluginInfo& plugin);
+
+ // Resets the group state to its default value (as if the group was empty).
+ // After calling this method, calling |UpdateActivePlugin| with all plugins
+ // in a row will correctly set the group state.
+ void ResetGroupState();
+
+ // Enables the plugin if not already enabled and if policy allows it to.
+ // Returns true on success. Does not update the group state.
+ static bool Enable(webkit::WebPluginInfo* plugin, int reason);
+
+ // Disables the plugin if not already disabled and if policy allows it to.
+ // Returns true on success. Does not update the group state.
+ static bool Disable(webkit::WebPluginInfo* plugin, int reason);
+
+ // Helper function to implement the functions above.
+ static bool SetPluginState(webkit::WebPluginInfo* plugin,
+ int new_reason,
+ bool state_changes);
+
// Returns a non-const vector of all plugins in the group. This is only used
// by PluginList.
std::vector<webkit::WebPluginInfo>& GetPluginsContainer() {
return web_plugin_infos_;
}
+ // Checks if |name| matches any of the patterns in |pattern_set|.
+ static bool IsStringMatchedInSet(const string16& name,
+ const std::set<string16>* pattern_set);
+
+ static std::set<string16>* policy_disabled_plugin_patterns_;
+ static std::set<string16>* policy_disabled_plugin_exception_patterns_;
+ static std::set<string16>* policy_enabled_plugin_patterns_;
+
std::string identifier_;
string16 group_name_;
string16 name_matcher_;
+ string16 description_;
std::string update_url_;
+ bool enabled_;
std::vector<VersionRange> version_ranges_;
+ scoped_ptr<Version> version_;
std::vector<webkit::WebPluginInfo> web_plugin_infos_;
};
diff --git a/webkit/plugins/npapi/plugin_group_unittest.cc b/webkit/plugins/npapi/plugin_group_unittest.cc
index a9e1c1c..8f9bf50 100644
--- a/webkit/plugins/npapi/plugin_group_unittest.cc
+++ b/webkit/plugins/npapi/plugin_group_unittest.cc
@@ -87,6 +87,12 @@ class PluginGroupTest : public testing::Test {
static PluginGroup* CreatePluginGroup(const WebPluginInfo& wpi) {
return PluginGroup::FromWebPluginInfo(wpi);
}
+ protected:
+ virtual void TearDown() {
+ PluginGroup::SetPolicyEnforcedPluginPatterns(std::set<string16>(),
+ std::set<string16>(),
+ std::set<string16>());
+ }
};
TEST_F(PluginGroupTest, PluginGroupMatch) {
@@ -96,7 +102,7 @@ TEST_F(PluginGroupTest, PluginGroupMatch) {
EXPECT_TRUE(group->Match(kPlugin3045r));
EXPECT_FALSE(group->Match(kPluginNoVersion));
group->AddPlugin(kPlugin3045);
- EXPECT_FALSE(group->IsVulnerable(kPlugin3045));
+ EXPECT_FALSE(group->IsVulnerable());
group.reset(PluginGroupTest::CreatePluginGroup(kPluginDef));
EXPECT_FALSE(group->Match(kPluginNoVersion));
@@ -120,6 +126,45 @@ TEST_F(PluginGroupTest, PluginGroupMatchCorrectVersion) {
EXPECT_TRUE(group->Match(kPlugin4043));
}
+TEST_F(PluginGroupTest, PluginGroupDescription) {
+ string16 desc3043(ASCIIToUTF16("MyPlugin version 3.0.43"));
+ string16 desc3045(ASCIIToUTF16("MyPlugin version 3.0.45"));
+
+ PluginGroupDefinition plugindefs[] =
+ { kPluginDef, kPluginDef3, kPluginDef34 };
+ for (size_t i = 0; i < arraysize(plugindefs); ++i) {
+ WebPluginInfo plugin3043(kPlugin3043);
+ WebPluginInfo plugin3045(kPlugin3045);
+ {
+ scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup(
+ plugindefs[i]));
+ EXPECT_TRUE(group->Match(plugin3043));
+ group->AddPlugin(plugin3043);
+ EXPECT_EQ(desc3043, group->description());
+ EXPECT_TRUE(group->IsVulnerable());
+ EXPECT_TRUE(group->Match(plugin3045));
+ group->AddPlugin(plugin3045);
+ EXPECT_EQ(desc3043, group->description());
+ EXPECT_TRUE(group->IsVulnerable());
+ }
+ {
+ // Disable the second plugin.
+ plugin3045.enabled =
+ webkit::WebPluginInfo::USER_DISABLED_POLICY_UNMANAGED;
+ scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup(
+ plugindefs[i]));
+ EXPECT_TRUE(group->Match(plugin3043));
+ group->AddPlugin(plugin3043);
+ EXPECT_EQ(desc3043, group->description());
+ EXPECT_TRUE(group->IsVulnerable());
+ EXPECT_TRUE(group->Match(plugin3045));
+ group->AddPlugin(plugin3045);
+ EXPECT_EQ(desc3043, group->description());
+ EXPECT_TRUE(group->IsVulnerable());
+ }
+ }
+}
+
TEST_F(PluginGroupTest, PluginGroupDefinition) {
for (size_t i = 0; i < arraysize(kPluginDefinitions); ++i) {
scoped_ptr<PluginGroup> def_group(
@@ -143,12 +188,117 @@ TEST_F(PluginGroupTest, VersionExtraction) {
};
for (size_t i = 0; i < arraysize(versions); i++) {
- scoped_ptr<Version> version(PluginGroup::CreateVersionFromString(
- ASCIIToUTF16(versions[i][0])));
- EXPECT_STREQ(versions[i][1], version->GetString().c_str());
+ const WebPluginInfo plugin = WebPluginInfo(
+ ASCIIToUTF16("Blah Plugin"), FilePath(FILE_PATH_LITERAL("blahfile")),
+ ASCIIToUTF16(versions[i][0]), string16());
+ scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup(plugin));
+ EXPECT_TRUE(group->Match(plugin));
+ group->AddPlugin(plugin);
+ scoped_ptr<DictionaryValue> data(group->GetDataForUI());
+ std::string version;
+ data->GetString("version", &version);
+ EXPECT_EQ(versions[i][1], version);
}
}
+TEST_F(PluginGroupTest, DisabledByPolicy) {
+ std::set<string16> disabled_plugins;
+ disabled_plugins.insert(ASCIIToUTF16("Disable this!"));
+ disabled_plugins.insert(ASCIIToUTF16("*Google*"));
+ PluginGroup::SetPolicyEnforcedPluginPatterns(disabled_plugins,
+ std::set<string16>(),
+ std::set<string16>());
+
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(ASCIIToUTF16("42")));
+ EXPECT_TRUE(PluginGroup::IsPluginNameDisabledByPolicy(
+ ASCIIToUTF16("Disable this!")));
+ EXPECT_TRUE(PluginGroup::IsPluginNameDisabledByPolicy(
+ ASCIIToUTF16("Google Earth")));
+}
+
+TEST_F(PluginGroupTest, EnabledByPolicy) {
+ std::set<string16> enabled_plugins;
+ enabled_plugins.insert(ASCIIToUTF16("Enable that!"));
+ enabled_plugins.insert(ASCIIToUTF16("PDF*"));
+ PluginGroup::SetPolicyEnforcedPluginPatterns(std::set<string16>(),
+ std::set<string16>(),
+ enabled_plugins);
+
+ EXPECT_FALSE(PluginGroup::IsPluginNameEnabledByPolicy(ASCIIToUTF16("42")));
+ EXPECT_TRUE(PluginGroup::IsPluginNameEnabledByPolicy(
+ ASCIIToUTF16("Enable that!")));
+ EXPECT_TRUE(PluginGroup::IsPluginNameEnabledByPolicy(
+ ASCIIToUTF16("PDF Reader")));
+}
+
+TEST_F(PluginGroupTest, EnabledAndDisabledByPolicy) {
+ const string16 k42(ASCIIToUTF16("42"));
+ const string16 kEnabled(ASCIIToUTF16("Enabled"));
+ const string16 kEnabled2(ASCIIToUTF16("Enabled 2"));
+ const string16 kEnabled3(ASCIIToUTF16("Enabled 3"));
+ const string16 kException(ASCIIToUTF16("Exception"));
+ const string16 kException2(ASCIIToUTF16("Exception 2"));
+ const string16 kGoogleMars(ASCIIToUTF16("Google Mars"));
+ const string16 kGoogleEarth(ASCIIToUTF16("Google Earth"));
+
+ std::set<string16> disabled_plugins;
+ std::set<string16> disabled_plugins_exceptions;
+ std::set<string16> enabled_plugins;
+
+ disabled_plugins.insert(kEnabled);
+ disabled_plugins_exceptions.insert(kEnabled);
+ enabled_plugins.insert(kEnabled);
+
+ disabled_plugins_exceptions.insert(kException);
+
+ disabled_plugins.insert(kEnabled2);
+ enabled_plugins.insert(kEnabled2);
+
+ disabled_plugins.insert(kException2);
+ disabled_plugins_exceptions.insert(kException2);
+
+ disabled_plugins_exceptions.insert(kEnabled3);
+ enabled_plugins.insert(kEnabled3);
+
+ PluginGroup::SetPolicyEnforcedPluginPatterns(disabled_plugins,
+ disabled_plugins_exceptions,
+ enabled_plugins);
+
+ EXPECT_FALSE(PluginGroup::IsPluginNameEnabledByPolicy(k42));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(k42));
+
+ EXPECT_TRUE(PluginGroup::IsPluginNameEnabledByPolicy(kEnabled));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(kEnabled));
+ EXPECT_TRUE(PluginGroup::IsPluginNameEnabledByPolicy(kEnabled2));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(kEnabled2));
+ EXPECT_TRUE(PluginGroup::IsPluginNameEnabledByPolicy(kEnabled3));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(kEnabled3));
+
+ EXPECT_FALSE(PluginGroup::IsPluginNameEnabledByPolicy(kException));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(kException));
+ EXPECT_FALSE(PluginGroup::IsPluginNameEnabledByPolicy(kException2));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(kException2));
+
+ disabled_plugins.clear();
+ disabled_plugins_exceptions.clear();
+ enabled_plugins.clear();
+
+ disabled_plugins.insert(ASCIIToUTF16("*"));
+ disabled_plugins_exceptions.insert(ASCIIToUTF16("*Google*"));
+ enabled_plugins.insert(kGoogleEarth);
+
+ PluginGroup::SetPolicyEnforcedPluginPatterns(disabled_plugins,
+ disabled_plugins_exceptions,
+ enabled_plugins);
+
+ EXPECT_TRUE(PluginGroup::IsPluginNameEnabledByPolicy(kGoogleEarth));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(kGoogleEarth));
+ EXPECT_FALSE(PluginGroup::IsPluginNameEnabledByPolicy(kGoogleMars));
+ EXPECT_FALSE(PluginGroup::IsPluginNameDisabledByPolicy(kGoogleMars));
+ EXPECT_FALSE(PluginGroup::IsPluginNameEnabledByPolicy(k42));
+ EXPECT_TRUE(PluginGroup::IsPluginNameDisabledByPolicy(k42));
+}
+
TEST_F(PluginGroupTest, IsVulnerable) {
// Adobe Reader 10
VersionRangeDefinition adobe_reader_version_range[] = {
@@ -168,8 +318,8 @@ TEST_F(PluginGroupTest, IsVulnerable) {
adobe_reader_plugin_def));
group->AddPlugin(adobe_reader_plugin);
PluginGroup group_copy(*group); // Exercise the copy constructor.
- EXPECT_FALSE(group_copy.IsVulnerable(adobe_reader_plugin));
- EXPECT_FALSE(group_copy.RequiresAuthorization(adobe_reader_plugin));
+ EXPECT_FALSE(group_copy.IsVulnerable());
+ EXPECT_FALSE(group_copy.RequiresAuthorization());
// Silverlight 4
VersionRangeDefinition silverlight_version_range[] = {
@@ -186,8 +336,62 @@ TEST_F(PluginGroupTest, IsVulnerable) {
ASCIIToUTF16("silverlight 4"));
group.reset(PluginGroupTest::CreatePluginGroup(silverlight_plugin_def));
group->AddPlugin(silverlight_plugin);
- EXPECT_FALSE(PluginGroup(*group).IsVulnerable(silverlight_plugin));
- EXPECT_TRUE(PluginGroup(*group).RequiresAuthorization(silverlight_plugin));
+ EXPECT_FALSE(PluginGroup(*group).IsVulnerable());
+ EXPECT_TRUE(PluginGroup(*group).RequiresAuthorization());
+}
+
+TEST_F(PluginGroupTest, WhitelistedIsNotVulnerable) {
+ VersionRangeDefinition version_range[] = {
+ { "0", "6", "5.0", true }
+ };
+ PluginGroupDefinition plugin_def = {
+ "nativehtml5", "NativeHTML5", "NativeHTML5", version_range,
+ arraysize(version_range),
+ "http://bugzilla.mozilla.org/show_bug.cgi?id=649408" };
+ WebPluginInfo plugin(ASCIIToUTF16("NativeHTML5"),
+ FilePath(FILE_PATH_LITERAL("/native.so")),
+ ASCIIToUTF16("4.0"),
+ ASCIIToUTF16("NativeHTML5"));
+ scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup(plugin_def));
+ group->AddPlugin(plugin);
+
+ EXPECT_TRUE(group->IsVulnerable());
+ EXPECT_TRUE(group->RequiresAuthorization());
+
+ std::set<string16> enabled_plugins;
+ enabled_plugins.insert(ASCIIToUTF16("NativeHTML5"));
+ PluginGroup::SetPolicyEnforcedPluginPatterns(std::set<string16>(),
+ std::set<string16>(),
+ enabled_plugins);
+ group->EnforceGroupPolicy();
+
+ EXPECT_FALSE(group->IsVulnerable());
+ EXPECT_FALSE(group->RequiresAuthorization());
+}
+
+TEST_F(PluginGroupTest, MultipleVersions) {
+ scoped_ptr<PluginGroup> group(
+ PluginGroupTest::CreatePluginGroup(kPluginDef3));
+ group->AddPlugin(kPlugin3044);
+ group->AddPlugin(kPlugin3043);
+ EXPECT_EQ(kPlugin3044.desc, group->description());
+ EXPECT_FALSE(group->IsVulnerable());
+
+ group->DisablePlugin(kPlugin3044.path);
+ EXPECT_EQ(kPlugin3043.desc, group->description());
+ EXPECT_TRUE(group->IsVulnerable());
+
+ EXPECT_TRUE(group->EnableGroup(false));
+ EXPECT_EQ(kPlugin3044.desc, group->description());
+ EXPECT_FALSE(group->IsVulnerable());
+
+ EXPECT_TRUE(group->RemovePlugin(kPlugin3044.path));
+ EXPECT_EQ(kPlugin3043.desc, group->description());
+ EXPECT_TRUE(group->IsVulnerable());
+
+ EXPECT_TRUE(group->RemovePlugin(kPlugin3043.path));
+ EXPECT_TRUE(group->IsEmpty());
+ EXPECT_EQ(string16(), group->description());
}
} // namespace npapi
diff --git a/webkit/plugins/npapi/plugin_lib_mac.mm b/webkit/plugins/npapi/plugin_lib_mac.mm
index 542b43d..fe11197 100644
--- a/webkit/plugins/npapi/plugin_lib_mac.mm
+++ b/webkit/plugins/npapi/plugin_lib_mac.mm
@@ -125,6 +125,7 @@ bool ReadPlistPluginInfo(const FilePath& filename, CFBundleRef bundle,
info->desc = base::SysNSStringToUTF16(plugin_desc);
else
info->desc = UTF8ToUTF16(filename.BaseName().value());
+ info->enabled = WebPluginInfo::USER_ENABLED;
return true;
}
diff --git a/webkit/plugins/npapi/plugin_lib_posix.cc b/webkit/plugins/npapi/plugin_lib_posix.cc
index 64afcd2..641b6cd 100644
--- a/webkit/plugins/npapi/plugin_lib_posix.cc
+++ b/webkit/plugins/npapi/plugin_lib_posix.cc
@@ -162,6 +162,7 @@ bool PluginLib::ReadWebPluginInfo(const FilePath& filename,
}
info->path = filename;
+ info->enabled = WebPluginInfo::USER_ENABLED;
// Attempt to swap in the wrapped plugin if this is nspluginwrapper.
UnwrapNSPluginWrapper(&dl, &info->path);
diff --git a/webkit/plugins/npapi/plugin_lib_win.cc b/webkit/plugins/npapi/plugin_lib_win.cc
index 224e1c3..ccdb4b6 100644
--- a/webkit/plugins/npapi/plugin_lib_win.cc
+++ b/webkit/plugins/npapi/plugin_lib_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -38,6 +38,7 @@ bool PluginLib::ReadWebPluginInfo(const FilePath &filename,
info->desc = version_info->file_description();
info->version = version_info->file_version();
info->path = filename;
+ info->enabled = WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
// TODO(evan): Move the ParseMimeTypes code inline once Pepper is updated.
if (!PluginList::ParseMimeTypes(
diff --git a/webkit/plugins/npapi/plugin_list.cc b/webkit/plugins/npapi/plugin_list.cc
index a7f6dd4..45160fc 100644
--- a/webkit/plugins/npapi/plugin_list.cc
+++ b/webkit/plugins/npapi/plugin_list.cc
@@ -230,6 +230,7 @@ void PluginList::RegisterInternalPlugin(const FilePath& filename,
plugin.info.name = ASCIIToUTF16(name);
plugin.info.version = ASCIIToUTF16("1");
plugin.info.desc = ASCIIToUTF16(description);
+ plugin.info.enabled = webkit::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
webkit::WebPluginMimeType mime_type;
mime_type.mime_type = mime_type_str;
@@ -407,6 +408,51 @@ void PluginList::LoadPlugins() {
LoadPluginsInternal(&new_plugin_groups);
base::AutoLock lock(lock_);
+ // Grab all plugins that were found before to copy enabled statuses.
+ std::vector<webkit::WebPluginInfo> old_plugins;
+ for (size_t i = 0; i < plugin_groups_.size(); ++i) {
+ const std::vector<webkit::WebPluginInfo>& gr_plugins =
+ plugin_groups_[i]->web_plugins_info();
+ old_plugins.insert(old_plugins.end(), gr_plugins.begin(), gr_plugins.end());
+ }
+ // Disable all of the plugins and plugin groups that are disabled by policy.
+ for (size_t i = 0; i < new_plugin_groups.size(); ++i) {
+ PluginGroup* group = new_plugin_groups[i];
+ string16 group_name = group->GetGroupName();
+
+ std::vector<webkit::WebPluginInfo>& gr_plugins =
+ group->GetPluginsContainer();
+ for (size_t j = 0; j < gr_plugins.size(); ++j) {
+ int plugin_found = -1;
+ for (size_t k = 0; k < old_plugins.size(); ++k) {
+ if (gr_plugins[j].path == old_plugins[k].path) {
+ plugin_found = k;
+ break;
+ }
+ }
+ if (plugin_found >= 0)
+ gr_plugins[j].enabled = old_plugins[plugin_found].enabled;
+ // Set the disabled flag of all plugins scheduled for disabling.
+ if (plugins_to_disable_.find(gr_plugins[j].path) !=
+ plugins_to_disable_.end()) {
+ group->DisablePlugin(gr_plugins[j].path);
+ }
+ }
+
+ if (group->IsEmpty()) {
+ new_plugin_groups.erase(new_plugin_groups.begin() + i);
+ --i;
+ continue;
+ }
+
+ group->EnforceGroupPolicy();
+ }
+ // We flush the list of prematurely disabled plugins after the load has
+ // finished. If for some reason a plugin reappears on a second load it is
+ // going to be loaded normally. This is only true for non-policy controlled
+ // plugins though.
+ plugins_to_disable_.clear();
+
plugin_groups_.swap(new_plugin_groups);
}
@@ -447,7 +493,7 @@ void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) {
base::AutoLock lock(lock_);
for (size_t i = 0; i < plugin_groups_.size(); ++i) {
const std::vector<webkit::WebPluginInfo>& gr_plugins =
- plugin_groups_[i]->web_plugin_infos();
+ plugin_groups_[i]->web_plugins_info();
plugins->insert(plugins->end(), gr_plugins.begin(), gr_plugins.end());
}
}
@@ -476,7 +522,7 @@ void PluginList::GetPluginInfoArray(
// Add in plugins by mime type.
for (size_t i = 0; i < plugin_groups_.size(); ++i) {
const std::vector<webkit::WebPluginInfo>& plugins =
- plugin_groups_[i]->web_plugin_infos();
+ plugin_groups_[i]->web_plugins_info();
for (size_t i = 0; i < plugins.size(); ++i) {
if (SupportsType(plugins[i], mime_type, allow_wildcard)) {
FilePath path = plugins[i].path;
@@ -498,7 +544,7 @@ void PluginList::GetPluginInfoArray(
std::string actual_mime_type;
for (size_t i = 0; i < plugin_groups_.size(); ++i) {
const std::vector<webkit::WebPluginInfo>& plugins =
- plugin_groups_[i]->web_plugin_infos();
+ plugin_groups_[i]->web_plugins_info();
for (size_t i = 0; i < plugins.size(); ++i) {
if (SupportsExtension(plugins[i], extension, &actual_mime_type)) {
FilePath path = plugins[i].path;
@@ -523,9 +569,9 @@ void PluginList::GetPluginInfoArray(
if (plugin_groups_[i]->identifier().compare(
kDefaultPluginLibraryName) == 0) {
#endif
- DCHECK_NE(0U, plugin_groups_[i]->web_plugin_infos().size());
+ DCHECK_NE(0U, plugin_groups_[i]->web_plugins_info().size());
const webkit::WebPluginInfo& default_info =
- plugin_groups_[i]->web_plugin_infos()[0];
+ plugin_groups_[i]->web_plugins_info()[0];
if (SupportsType(default_info, mime_type, allow_wildcard)) {
info->push_back(default_info);
if (actual_mime_types)
@@ -541,7 +587,7 @@ bool PluginList::GetPluginInfoByPath(const FilePath& plugin_path,
base::AutoLock lock(lock_);
for (size_t i = 0; i < plugin_groups_.size(); ++i) {
const std::vector<webkit::WebPluginInfo>& plugins =
- plugin_groups_[i]->web_plugin_infos();
+ plugin_groups_[i]->web_plugins_info();
for (size_t i = 0; i < plugins.size(); ++i) {
if (plugins[i].path == plugin_path) {
*info = plugins[i];
@@ -568,10 +614,10 @@ void PluginList::GetPluginGroups(
}
}
-PluginGroup* PluginList::GetPluginGroup(
+const PluginGroup* PluginList::GetPluginGroup(
const webkit::WebPluginInfo& web_plugin_info) {
base::AutoLock lock(lock_);
- return new PluginGroup(*AddToPluginGroups(web_plugin_info, &plugin_groups_));
+ return AddToPluginGroups(web_plugin_info, &plugin_groups_);
}
string16 PluginList::GetPluginGroupName(const std::string& identifier) {
@@ -624,9 +670,60 @@ PluginGroup* PluginList::AddToPluginGroups(
plugin_groups->push_back(group);
}
group->AddPlugin(web_plugin_info);
+ // If group is scheduled for disabling do that now and remove it from the
+ // list.
+ if (groups_to_disable_.erase(group->GetGroupName()))
+ group->EnableGroup(false);
return group;
}
+bool PluginList::EnablePlugin(const FilePath& filename) {
+ base::AutoLock lock(lock_);
+ for (size_t i = 0; i < plugin_groups_.size(); ++i) {
+ if (plugin_groups_[i]->ContainsPlugin(filename))
+ return plugin_groups_[i]->EnablePlugin(filename);
+ }
+ // Non existing plugin is being enabled. Check if it has been disabled before
+ // and remove it.
+ return (plugins_to_disable_.erase(filename) != 0);
+}
+
+bool PluginList::DisablePlugin(const FilePath& filename) {
+ base::AutoLock lock(lock_);
+ for (size_t i = 0; i < plugin_groups_.size(); ++i) {
+ if (plugin_groups_[i]->ContainsPlugin(filename))
+ return plugin_groups_[i]->DisablePlugin(filename);
+ }
+ // Non existing plugin is being disabled. Queue the plugin so that on the next
+ // load plugins call they will be disabled.
+ plugins_to_disable_.insert(filename);
+ return true;
+}
+
+bool PluginList::EnableGroup(bool enable, const string16& group_name) {
+ base::AutoLock lock(lock_);
+ PluginGroup* group = NULL;
+ for (size_t i = 0; i < plugin_groups_.size(); ++i) {
+ if (!plugin_groups_[i]->IsEmpty() &&
+ plugin_groups_[i]->GetGroupName().find(group_name) != string16::npos) {
+ group = plugin_groups_[i];
+ break;
+ }
+ }
+ if (!group) {
+ // Non existing group is being enabled. Queue the group so that on the next
+ // load plugins call they will be disabled.
+ if (!enable) {
+ groups_to_disable_.insert(group_name);
+ return true;
+ } else {
+ return (groups_to_disable_.erase(group_name) != 0);
+ }
+ }
+
+ return group->EnableGroup(enable);
+}
+
bool PluginList::SupportsType(const webkit::WebPluginInfo& plugin,
const std::string& mime_type,
bool allow_wildcard) {
diff --git a/webkit/plugins/npapi/plugin_list.h b/webkit/plugins/npapi/plugin_list.h
index 640ccbd..4f17bdb 100644
--- a/webkit/plugins/npapi/plugin_list.h
+++ b/webkit/plugins/npapi/plugin_list.h
@@ -150,10 +150,16 @@ class PluginList {
void GetPluginGroups(bool load_if_necessary,
std::vector<PluginGroup>* plugin_groups);
- // Returns a copy of the PluginGroup corresponding to the given WebPluginInfo.
- // If no such group exists, it is created and added to the cache.
- // The caller takes ownership of the returned PluginGroup.
- PluginGroup* GetPluginGroup(const webkit::WebPluginInfo& web_plugin_info);
+ // Returns the PluginGroup corresponding to the given WebPluginInfo. If no
+ // such group exists, it is created and added to the cache.
+ // Beware: when calling this from the Browser process, the group that the
+ // returned pointer points to might disappear suddenly. This happens when
+ // |RefreshPlugins()| is called and then |LoadPlugins()| is triggered by a
+ // call to |GetPlugins()|, |GetEnabledPlugins()|, |GetPluginInfoArray()|,
+ // |GetPluginInfoByPath()|, or |GetPluginGroups(true, _)|. It is the caller's
+ // responsibility to make sure this doesn't happen.
+ const PluginGroup* GetPluginGroup(
+ const webkit::WebPluginInfo& web_plugin_info);
// Returns the name of the PluginGroup with the given identifier.
// If no such group exists, an empty string is returned.
@@ -169,6 +175,24 @@ class PluginList {
void LoadPlugin(const FilePath& filename,
ScopedVector<PluginGroup>* plugin_groups);
+ // Enable a specific plugin, specified by path. Returns |true| iff a plugin
+ // currently in the plugin list was actually enabled as a result; regardless
+ // of return value, if a plugin is found in the future with the given name, it
+ // will be enabled.
+ bool EnablePlugin(const FilePath& filename);
+
+ // Disable a specific plugin, specified by path. Returns |true| iff a plugin
+ // currently in the plugin list was actually disabled as a result; regardless
+ // of return value, if a plugin is found in the future with the given name, it
+ // will be disabled.
+ bool DisablePlugin(const FilePath& filename);
+
+ // Enable/disable a plugin group, specified by group_name. Returns |true| iff
+ // a plugin currently in the plugin list was actually enabled/disabled as a
+ // result; regardless of return value, if a plugin is found in the future with
+ // the given name, it will be enabled/disabled.
+ bool EnableGroup(bool enable, const string16& name);
+
virtual ~PluginList();
protected:
@@ -216,6 +240,12 @@ class PluginList {
bool ShouldLoadPlugin(const webkit::WebPluginInfo& info,
ScopedVector<PluginGroup>* plugins);
+ // Return whether a plug-in group with the given name should be disabled,
+ // either because it already is on the list of disabled groups, or because it
+ // is blacklisted by a policy. In the latter case, add the plugin group to the
+ // list of disabled groups as well.
+ bool ShouldDisableGroup(const string16& group_name);
+
// Returns true if the plugin supports |mime_type|. |mime_type| should be all
// lower case.
bool SupportsType(const webkit::WebPluginInfo& plugin,
@@ -278,6 +308,18 @@ class PluginList {
// Holds the currently available plugin groups.
ScopedVector<PluginGroup> plugin_groups_;
+ // The set of plugins that have been scheduled for disabling once they get
+ // loaded. This list is used in LoadPlugins and pruned after it. Contains
+ // plugins that were either disabled by the user (prefs are loaded before
+ // plugins) or disabled by a policy.
+ std::set<FilePath> plugins_to_disable_;
+ // Equivalent to the |plugins_to_disable_| this is the set of groups
+ // scheduled for disabling once they appear. This list is never completely
+ // pruned but all groups that do get created are removed from it. New groups
+ // might get added if they should be pruned because of plugins getting removed
+ // for example.
+ std::set<string16> groups_to_disable_;
+
// Need synchronization for the above members since this object can be
// accessed on multiple threads.
base::Lock lock_;
diff --git a/webkit/plugins/npapi/plugin_list_mac.mm b/webkit/plugins/npapi/plugin_list_mac.mm
index 361691a..b142b2c 100644
--- a/webkit/plugins/npapi/plugin_list_mac.mm
+++ b/webkit/plugins/npapi/plugin_list_mac.mm
@@ -107,7 +107,7 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
// encounter earlier must override plugins we encounter later)
for (size_t i = 0; i < plugin_groups->size(); ++i) {
const std::vector<WebPluginInfo>& plugins =
- (*plugin_groups)[i]->web_plugin_infos();
+ (*plugin_groups)[i]->web_plugins_info();
for (size_t j = 0; j < plugins.size(); ++j) {
if (plugins[j].path.BaseName() == info.path.BaseName()) {
return false; // Already have a loaded plugin higher in the hierarchy.
diff --git a/webkit/plugins/npapi/plugin_list_posix.cc b/webkit/plugins/npapi/plugin_list_posix.cc
index 246f859..9d35898 100644
--- a/webkit/plugins/npapi/plugin_list_posix.cc
+++ b/webkit/plugins/npapi/plugin_list_posix.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -248,7 +248,7 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
// See if we have a better version of this plugin.
for (size_t i = 0; i < plugin_groups->size(); ++i) {
const std::vector<WebPluginInfo>& plugins =
- (*plugin_groups)[i]->web_plugin_infos();
+ (*plugin_groups)[i]->web_plugins_info();
for (size_t j = 0; j < plugins.size(); ++j) {
if (plugins[j].name == info.name &&
!IsUndesirablePlugin(plugins[j])) {
diff --git a/webkit/plugins/npapi/plugin_list_unittest.cc b/webkit/plugins/npapi/plugin_list_unittest.cc
index 40a0c12..a86f699a 100644
--- a/webkit/plugins/npapi/plugin_list_unittest.cc
+++ b/webkit/plugins/npapi/plugin_list_unittest.cc
@@ -13,18 +13,21 @@ namespace npapi {
namespace {
-bool Equals(const WebPluginInfo& a, const WebPluginInfo& b) {
+bool Equals(const WebPluginInfo& a, const WebPluginInfo& b,
+ bool care_about_enabled_status) {
return (a.name == b.name &&
a.path == b.path &&
a.version == b.version &&
- a.desc == b.desc);
+ a.desc == b.desc &&
+ (!care_about_enabled_status || a.enabled == b.enabled));
}
bool Contains(const std::vector<WebPluginInfo>& list,
- const WebPluginInfo& plugin) {
+ const WebPluginInfo& plugin,
+ bool care_about_enabled_status) {
for (std::vector<WebPluginInfo>::const_iterator it = list.begin();
it != list.end(); ++it) {
- if (Equals(*it, plugin))
+ if (Equals(*it, plugin, care_about_enabled_status))
return true;
}
return false;
@@ -57,6 +60,8 @@ class PluginListTest : public testing::Test {
}
virtual void SetUp() {
+ bar_plugin_.enabled = WebPluginInfo::USER_DISABLED_POLICY_UNMANAGED;
+ plugin_list_.DisablePlugin(bar_plugin_.path);
plugin_list_.AddPluginToLoad(foo_plugin_);
plugin_list_.AddPluginToLoad(bar_plugin_);
}
@@ -71,20 +76,26 @@ TEST_F(PluginListTest, GetPlugins) {
std::vector<WebPluginInfo> plugins;
plugin_list_.GetPlugins(&plugins);
EXPECT_EQ(2u, plugins.size());
- EXPECT_TRUE(Contains(plugins, foo_plugin_));
- EXPECT_TRUE(Contains(plugins, bar_plugin_));
+ EXPECT_TRUE(Contains(plugins, foo_plugin_, true));
+ EXPECT_TRUE(Contains(plugins, bar_plugin_, true));
}
TEST_F(PluginListTest, GetPluginGroup) {
const PluginGroup* foo_group = plugin_list_.GetPluginGroup(foo_plugin_);
EXPECT_EQ(ASCIIToUTF16(kFooGroupName), foo_group->GetGroupName());
+ EXPECT_TRUE(foo_group->Enabled());
+ // The second request should return a pointer to the same instance.
+ const PluginGroup* foo_group2 = plugin_list_.GetPluginGroup(foo_plugin_);
+ EXPECT_EQ(foo_group, foo_group2);
+ const PluginGroup* bar_group = plugin_list_.GetPluginGroup(bar_plugin_);
+ EXPECT_FALSE(bar_group->Enabled());
}
TEST_F(PluginListTest, EmptyGroup) {
std::vector<PluginGroup> groups;
plugin_list_.GetPluginGroups(false, &groups);
for (size_t i = 0; i < groups.size(); ++i)
- EXPECT_GE(1U, groups[i].web_plugin_infos().size());
+ EXPECT_GE(1U, groups[i].web_plugins_info().size());
}
TEST_F(PluginListTest, BadPluginDescription) {
@@ -99,20 +110,61 @@ TEST_F(PluginListTest, BadPluginDescription) {
plugin_list_.RefreshPlugins();
std::vector<WebPluginInfo> plugins;
plugin_list_.GetPlugins(&plugins);
- ASSERT_TRUE(Contains(plugins, plugin_3043));
+ ASSERT_TRUE(Contains(plugins, plugin_3043, true));
+}
+
+TEST_F(PluginListTest, DisableAndEnableBeforeLoad) {
+ WebPluginInfo plugin_3043(ASCIIToUTF16("MyPlugin"),
+ FilePath(FILE_PATH_LITERAL("/myplugin.3.0.43")),
+ ASCIIToUTF16("3.0.43"),
+ ASCIIToUTF16("MyPlugin version 3.0.43"));
+ WebPluginInfo plugin_3045(ASCIIToUTF16("MyPlugin"),
+ FilePath(FILE_PATH_LITERAL("/myplugin.3.0.45")),
+ ASCIIToUTF16("3.0.45"),
+ ASCIIToUTF16("MyPlugin version 3.0.45"));
+ // Disable the first one and disable and then enable the second one.
+ EXPECT_TRUE(plugin_list_.DisablePlugin(plugin_3043.path));
+ EXPECT_TRUE(plugin_list_.DisablePlugin(plugin_3045.path));
+ EXPECT_TRUE(plugin_list_.EnablePlugin(plugin_3045.path));
+ // Simulate loading of the plugins.
+ plugin_list_.ClearPluginsToLoad();
+ plugin_list_.AddPluginToLoad(plugin_3043);
+ plugin_list_.AddPluginToLoad(plugin_3045);
+ // Now we should have them in the state we specified above.
+ plugin_list_.RefreshPlugins();
+ std::vector<WebPluginInfo> plugins;
+ plugin_list_.GetPlugins(&plugins);
+ plugin_3043.enabled = WebPluginInfo::USER_DISABLED_POLICY_UNMANAGED;
+ ASSERT_TRUE(Contains(plugins, plugin_3043, true));
+ ASSERT_TRUE(Contains(plugins, plugin_3045, true));
}
TEST_F(PluginListTest, HardcodedGroups) {
std::vector<PluginGroup> groups;
plugin_list_.GetPluginGroups(true, &groups);
ASSERT_EQ(2u, groups.size());
- EXPECT_EQ(1u, groups[0].web_plugin_infos().size());
+ EXPECT_TRUE(groups[0].Enabled());
+ EXPECT_EQ(1u, groups[0].web_plugins_info().size());
EXPECT_TRUE(groups[0].ContainsPlugin(FilePath(kFooPath)));
EXPECT_EQ(kFooIdentifier, groups[0].identifier());
- EXPECT_EQ(1u, groups[1].web_plugin_infos().size());
+ EXPECT_FALSE(groups[1].Enabled());
+ EXPECT_EQ(1u, groups[1].web_plugins_info().size());
EXPECT_TRUE(groups[1].ContainsPlugin(FilePath(kBarPath)));
EXPECT_EQ("bar.plugin", groups[1].identifier());
}
+TEST_F(PluginListTest, DisableBeforeLoad) {
+ // Test that a plugin group that was disabled before plugins are loaded stays
+ // disabled afterwards.
+
+ EXPECT_TRUE(plugin_list_.EnableGroup(false, ASCIIToUTF16(kFooGroupName)));
+
+ plugin_list_.RefreshPlugins();
+ std::vector<WebPluginInfo> plugins;
+ plugin_list_.GetPlugins(&plugins);
+ ASSERT_EQ(2u, plugins.size());
+ ASSERT_EQ(WebPluginInfo::USER_DISABLED_POLICY_UNMANAGED, plugins[0].enabled);
+}
+
} // namespace npapi
} // namespace webkit
diff --git a/webkit/plugins/npapi/plugin_list_win.cc b/webkit/plugins/npapi/plugin_list_win.cc
index 0f832e9..b739771 100644
--- a/webkit/plugins/npapi/plugin_list_win.cc
+++ b/webkit/plugins/npapi/plugin_list_win.cc
@@ -358,7 +358,7 @@ bool PluginList::ShouldLoadPlugin(const webkit::WebPluginInfo& info,
for (size_t i = 0; i < plugin_groups->size(); ++i) {
const std::vector<webkit::WebPluginInfo>& plugins =
- (*plugin_groups)[i]->web_plugin_infos();
+ (*plugin_groups)[i]->web_plugins_info();
for (size_t j = 0; j < plugins.size(); ++j) {
std::wstring plugin1 =
StringToLowerASCII(plugins[j].path.BaseName().value());
@@ -420,7 +420,7 @@ bool PluginList::ShouldLoadPlugin(const webkit::WebPluginInfo& info,
for (size_t i = 0; i < plugin_groups->size(); ++i) {
const std::vector<webkit::WebPluginInfo>& plugins =
- (*plugin_groups)[i]->web_plugin_infos();
+ (*plugin_groups)[i]->web_plugins_info();
for (size_t j = 0; j < plugins.size(); ++j) {
if (plugins[j].path.BaseName().value() == kOldWMPPlugin) {
(*plugin_groups)[i]->RemovePlugin(plugins[j].path);
@@ -431,7 +431,7 @@ bool PluginList::ShouldLoadPlugin(const webkit::WebPluginInfo& info,
} else if (filename == kOldWMPPlugin) {
for (size_t i = 0; i < plugin_groups->size(); ++i) {
const std::vector<webkit::WebPluginInfo>& plugins =
- (*plugin_groups)[i]->web_plugin_infos();
+ (*plugin_groups)[i]->web_plugins_info();
for (size_t j = 0; j < plugins.size(); ++j) {
if (plugins[j].path.BaseName().value() == kNewWMPPlugin)
return false;
diff --git a/webkit/plugins/webplugininfo.cc b/webkit/plugins/webplugininfo.cc
index 031dd40..0bdc255 100644
--- a/webkit/plugins/webplugininfo.cc
+++ b/webkit/plugins/webplugininfo.cc
@@ -22,7 +22,8 @@ WebPluginMimeType::WebPluginMimeType(const std::string& m,
WebPluginMimeType::~WebPluginMimeType() {}
-WebPluginInfo::WebPluginInfo() : type(PLUGIN_TYPE_NPAPI) {
+WebPluginInfo::WebPluginInfo()
+ : enabled(USER_DISABLED_POLICY_UNMANAGED), type(PLUGIN_TYPE_NPAPI) {
}
WebPluginInfo::WebPluginInfo(const WebPluginInfo& rhs)
@@ -31,6 +32,7 @@ WebPluginInfo::WebPluginInfo(const WebPluginInfo& rhs)
version(rhs.version),
desc(rhs.desc),
mime_types(rhs.mime_types),
+ enabled(rhs.enabled),
type(rhs.type) {
}
@@ -42,6 +44,7 @@ WebPluginInfo& WebPluginInfo::operator=(const WebPluginInfo& rhs) {
version = rhs.version;
desc = rhs.desc;
mime_types = rhs.mime_types;
+ enabled = rhs.enabled;
type = rhs.type;
return *this;
}
@@ -55,9 +58,15 @@ WebPluginInfo::WebPluginInfo(const string16& fake_name,
version(fake_version),
desc(fake_desc),
mime_types(),
+ enabled(USER_ENABLED_POLICY_UNMANAGED),
type(PLUGIN_TYPE_NPAPI) {
}
+bool IsPluginEnabled(const WebPluginInfo& plugin) {
+ return ((plugin.enabled & WebPluginInfo::POLICY_ENABLED) ||
+ plugin.enabled == WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED);
+}
+
bool IsPepperPlugin(const WebPluginInfo& plugin) {
return ((plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS ) ||
plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS);
diff --git a/webkit/plugins/webplugininfo.h b/webkit/plugins/webplugininfo.h
index b7bb4d3..d39c4cd 100644
--- a/webkit/plugins/webplugininfo.h
+++ b/webkit/plugins/webplugininfo.h
@@ -38,6 +38,32 @@ struct WebPluginMimeType {
// Describes an available NPAPI or Pepper plugin.
struct WebPluginInfo {
+ // Defines the possible enabled state a plugin can have.
+ // The enum values actually represent a 3-bit bitfield :
+ // |PE|PD|U| - where |PE|PD| is policy state and U is user state.
+ // PE == 1 means the plugin is forced to enabled state by policy
+ // PD == 1 means the plugin is forced to disabled by policy
+ // PE and PD CAN'T be both 1 but can be both 0 which mean no policy is set.
+ // U == 1 means the user has disabled the plugin.
+ // Because the plugin user state might have been changed before a policy was
+ // introduced the user state might contradict the policy state in which case
+ // the policy has precedence.
+ enum EnabledStates {
+ USER_ENABLED = 0,
+ USER_DISABLED = 1 << 0,
+ POLICY_DISABLED = 1 << 1,
+ POLICY_ENABLED = 1 << 2,
+ USER_ENABLED_POLICY_UNMANAGED = USER_ENABLED,
+ USER_ENABLED_POLICY_DISABLED = USER_ENABLED| POLICY_DISABLED,
+ USER_ENABLED_POLICY_ENABLED = USER_ENABLED | POLICY_ENABLED,
+ USER_DISABLED_POLICY_UNMANAGED = USER_DISABLED,
+ USER_DISABLED_POLICY_DISABLED = USER_DISABLED | POLICY_DISABLED,
+ USER_DISABLED_POLICY_ENABLED = USER_DISABLED | POLICY_ENABLED,
+ USER_MASK = USER_DISABLED,
+ MANAGED_MASK = POLICY_DISABLED | POLICY_ENABLED,
+ POLICY_UNMANAGED = -1
+ };
+
enum PluginType {
PLUGIN_TYPE_NPAPI,
PLUGIN_TYPE_PEPPER_IN_PROCESS,
@@ -70,10 +96,16 @@ struct WebPluginInfo {
// A list of all the mime types that this plugin supports.
std::vector<WebPluginMimeType> mime_types;
+ // Enabled state of the plugin. See the EnabledStates enum.
+ int enabled;
+
// Plugin type. See the PluginType enum.
int type;
};
+// Checks whether a plugin is enabled either by the user or by policy.
+bool IsPluginEnabled(const WebPluginInfo& plugin);
+
// Checks whether a plugin is a Pepper plugin, enabled or disabled.
bool IsPepperPlugin(const WebPluginInfo& plugin);
diff --git a/webkit/support/webkit_support_glue.cc b/webkit/support/webkit_support_glue.cc
index 0f85ff4..501356e 100644
--- a/webkit/support/webkit_support_glue.cc
+++ b/webkit/support/webkit_support_glue.cc
@@ -30,6 +30,7 @@ void GetPlugins(bool refresh,
webkit::WebPluginInfo plugin_info = plugins->at(i);
for (size_t j = 0; j < arraysize(kPluginBlackList); ++j) {
if (plugin_info.path.BaseName() == FilePath(kPluginBlackList[j])) {
+ webkit::npapi::PluginList::Singleton()->DisablePlugin(plugin_info.path);
plugins->erase(plugins->begin() + i);
}
}
diff --git a/webkit/tools/test_shell/test_shell.cc b/webkit/tools/test_shell/test_shell.cc
index 38e83ca..7c78dbc 100644
--- a/webkit/tools/test_shell/test_shell.cc
+++ b/webkit/tools/test_shell/test_shell.cc
@@ -675,6 +675,7 @@ void GetPlugins(bool refresh,
webkit::WebPluginInfo plugin_info = plugins->at(i);
for (size_t j = 0; j < arraysize(kPluginBlackList); ++j) {
if (plugin_info.path.BaseName() == FilePath(kPluginBlackList[j])) {
+ webkit::npapi::PluginList::Singleton()->DisablePlugin(plugin_info.path);
plugins->erase(plugins->begin() + i);
}
}