diff options
-rw-r--r-- | chrome/browser/extensions/extension.cc | 13 | ||||
-rw-r--r-- | chrome/browser/extensions/extension.h | 10 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 17 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 2 | ||||
-rw-r--r-- | chrome/browser/plugin_service.cc | 6 | ||||
-rw-r--r-- | chrome/browser/plugin_service.h | 5 | ||||
-rw-r--r-- | chrome/test/data/extensions/good/extension2/2/manifest.json | 3 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.cc | 20 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_list.h | 10 |
9 files changed, 80 insertions, 6 deletions
diff --git a/chrome/browser/extensions/extension.cc b/chrome/browser/extensions/extension.cc index b886d85..d75ed5e 100644 --- a/chrome/browser/extensions/extension.cc +++ b/chrome/browser/extensions/extension.cc @@ -25,6 +25,7 @@ const wchar_t* Extension::kNameKey = L"name"; const wchar_t* Extension::kRunAtKey = L"run_at"; const wchar_t* Extension::kVersionKey = L"version"; const wchar_t* Extension::kZipHashKey = L"zip_hash"; +const wchar_t* Extension::kPluginsDirKey = L"plugins_dir"; const char* Extension::kRunAtDocumentStartValue = "document_start"; const char* Extension::kRunAtDocumentEndValue = "document_end"; @@ -67,6 +68,8 @@ const char* Extension::kInvalidVersionError = "Required value 'version' is missing or invalid."; const char* Extension::kInvalidZipHashError = "Required key 'zip_hash' is missing or invalid."; +const char* Extension::kInvalidPluginsDirError = + "Invalid value for 'plugins_dir'."; const std::string Extension::VersionString() const { return version_->GetString(); @@ -230,6 +233,16 @@ bool Extension::InitFromValue(const DictionaryValue& source, } } + // Initialize plugins dir (optional). + if (source.HasKey(kPluginsDirKey)) { + std::string plugins_dir; + if (!source.GetString(kPluginsDirKey, &plugins_dir)) { + *error = kInvalidPluginsDirError; + return false; + } + plugins_dir_ = path_.AppendASCII(plugins_dir); + } + // Initialize content scripts (optional). if (source.HasKey(kContentScriptsKey)) { ListValue* list_value; diff --git a/chrome/browser/extensions/extension.h b/chrome/browser/extensions/extension.h index eae110c..cc44cd5 100644 --- a/chrome/browser/extensions/extension.h +++ b/chrome/browser/extensions/extension.h @@ -47,6 +47,7 @@ class Extension { static const wchar_t* kRunAtKey; static const wchar_t* kVersionKey; static const wchar_t* kZipHashKey; + static const wchar_t* kPluginsDirKey; // Some values expected in manifests. static const char* kRunAtDocumentStartValue; @@ -69,6 +70,7 @@ class Extension { static const char* kInvalidRunAtError; static const char* kInvalidVersionError; static const char* kInvalidZipHashError; + static const char* kInvalidPluginsDirError; // Creates an absolute url to a resource inside an extension. The // |extension_url| argument should be the url() from an Extension object. The @@ -117,6 +119,11 @@ class Extension { return content_scripts_; } + // Path to the directory of NPAPI plugins that the extension contains. + const FilePath& plugins_dir() const { + return plugins_dir_; + } + // Initialize the extension from a parsed manifest. bool InitFromValue(const DictionaryValue& value, std::string* error); @@ -142,6 +149,9 @@ class Extension { // Paths to the content scripts the extension contains. UserScriptList content_scripts_; + // Path to the directory of NPAPI plugins that the extension contains. + FilePath plugins_dir_; + // A SHA1 hash of the contents of the zip file. Note that this key is only // present in the manifest that's prepended to the zip. The inner manifest // will not have this key. diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 13d43a5..2f10da0 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -15,6 +15,7 @@ #include "net/base/file_stream.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/user_script_master.h" +#include "chrome/browser/plugin_service.h" #include "chrome/common/json_value_serializer.h" #include "chrome/common/notification_service.h" #include "chrome/common/unzip.h" @@ -101,9 +102,23 @@ void ExtensionsService::OnExtensionsLoadedFromDirectory( extensions_.insert(extensions_.end(), new_extensions->begin(), new_extensions->end()); - // Tell UserScriptMaster about any scripts in the loaded extensions. + bool found_plugin = false; + + // TODO: Fix race here. A page could need a user script on startup, before + // the user script is loaded. We need to freeze the renderer in that case. + // TODO(mpcomplete): We also need to force a renderer to refresh its cache of + // the plugin list when we inject user scripts, since it could have a stale + // version by the time extensions are loaded. + for (ExtensionList::iterator extension = extensions_.begin(); extension != extensions_.end(); ++extension) { + // Tell NPAPI about any plugins in the loaded extensions. + if (!(*extension)->plugins_dir().empty()) { + PluginService::GetInstance()->AddExtraPluginDir( + (*extension)->plugins_dir()); + } + + // Tell UserScriptMaster about any scripts in the loaded extensions. const UserScriptList& scripts = (*extension)->content_scripts(); for (UserScriptList::const_iterator script = scripts.begin(); script != scripts.end(); ++script) { diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 4c38801..6040823 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -177,6 +177,8 @@ TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectorySuccess) { frontend->extensions()->at(1)->name()); EXPECT_EQ(std::string(""), frontend->extensions()->at(1)->description()); + EXPECT_EQ(frontend->extensions()->at(1)->path().AppendASCII("npapi").value(), + frontend->extensions()->at(1)->plugins_dir().value()); ASSERT_EQ(0u, frontend->extensions()->at(1)->content_scripts().size()); EXPECT_EQ(std::string("com.google.myextension3"), diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index 7889f79..ea25346 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -69,6 +69,12 @@ const FilePath& PluginService::GetChromePluginDataDir() { return chrome_plugin_data_dir_; } +void PluginService::AddExtraPluginDir(const FilePath& plugin_dir) { + AutoLock lock(lock_); + NPAPI::PluginList::ResetPluginsLoaded(); + NPAPI::PluginList::AddExtraPluginDir(plugin_dir); +} + const std::wstring& PluginService::GetUILocale() { return ui_locale_; } diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h index 42c0cf6..d4f9368 100644 --- a/chrome/browser/plugin_service.h +++ b/chrome/browser/plugin_service.h @@ -47,6 +47,11 @@ class PluginService { void SetChromePluginDataDir(const FilePath& data_dir); const FilePath& GetChromePluginDataDir(); + // Add an extra plugin directory to scan when we actually do the loading. + // This will force a refresh of the plugin list the next time plugins are + // requested. + void AddExtraPluginDir(const FilePath& plugin_dir); + // Gets the browser's UI locale. const std::wstring& GetUILocale(); diff --git a/chrome/test/data/extensions/good/extension2/2/manifest.json b/chrome/test/data/extensions/good/extension2/2/manifest.json index 4e157c4..5e727ec 100644 --- a/chrome/test/data/extensions/good/extension2/2/manifest.json +++ b/chrome/test/data/extensions/good/extension2/2/manifest.json @@ -2,5 +2,6 @@ "format_version": 1,
"id": "com.google.myextension2",
"version": "1.0.0.0",
- "name": "My extension 2"
+ "name": "My extension 2",
+ "plugins_dir": "npapi"
}
diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc index 3f308d6..a2e369e 100644 --- a/webkit/glue/plugins/plugin_list.cc +++ b/webkit/glue/plugins/plugin_list.cc @@ -36,17 +36,25 @@ PluginList* PluginList::Singleton() { } // static -void PluginList::AddExtraPluginPath(const FilePath& plugin_path) { +void PluginList::ResetPluginsLoaded() { // We access the singleton directly, and not through Singleton(), since // we don't want LoadPlugins() to be called. - DCHECK(!g_singleton.Pointer()->plugins_loaded_); + g_singleton.Pointer()->plugins_loaded_ = false; +} +// static +void PluginList::AddExtraPluginPath(const FilePath& plugin_path) { + DCHECK(!g_singleton.Pointer()->plugins_loaded_); g_singleton.Pointer()->extra_plugin_paths_.push_back(plugin_path); } +// static +void PluginList::AddExtraPluginDir(const FilePath& plugin_dir) { + DCHECK(!g_singleton.Pointer()->plugins_loaded_); + g_singleton.Pointer()->extra_plugin_dirs_.push_back(plugin_dir); +} + void PluginList::RegisterInternalPlugin(const PluginVersionInfo& info) { - // We access the singleton directly, and not through Singleton(), since - // we don't want LoadPlugins() to be called. DCHECK(!g_singleton.Pointer()->plugins_loaded_); g_singleton.Pointer()->internal_plugins_.push_back(info); } @@ -157,6 +165,10 @@ void PluginList::LoadPlugins(bool refresh) { LoadPluginsFromDir(directories_to_scan[i]); } + for (size_t i = 0; i < extra_plugin_dirs_.size(); ++i) { + LoadPluginsFromDir(extra_plugin_dirs_[i]); + } + for (size_t i = 0; i < extra_plugin_paths_.size(); ++i) LoadPlugin(extra_plugin_paths_[i]); diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h index d64131e..3b7b84a 100644 --- a/webkit/glue/plugins/plugin_list.h +++ b/webkit/glue/plugins/plugin_list.h @@ -75,11 +75,18 @@ class PluginList { // the first time. static PluginList* Singleton(); + // Clear the plugins_loaded_ bit to force a refresh next time we retrieve + // plugins. + static void ResetPluginsLoaded(); + // Add an extra plugin to load when we actually do the loading. This is // static because we want to be able to add to it without searching the disk // for plugins. Must be called before the plugins have been loaded. static void AddExtraPluginPath(const FilePath& plugin_path); + // Same as above, but specifies a directory in which to search for plugins. + static void AddExtraPluginDir(const FilePath& plugin_dir); + // Register an internal plugin with the specified plugin information and // function pointers. An internal plugin must be registered before it can // be loaded using PluginList::LoadPlugin(). @@ -204,6 +211,9 @@ class PluginList { // Extra plugin paths that we want to search when loading. std::vector<FilePath> extra_plugin_paths_; + // Extra plugin directories that we want to search when loading. + std::vector<FilePath> extra_plugin_dirs_; + // Holds information about internal plugins. std::vector<PluginVersionInfo> internal_plugins_; |