diff options
author | jkummerow@chromium.org <jkummerow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-07 13:29:41 +0000 |
---|---|---|
committer | jkummerow@chromium.org <jkummerow@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-07 13:29:41 +0000 |
commit | 79ce10352dd7f73f221a68e2e9b62bb8aa30887b (patch) | |
tree | 6ad96840fc5a452c43af2c39f154caf86c66a963 /webkit/glue/plugins | |
parent | d6166ca658f5011183ff2402d4d675e673e4e315 (diff) | |
download | chromium_src-79ce10352dd7f73f221a68e2e9b62bb8aa30887b.zip chromium_src-79ce10352dd7f73f221a68e2e9b62bb8aa30887b.tar.gz chromium_src-79ce10352dd7f73f221a68e2e9b62bb8aa30887b.tar.bz2 |
Clean up PluginGroup and related code.
To avoid data races, do not pass pointers to PluginGroup around. Instead, create copies as plain objects.
BUG=61210
TEST=existing unit tests still work; TSan no longer reports the race (see bug)
Review URL: http://codereview.chromium.org/5516004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68471 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/plugins')
-rw-r--r-- | webkit/glue/plugins/plugin_group.cc | 180 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_group.h | 64 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_group_unittest.cc | 39 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.cc | 213 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.h | 56 |
5 files changed, 321 insertions, 231 deletions
diff --git a/webkit/glue/plugins/plugin_group.cc b/webkit/glue/plugins/plugin_group.cc index e68649c..52cc132 100644 --- a/webkit/glue/plugins/plugin_group.cc +++ b/webkit/glue/plugins/plugin_group.cc @@ -16,82 +16,10 @@ const char* PluginGroup::kAdobeReader8GroupName = "Adobe Reader 8"; const char* PluginGroup::kAdobeReader9GroupName = "Adobe Reader 9"; -#if defined(OS_MACOSX) -// Plugin Groups for Mac. -// Plugins are listed here as soon as vulnerabilities and solutions -// (new versions) are published. -// TODO(panayiotis): Get the Real Player version on Mac, somehow. -static const PluginGroupDefinition kGroupDefinitions[] = { - { "apple-quicktime", "Quicktime", "QuickTime Plug-in", "", "", "7.6.6", - "http://www.apple.com/quicktime/download/" }, - { "java-runtime-environment", "Java", "Java", "", "", "", - "http://support.apple.com/kb/HT1338" }, - { "adobe-flash-player", "Flash", "Shockwave Flash", "", "", "10.1.102", - "http://get.adobe.com/flashplayer/" }, - { "silverlight-3", "Silverlight 3", "Silverlight", "0", "4", "3.0.50106.0", - "http://www.microsoft.com/getsilverlight/" }, - { "silverlight-4", "Silverlight 4", "Silverlight", "4", "5", "", - "http://www.microsoft.com/getsilverlight/" }, - { "flip4mac", "Flip4Mac", "Flip4Mac", "", "", "2.2.1", - "http://www.telestream.net/flip4mac-wmv/overview.htm" }, - { "shockwave", "Shockwave", "Shockwave for Director", "", "", "11.5.9.615", - "http://www.adobe.com/shockwave/download/" } -}; - -#elif defined(OS_WIN) -// TODO(panayiotis): We should group "RealJukebox NS Plugin" with the rest of -// the RealPlayer files. -static const PluginGroupDefinition kGroupDefinitions[] = { - { "apple-quicktime", "Quicktime", "QuickTime Plug-in", "", "", "7.6.8", - "http://www.apple.com/quicktime/download/" }, - { "java-runtime-environment", "Java 6", "Java", "", "6", "6.0.220", - "http://www.java.com/" }, - { "adobe-reader", PluginGroup::kAdobeReader9GroupName, "Adobe Acrobat", "9", - "10", "9.4.1", "http://get.adobe.com/reader/" }, - { "adobe-reader-8", PluginGroup::kAdobeReader8GroupName, "Adobe Acrobat", "0", - "9", "8.2.5", "http://get.adobe.com/reader/" }, - { "adobe-flash-player", "Flash", "Shockwave Flash", "", "", "10.1.102", - "http://get.adobe.com/flashplayer/" }, - { "silverlight-3", "Silverlight 3", "Silverlight", "0", "4", "3.0.50106.0", - "http://www.microsoft.com/getsilverlight/" }, - { "silverlight-4", "Silverlight 4", "Silverlight", "4", "5", "", - "http://www.microsoft.com/getsilverlight/" }, - { "shockwave", "Shockwave", "Shockwave for Director", "", "", "11.5.9.615", - "http://www.adobe.com/shockwave/download/" }, - { "divx-player", "DivX Player", "DivX Web Player", "", "", "1.4.3.4", - "http://download.divx.com/divx/autoupdate/player/" - "DivXWebPlayerInstaller.exe" }, - // These are here for grouping, no vulnerabilies known. - { "windows-media-player", "Windows Media Player", "Windows Media Player", - "", "", "", "" }, - { "microsoft-office", "Microsoft Office", "Microsoft Office", - "", "", "", "" }, - // TODO(panayiotis): The vulnerable versions are - // (v >= 6.0.12.1040 && v <= 6.0.12.1663) - // || v == 6.0.12.1698 || v == 6.0.12.1741 - { "realplayer", "RealPlayer", "RealPlayer", "", "", "", - "http://www.adobe.com/shockwave/download/" }, -}; - -#else -static const PluginGroupDefinition kGroupDefinitions[] = {}; -#endif - /*static*/ std::set<string16>* PluginGroup::policy_disabled_plugin_patterns_; /*static*/ -const PluginGroupDefinition* PluginGroup::GetPluginGroupDefinitions() { - return kGroupDefinitions; -} - -/*static*/ -size_t PluginGroup::GetPluginGroupDefinitionsSize() { - // TODO(viettrungluu): |arraysize()| doesn't work with zero-size arrays. - return ARRAYSIZE_UNSAFE(kGroupDefinitions); -} - -/*static*/ void PluginGroup::SetPolicyDisabledPluginPatterns( const std::set<string16>& set) { if (!policy_disabled_plugin_patterns_) @@ -157,6 +85,38 @@ PluginGroup::PluginGroup(const string16& group_name, min_version_.reset(Version::GetVersionFromString(min_version)); } +void PluginGroup::InitFrom(const PluginGroup& other) { + identifier_ = other.identifier_; + group_name_ = other.group_name_; + name_matcher_ = other.name_matcher_; + version_range_low_str_ = other.version_range_low_str_; + version_range_high_str_ = other.version_range_high_str_; + version_range_low_.reset( + Version::GetVersionFromString(version_range_low_str_)); + version_range_high_.reset( + Version::GetVersionFromString(version_range_high_str_)); + description_ = other.description_; + update_url_ = other.update_url_; + enabled_ = other.enabled_; + min_version_str_ = other.min_version_str_; + min_version_.reset(Version::GetVersionFromString(min_version_str_)); + DCHECK_EQ(other.web_plugin_infos_.size(), other.web_plugin_positions_.size()); + for (size_t i = 0; i < other.web_plugin_infos_.size(); ++i) + AddPlugin(other.web_plugin_infos_[i], other.web_plugin_positions_[i]); + if (!version_.get()) + version_.reset(Version::GetVersionFromString("0")); +} + +PluginGroup::PluginGroup(const PluginGroup& other) { + InitFrom(other); +} + +PluginGroup& PluginGroup::operator=(const PluginGroup& other) { + InitFrom(other); + return *this; +} + +/*static*/ PluginGroup* PluginGroup::FromPluginGroupDefinition( const PluginGroupDefinition& definition) { return new PluginGroup(ASCIIToUTF16(definition.name), @@ -170,56 +130,30 @@ PluginGroup* PluginGroup::FromPluginGroupDefinition( PluginGroup::~PluginGroup() { } -PluginGroup* PluginGroup::FromWebPluginInfo(const WebPluginInfo& wpi) { - // Create a matcher from the name of this plugin. +/*static*/ +std::string PluginGroup::GetIdentifier(const WebPluginInfo& wpi) { #if defined(OS_POSIX) - std::string identifier = wpi.path.BaseName().value(); + return wpi.path.BaseName().value(); #elif defined(OS_WIN) - std::string identifier = base::SysWideToUTF8(wpi.path.BaseName().value()); + return base::SysWideToUTF8(wpi.path.BaseName().value()); #endif - return new PluginGroup(wpi.name, wpi.name, std::string(), std::string(), - std::string(), std::string(), identifier); } -PluginGroup* PluginGroup::CopyOrCreatePluginGroup( - const WebPluginInfo& info) { - static PluginMap* hardcoded_plugin_groups = NULL; - if (!hardcoded_plugin_groups) { - PluginMap* groups = new PluginMap(); - const PluginGroupDefinition* definitions = GetPluginGroupDefinitions(); - for (size_t i = 0; i < GetPluginGroupDefinitionsSize(); ++i) { - PluginGroup* definition_group = PluginGroup::FromPluginGroupDefinition( - definitions[i]); - std::string identifier = definition_group->identifier(); - DCHECK(groups->find(identifier) == groups->end()); - (*groups)[identifier] = linked_ptr<PluginGroup>(definition_group); - } - hardcoded_plugin_groups = groups; - } - - // See if this plugin matches any of the hardcoded groups. - PluginGroup* hardcoded_group = FindGroupMatchingPlugin( - *hardcoded_plugin_groups, info); - if (hardcoded_group) { - // Make a copy. - return hardcoded_group->Copy(); - } else { - // Not found in our hardcoded list, create a new one. - return PluginGroup::FromWebPluginInfo(info); - } +/*static*/ +std::string PluginGroup::GetLongIdentifier(const WebPluginInfo& wpi) { +#if defined(OS_POSIX) + return wpi.path.value(); +#elif defined(OS_WIN) + return base::SysWideToUTF8(wpi.path.value()); +#endif } -PluginGroup* PluginGroup::FindGroupMatchingPlugin( - const PluginMap& plugin_groups, - const WebPluginInfo& plugin) { - for (std::map<std::string, linked_ptr<PluginGroup> >::const_iterator it = - plugin_groups.begin(); - it != plugin_groups.end(); - ++it) { - if (it->second->Match(plugin)) - return it->second.get(); - } - return NULL; +/*static*/ +PluginGroup* PluginGroup::FromWebPluginInfo(const WebPluginInfo& wpi) { + // Create a matcher from the name of this plugin. + return new PluginGroup(wpi.name, wpi.name, std::string(), std::string(), + std::string(), std::string(), + GetIdentifier(wpi)); } bool PluginGroup::Match(const WebPluginInfo& plugin) const { @@ -287,6 +221,15 @@ void PluginGroup::UpdateDescriptionAndVersion(const WebPluginInfo& plugin) { } void PluginGroup::AddPlugin(const WebPluginInfo& plugin, int position) { + // Check if this group already contains this plugin. + for (size_t i = 0; i < web_plugin_infos_.size(); ++i) { + if (web_plugin_infos_[i].name == plugin.name && + web_plugin_infos_[i].version == plugin.version && + FilePath::CompareEqualIgnoreCase(web_plugin_infos_[i].path.value(), + plugin.path.value())) { + return; + } + } web_plugin_infos_.push_back(plugin); // The position of this plugin relative to the global list of plugins. web_plugin_positions_.push_back(position); @@ -407,13 +350,18 @@ void PluginGroup::DisableOutdatedPlugins() { } void PluginGroup::Enable(bool enable) { - for (std::vector<WebPluginInfo>::const_iterator it = + bool enabled_plugin_exists = false; + for (std::vector<WebPluginInfo>::iterator it = web_plugin_infos_.begin(); it != web_plugin_infos_.end(); ++it) { if (enable && !IsPluginNameDisabledByPolicy(it->name)) { NPAPI::PluginList::Singleton()->EnablePlugin(it->path); + it->enabled = true; + enabled_plugin_exists = true; } else { + it->enabled = false; NPAPI::PluginList::Singleton()->DisablePlugin(it->path); } } + enabled_ = enabled_plugin_exists; } diff --git a/webkit/glue/plugins/plugin_group.h b/webkit/glue/plugins/plugin_group.h index 2281437..a2d1aaf 100644 --- a/webkit/glue/plugins/plugin_group.h +++ b/webkit/glue/plugins/plugin_group.h @@ -8,6 +8,7 @@ #include <map> #include <set> +#include <string> #include <vector> #include "base/gtest_prod_util.h" @@ -22,9 +23,9 @@ struct WebPluginInfo; namespace NPAPI { class PluginList; }; - -template <typename T> -class linked_ptr; +namespace plugin_test_internal { +class PluginExceptionsTableModelTest; +} // Hard-coded definitions of plugin groups. struct PluginGroupDefinition { @@ -51,23 +52,11 @@ class PluginGroup { static const char* kAdobeReader8GroupName; static const char* kAdobeReader9GroupName; - typedef std::map<std::string, linked_ptr<PluginGroup> > PluginMap; - - // Creates a PluginGroup from a PluginGroupDefinition. - static PluginGroup* FromPluginGroupDefinition( - const PluginGroupDefinition& definition); + PluginGroup(const PluginGroup& other); ~PluginGroup(); - // Creates a PluginGroup from a WebPluginInfo -- when no hard-coded - // definition is found. - static PluginGroup* FromWebPluginInfo(const WebPluginInfo& wpi); - - // Find a plugin group matching |info| in the list of hardcoded plugins and - // returns a copy of it if found, or a new group matching exactly this plugin - // otherwise. - // The caller should take ownership of the return PluginGroup. - static PluginGroup* CopyOrCreatePluginGroup(const WebPluginInfo& info); + PluginGroup& operator=(const PluginGroup& other); // Configures the set of plugin name patterns for disabling plugins via // enterprise configuration management. @@ -81,19 +70,6 @@ class PluginGroup { // the lookup key. static bool IsPluginPathDisabledByPolicy(const FilePath& plugin_path); - // Find the PluginGroup matching a Plugin in a list of plugin groups. Returns - // NULL if no matching PluginGroup is found. - static PluginGroup* FindGroupMatchingPlugin( - const std::map<std::string, linked_ptr<PluginGroup> >& plugin_groups, - const WebPluginInfo& plugin); - - // Creates a copy of this plugin group. - PluginGroup* Copy() { - return new PluginGroup(group_name_, name_matcher_, version_range_low_str_, - version_range_high_str_, min_version_str_, - update_url_, identifier_); - } - // Returns true if the given plugin matches this group. bool Match(const WebPluginInfo& plugin) const; @@ -137,10 +113,28 @@ class PluginGroup { void DisableOutdatedPlugins(); private: - FRIEND_TEST_ALL_PREFIXES(PluginGroupTest, PluginGroupDefinition); + typedef std::map<std::string, PluginGroup*> PluginMap; + + friend class NPAPI::PluginList; + friend class PluginGroupTest; + friend class TableModelArrayControllerTest; + friend class plugin_test_internal::PluginExceptionsTableModelTest; - static const PluginGroupDefinition* GetPluginGroupDefinitions(); - static size_t GetPluginGroupDefinitionsSize(); + // Generates the (short) identifier string for the given plugin. + static std::string GetIdentifier(const WebPluginInfo& wpi); + + // Generates the long identifier (based on the full file path) for the given + // plugin, to be called when the short identifier is not unique. + static std::string GetLongIdentifier(const WebPluginInfo& wpi); + + // Creates a PluginGroup from a PluginGroupDefinition. The caller takes + // ownership of the created PluginGroup. + static PluginGroup* FromPluginGroupDefinition( + const PluginGroupDefinition& definition); + + // Creates a PluginGroup from a WebPluginInfo. The caller takes ownership of + // the created PluginGroup. + static PluginGroup* FromWebPluginInfo(const WebPluginInfo& wpi); PluginGroup(const string16& group_name, const string16& name_matcher, @@ -150,6 +144,8 @@ class PluginGroup { const std::string& update_url, const std::string& identifier); + void InitFrom(const PluginGroup& other); + Version* CreateVersionFromString(const string16& version_string); // Set the description and version for this plugin group from the @@ -177,8 +173,6 @@ class PluginGroup { scoped_ptr<Version> version_; std::vector<WebPluginInfo> web_plugin_infos_; std::vector<int> web_plugin_positions_; - - DISALLOW_COPY_AND_ASSIGN(PluginGroup); }; #endif // WEBKIT_GLUE_PLUGINS_PLUGIN_GROUP_H_ diff --git a/webkit/glue/plugins/plugin_group_unittest.cc b/webkit/glue/plugins/plugin_group_unittest.cc index 467c273..1868fb4 100644 --- a/webkit/glue/plugins/plugin_group_unittest.cc +++ b/webkit/glue/plugins/plugin_group_unittest.cc @@ -14,13 +14,16 @@ #include "base/version.h" #include "testing/gtest/include/gtest/gtest.h" #include "webkit/glue/plugins/webplugininfo.h" +#include "webkit/glue/plugins/plugin_list.h" static const PluginGroupDefinition kPluginDef = { "myplugin", "MyPlugin", "MyPlugin", "", "", "3.0.44", "http://latest/" }; static const PluginGroupDefinition kPluginDef3 = { - "myplugin-3", "MyPlugin 3", "MyPlugin", "0", "4", "3.0.44", "http://latest" }; + "myplugin-3", "MyPlugin 3", "MyPlugin", "0", "4", "3.0.44", + "http://latest" }; static const PluginGroupDefinition kPluginDef4 = { - "myplugin-4", "MyPlugin 4", "MyPlugin", "4", "5", "4.0.44", "http://latest" }; + "myplugin-4", "MyPlugin 4", "MyPlugin", "4", "5", "4.0.44", + "http://latest" }; static const PluginGroupDefinition kPluginDefNotVulnerable = { "myplugin-latest", "MyPlugin", "MyPlugin", "", "", "", "http://latest" }; @@ -42,6 +45,14 @@ static WebPluginInfo kPlugin4043 = WebPluginInfo( ASCIIToUTF16("MyPlugin version 4.0.43")); class PluginGroupTest : public testing::Test { + public: + static PluginGroup* CreatePluginGroup( + const PluginGroupDefinition& definition) { + return PluginGroup::FromPluginGroupDefinition(definition); + } + static PluginGroup* CreatePluginGroup(const WebPluginInfo& wpi) { + return PluginGroup::FromWebPluginInfo(wpi); + } protected: virtual void TearDown() { PluginGroup::SetPolicyDisabledPluginPatterns(std::set<string16>()); @@ -49,7 +60,7 @@ class PluginGroupTest : public testing::Test { }; TEST(PluginGroupTest, PluginGroupMatch) { - scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition( + scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup( kPluginDef3)); EXPECT_TRUE(group->Match(kPlugin3045)); group->AddPlugin(kPlugin3045, 0); @@ -57,13 +68,13 @@ TEST(PluginGroupTest, PluginGroupMatch) { } TEST(PluginGroupTest, PluginGroupMatchCorrectVersion) { - scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition( + scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup( kPluginDef3)); EXPECT_TRUE(group->Match(kPlugin2043)); EXPECT_TRUE(group->Match(kPlugin3043)); EXPECT_FALSE(group->Match(kPlugin4043)); - group.reset(PluginGroup::FromPluginGroupDefinition(kPluginDef4)); + group.reset(PluginGroupTest::CreatePluginGroup(kPluginDef4)); EXPECT_FALSE(group->Match(kPlugin2043)); EXPECT_FALSE(group->Match(kPlugin3043)); EXPECT_TRUE(group->Match(kPlugin4043)); @@ -76,7 +87,7 @@ TEST(PluginGroupTest, PluginGroupDescription) { WebPluginInfo plugin3045(kPlugin3045); { - scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition( + scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup( kPluginDef3)); EXPECT_TRUE(group->Match(plugin3043)); group->AddPlugin(plugin3043, 0); @@ -91,7 +102,7 @@ TEST(PluginGroupTest, PluginGroupDescription) { { // Disable the first plugin. plugin3043.enabled = false; - scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition( + scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup( kPluginDef3)); EXPECT_TRUE(group->Match(plugin3043)); group->AddPlugin(plugin3043, 0); @@ -106,7 +117,7 @@ TEST(PluginGroupTest, PluginGroupDescription) { { // Disable the second plugin. plugin3045.enabled = false; - scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition( + scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup( kPluginDef3)); EXPECT_TRUE(group->Match(plugin3043)); group->AddPlugin(plugin3043, 1); @@ -121,17 +132,19 @@ TEST(PluginGroupTest, PluginGroupDescription) { TEST(PluginGroupTest, PluginGroupDefinition) { const PluginGroupDefinition* definitions = - PluginGroup::GetPluginGroupDefinitions(); - for (size_t i = 0; i < PluginGroup::GetPluginGroupDefinitionsSize(); ++i) { + NPAPI::PluginList::GetPluginGroupDefinitions(); + for (size_t i = 0; + i < NPAPI::PluginList::GetPluginGroupDefinitionsSize(); + ++i) { scoped_ptr<PluginGroup> def_group( - PluginGroup::FromPluginGroupDefinition(definitions[i])); + PluginGroupTest::CreatePluginGroup(definitions[i])); ASSERT_TRUE(def_group.get() != NULL); EXPECT_FALSE(def_group->Match(kPlugin2043)); } } TEST(PluginGroupTest, DisableOutdated) { - scoped_ptr<PluginGroup> group(PluginGroup::FromPluginGroupDefinition( + scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup( kPluginDef3)); group->AddPlugin(kPlugin3043, 0); group->AddPlugin(kPlugin3045, 1); @@ -157,7 +170,7 @@ TEST(PluginGroupTest, VersionExtraction) { for (size_t i = 0; i < arraysize(versions); i++) { const WebPluginInfo plugin = WebPluginInfo( ASCIIToUTF16("Blah Plugin"), ASCIIToUTF16(versions[i][0]), string16()); - scoped_ptr<PluginGroup> group(PluginGroup::FromWebPluginInfo(plugin)); + scoped_ptr<PluginGroup> group(PluginGroupTest::CreatePluginGroup(plugin)); EXPECT_TRUE(group->Match(plugin)); group->AddPlugin(plugin, 0); scoped_ptr<DictionaryValue> data(group->GetDataForUI()); diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc index 84736cb..5dcda7e 100644 --- a/webkit/glue/plugins/plugin_list.cc +++ b/webkit/glue/plugins/plugin_list.cc @@ -22,6 +22,78 @@ namespace NPAPI { +#if defined(OS_MACOSX) +// Plugin Groups for Mac. +// Plugins are listed here as soon as vulnerabilities and solutions +// (new versions) are published. +// TODO(panayiotis): Get the Real Player version on Mac, somehow. +static const PluginGroupDefinition kGroupDefinitions[] = { + { "apple-quicktime", "Quicktime", "QuickTime Plug-in", "", "", "7.6.6", + "http://www.apple.com/quicktime/download/" }, + { "java-runtime-environment", "Java", "Java", "", "", "", + "http://support.apple.com/kb/HT1338" }, + { "adobe-flash-player", "Flash", "Shockwave Flash", "", "", "10.1.102", + "http://get.adobe.com/flashplayer/" }, + { "silverlight-3", "Silverlight 3", "Silverlight", "0", "4", "3.0.50106.0", + "http://www.microsoft.com/getsilverlight/" }, + { "silverlight-4", "Silverlight 4", "Silverlight", "4", "5", "", + "http://www.microsoft.com/getsilverlight/" }, + { "flip4mac", "Flip4Mac", "Flip4Mac", "", "", "2.2.1", + "http://www.telestream.net/flip4mac-wmv/overview.htm" }, + { "shockwave", "Shockwave", "Shockwave for Director", "", "", "11.5.9.615", + "http://www.adobe.com/shockwave/download/" } +}; + +#elif defined(OS_WIN) +// TODO(panayiotis): We should group "RealJukebox NS Plugin" with the rest of +// the RealPlayer files. +static const PluginGroupDefinition kGroupDefinitions[] = { + { "apple-quicktime", "Quicktime", "QuickTime Plug-in", "", "", "7.6.8", + "http://www.apple.com/quicktime/download/" }, + { "java-runtime-environment", "Java 6", "Java", "", "6", "6.0.220", + "http://www.java.com/" }, + { "adobe-reader", PluginGroup::kAdobeReader9GroupName, "Adobe Acrobat", "9", + "10", "9.4.1", "http://get.adobe.com/reader/" }, + { "adobe-reader-8", PluginGroup::kAdobeReader8GroupName, "Adobe Acrobat", "0", + "9", "8.2.5", "http://get.adobe.com/reader/" }, + { "adobe-flash-player", "Flash", "Shockwave Flash", "", "", "10.1.102", + "http://get.adobe.com/flashplayer/" }, + { "silverlight-3", "Silverlight 3", "Silverlight", "0", "4", "3.0.50106.0", + "http://www.microsoft.com/getsilverlight/" }, + { "silverlight-4", "Silverlight 4", "Silverlight", "4", "5", "", + "http://www.microsoft.com/getsilverlight/" }, + { "shockwave", "Shockwave", "Shockwave for Director", "", "", "11.5.9.615", + "http://www.adobe.com/shockwave/download/" }, + { "divx-player", "DivX Player", "DivX Web Player", "", "", "1.4.3.4", + "http://download.divx.com/divx/autoupdate/player/" + "DivXWebPlayerInstaller.exe" }, + // These are here for grouping, no vulnerabilies known. + { "windows-media-player", "Windows Media Player", "Windows Media Player", + "", "", "", "" }, + { "microsoft-office", "Microsoft Office", "Microsoft Office", + "", "", "", "" }, + // TODO(panayiotis): The vulnerable versions are + // (v >= 6.0.12.1040 && v <= 6.0.12.1663) + // || v == 6.0.12.1698 || v == 6.0.12.1741 + { "realplayer", "RealPlayer", "RealPlayer", "", "", "", + "http://www.adobe.com/shockwave/download/" }, +}; + +#else +static const PluginGroupDefinition kGroupDefinitions[] = {}; +#endif + +// static +const PluginGroupDefinition* PluginList::GetPluginGroupDefinitions() { + return kGroupDefinitions; +} + +// static +size_t PluginList::GetPluginGroupDefinitionsSize() { + // TODO(viettrungluu): |arraysize()| doesn't work with zero-size arrays. + return ARRAYSIZE_UNSAFE(kGroupDefinitions); +} + base::LazyInstance<PluginList> g_singleton(base::LINKER_INITIALIZED); // static @@ -157,8 +229,10 @@ bool PluginList::CreateWebPluginInfo(const PluginVersionInfo& pvi, PluginList::PluginList() : plugins_loaded_(false), plugins_need_refresh_(false), - disable_outdated_plugins_(false) { + disable_outdated_plugins_(false), + next_priority_(0) { PlatformInit(); + AddHardcodedPluginGroups(); } bool PluginList::ShouldDisableGroup(const string16& group_name) { @@ -233,34 +307,26 @@ void PluginList::LoadPlugins(bool refresh) { // plugins or plugin-groups to their original, "pre-policy" state, so // plugins and groups are only changed to a more "safe" state after a policy // change, i.e. from enabled to disabled. See bug 54681. - PluginMap plugin_groups; - GetPluginGroups(&new_plugins, &plugin_groups); - for (PluginMap::const_iterator it = plugin_groups.begin(); - it != plugin_groups.end(); ++it) { - PluginGroup* group = it->second.get(); + for (PluginGroup::PluginMap::iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { + PluginGroup* group = it->second; string16 group_name = group->GetGroupName(); if (ShouldDisableGroup(group_name)) { - it->second->Enable(false); + group->Enable(false); } if (disable_outdated_plugins_) { group->DisableOutdatedPlugins(); - if (!group->Enabled()) { - AutoLock lock(lock_); - disabled_groups_.insert(group_name); - } + } + if (!group->Enabled()) { + AutoLock lock(lock_); + disabled_groups_.insert(group_name); } } // Only update the data now since loading plugins can take a while. AutoLock lock(lock_); - // Mark disabled plugins as such. - for (size_t i = 0; i < new_plugins.size(); ++i) { - if (disabled_plugins_.count(new_plugins[i].path)) - new_plugins[i].enabled = false; - } - plugins_ = new_plugins; plugins_loaded_ = true; } @@ -294,7 +360,17 @@ void PluginList::LoadPlugin(const FilePath& path, } } + // Mark disabled plugins as such. (This has to happen before calling + // |AddToPluginGroups(plugin_info)|.) + if (disabled_plugins_.count(plugin_info.path)) { + plugin_info.enabled = false; + } else { + plugin_info.enabled = true; + } + + AutoLock lock(lock_); plugins->push_back(plugin_info); + AddToPluginGroups(plugin_info); } bool PluginList::SupportsType(const WebPluginInfo& info, @@ -476,45 +552,75 @@ bool PluginList::GetPluginInfoByPath(const FilePath& plugin_path, return false; } -void PluginList::GetPluginGroups(bool load_if_necessary, - PluginMap* plugin_groups) { +void PluginList::GetPluginGroups( + bool load_if_necessary, + std::vector<PluginGroup>* plugin_groups) { if (load_if_necessary) LoadPlugins(false); + plugin_groups->clear(); + for (PluginGroup::PluginMap::const_iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { + plugin_groups->push_back(*it->second); + } +} +const PluginGroup* PluginList::GetPluginGroup( + const WebPluginInfo& web_plugin_info) { AutoLock lock(lock_); - GetPluginGroups(&plugins_, plugin_groups); + return AddToPluginGroups(web_plugin_info); } -// static -void PluginList::GetPluginGroups(const std::vector<WebPluginInfo>* plugins, - PluginMap* plugin_groups) { - plugin_groups->clear(); - // We first search for an existing group that matches our name, - // and only create a new group if we can't find any. - for (size_t i = 0; i < plugins->size(); ++i) { - const WebPluginInfo& web_plugin = (*plugins)[i]; - PluginGroup* group = PluginGroup::FindGroupMatchingPlugin( - *plugin_groups, web_plugin); - if (!group) { - group = PluginGroup::CopyOrCreatePluginGroup(web_plugin); - std::string identifier = group->identifier(); - // If the identifier is not unique, use the full path. This means that we - // probably won't be able to search for this group by identifier, but at - // least it's going to be in the set of plugin groups, and if there - // is already a plug-in with the same filename, it's probably going to - // handle the same MIME types (and it has a higher priority), so this one - // is not going to run anyway. - if (plugin_groups->find(identifier) != plugin_groups->end()) -#if defined(OS_POSIX) - identifier = web_plugin.path.value(); -#elif defined(OS_WIN) - identifier = base::SysWideToUTF8(web_plugin.path.value()); -#endif - DCHECK(plugin_groups->find(identifier) == plugin_groups->end()); - (*plugin_groups)[identifier] = linked_ptr<PluginGroup>(group); - } - group->AddPlugin(web_plugin, i); +string16 PluginList::GetPluginGroupName(std::string identifier) { + PluginGroup::PluginMap::iterator it = plugin_groups_.find(identifier); + if (it == plugin_groups_.end()) { + return string16(); + } + return it->second->GetGroupName(); +} + +std::string PluginList::GetPluginGroupIdentifier( + const WebPluginInfo& web_plugin_info) { + AutoLock lock(lock_); + PluginGroup* group = AddToPluginGroups(web_plugin_info); + return group->identifier(); +} + +void PluginList::AddHardcodedPluginGroups() { + AutoLock lock(lock_); + const PluginGroupDefinition* definitions = GetPluginGroupDefinitions(); + for (size_t i = 0; i < GetPluginGroupDefinitionsSize(); ++i) { + PluginGroup* definition_group = PluginGroup::FromPluginGroupDefinition( + definitions[i]); + std::string identifier = definition_group->identifier(); + DCHECK(plugin_groups_.find(identifier) == plugin_groups_.end()); + plugin_groups_.insert(std::make_pair(identifier, definition_group)); + } +} + +PluginGroup* PluginList::AddToPluginGroups( + const WebPluginInfo& web_plugin_info) { + PluginGroup* group = NULL; + for (PluginGroup::PluginMap::iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { + if (it->second->Match(web_plugin_info)) + group = it->second; + } + if (!group) { + group = PluginGroup::FromWebPluginInfo(web_plugin_info); + std::string identifier = group->identifier(); + // If the identifier is not unique, use the full path. This means that we + // probably won't be able to search for this group by identifier, but at + // least it's going to be in the set of plugin groups, and if there + // is already a plug-in with the same filename, it's probably going to + // handle the same MIME types (and it has a higher priority), so this one + // is not going to run anyway. + if (plugin_groups_.find(identifier) != plugin_groups_.end()) + identifier = PluginGroup::GetLongIdentifier(web_plugin_info); + DCHECK(plugin_groups_.find(identifier) == plugin_groups_.end()); + plugin_groups_.insert(std::make_pair(identifier, group)); } + group->AddPlugin(web_plugin_info, next_priority_++); + return group; } bool PluginList::EnablePlugin(const FilePath& filename) { @@ -583,10 +689,8 @@ bool PluginList::EnableGroup(bool enable, const string16& group_name) { } } - PluginMap plugin_groups; - GetPluginGroups(false, &plugin_groups); - for (PluginMap::const_iterator it = plugin_groups.begin(); - it != plugin_groups.end(); ++it) { + for (PluginGroup::PluginMap::iterator it = plugin_groups_.begin(); + it != plugin_groups_.end(); ++it) { if (it->second->GetGroupName() == group_name) { if (it->second->Enabled() != enable) { it->second->Enable(enable); @@ -608,6 +712,9 @@ PluginList::~PluginList() { void PluginList::Shutdown() { // TODO + // Note: plugin_groups_ contains simple pointers of type PluginGroup*, but + // since this singleton lives until the process is destroyed, no explicit + // cleanup is necessary. } } // namespace NPAPI diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h index 101e6b7..734cc6d 100644 --- a/webkit/glue/plugins/plugin_list.h +++ b/webkit/glue/plugins/plugin_list.h @@ -5,11 +5,9 @@ #ifndef WEBKIT_GLUE_PLUGINS_PLUGIN_LIST_H_ #define WEBKIT_GLUE_PLUGINS_PLUGIN_LIST_H_ -#include <map> #include <set> #include <string> #include <vector> -#include <set> #include "base/basictypes.h" #include "base/file_path.h" @@ -80,6 +78,9 @@ class PluginList { // by a command line switch. static bool DebugPluginLoading(); + static const PluginGroupDefinition* GetPluginGroupDefinitions(); + static size_t GetPluginGroupDefinitionsSize(); + // Returns true iff the plugin list has been loaded already. bool PluginsLoaded(); @@ -157,13 +158,28 @@ class PluginList { bool GetPluginInfoByPath(const FilePath& plugin_path, WebPluginInfo* info); - typedef std::map<std::string, linked_ptr<PluginGroup> > PluginMap; - - // Fill the map from identifier to plugin group for all plugin groups. If - // |load_if_necessary| is set, the plugins will be loaded if they haven't - // already been loaded, or if Refresh() has been called in the meantime; - // otherwise a possibly empty or stale list may be returned. - void GetPluginGroups(bool load_if_necessary, PluginMap* plugin_groups); + // Populates the given vector with all available plugin groups. + void GetPluginGroups(bool load_if_necessary, + std::vector<PluginGroup>* plugin_groups); + + // 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 WebPluginInfo& web_plugin_info); + + // Returns the name of the PluginGroup with the given identifier. + // If no such group exists, an empty string is returned. + string16 GetPluginGroupName(std::string identifier); + + // Returns the identifier string of the PluginGroup corresponding to the given + // WebPluginInfo. If no such group exists, it is created and added to the + // cache. + std::string GetPluginGroupIdentifier(const WebPluginInfo& web_plugin_info); // Load a specific plugin with full path. void LoadPlugin(const FilePath& filename, @@ -198,9 +214,20 @@ class PluginList { ~PluginList(); private: + FRIEND_TEST_ALL_PREFIXES(PluginGroupTest, PluginGroupDefinition); + // Constructors are private for singletons PluginList(); + // Creates PluginGroups for the static group definitions, and adds them to + // the PluginGroup cache of this PluginList. + void AddHardcodedPluginGroups(); + + // Adds the given WebPluginInfo to its corresponding group, creating it if + // necessary, and returns the group. + // Callers need to protect calls to this method by a lock themselves. + PluginGroup* AddToPluginGroups(const WebPluginInfo& web_plugin_info); + // Load all plugins from the default plugins directory void LoadPlugins(bool refresh); @@ -224,10 +251,6 @@ class PluginList { // list of disabled groups as well. bool ShouldDisableGroup(const string16& group_name); - // Like GetPluginGroups above, but works on a given vector of plugins. - static void GetPluginGroups(const std::vector<WebPluginInfo>* plugins, - PluginMap* plugin_groups); - // Returns true if the given WebPluginInfo supports "mime-type". // mime_type should be all lower case. static bool SupportsType(const WebPluginInfo& info, @@ -291,11 +314,16 @@ class PluginList { // Path names of plugins to disable (the default is to enable them all). std::set<FilePath> disabled_plugins_; - // Group names disable (the default is to enable them all). + // Group names to disable (the default is to enable them all). std::set<string16> disabled_groups_; bool disable_outdated_plugins_; + // Holds the currently available plugin groups. + PluginGroup::PluginMap plugin_groups_; + + int next_priority_; + // Need synchronization for the above members since this object can be // accessed on multiple threads. Lock lock_; |