diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-18 17:15:00 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-18 17:15:00 +0000 |
commit | cebc3dc5b2649fba2dd4e5c38197f367cbe296ad (patch) | |
tree | 5fdabab303791a373f741fed1caf15b4b967012f /content | |
parent | 197d77b84fe78fd08bdfc72553b297111142a9f2 (diff) | |
download | chromium_src-cebc3dc5b2649fba2dd4e5c38197f367cbe296ad.zip chromium_src-cebc3dc5b2649fba2dd4e5c38197f367cbe296ad.tar.gz chromium_src-cebc3dc5b2649fba2dd4e5c38197f367cbe296ad.tar.bz2 |
Move PepperPluginRegistry to content, while leaving the Chrome specific bits (NaCl, registration of Chrome plugins like pdf/remoting/flash) behind.
Review URL: http://codereview.chromium.org/6869051
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81959 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/plugin_service.cc | 2 | ||||
-rw-r--r-- | content/browser/ppapi_broker_process_host.cc | 2 | ||||
-rw-r--r-- | content/browser/ppapi_plugin_process_host.cc | 2 | ||||
-rw-r--r-- | content/browser/zygote_main_linux.cc | 2 | ||||
-rw-r--r-- | content/common/content_client.h | 9 | ||||
-rw-r--r-- | content/common/pepper_plugin_registry.cc | 233 | ||||
-rw-r--r-- | content/common/pepper_plugin_registry.h | 125 | ||||
-rw-r--r-- | content/content_common.gypi | 2 | ||||
-rw-r--r-- | content/renderer/pepper_plugin_delegate_impl.cc | 2 | ||||
-rw-r--r-- | content/renderer/render_view.cc | 2 |
10 files changed, 373 insertions, 8 deletions
diff --git a/content/browser/plugin_service.cc b/content/browser/plugin_service.cc index 703235e..581e404 100644 --- a/content/browser/plugin_service.cc +++ b/content/browser/plugin_service.cc @@ -21,7 +21,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/default_plugin.h" #include "chrome/common/logging_chrome.h" -#include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/render_messages.h" #include "content/browser/browser_thread.h" #include "content/browser/ppapi_plugin_process_host.h" @@ -29,6 +28,7 @@ #include "content/browser/renderer_host/render_view_host.h" #include "content/common/notification_service.h" #include "content/common/notification_type.h" +#include "content/common/pepper_plugin_registry.h" #include "content/common/plugin_messages.h" #include "content/common/view_messages.h" #include "webkit/plugins/npapi/plugin_constants_win.h" diff --git a/content/browser/ppapi_broker_process_host.cc b/content/browser/ppapi_broker_process_host.cc index a0c8498..57298de 100644 --- a/content/browser/ppapi_broker_process_host.cc +++ b/content/browser/ppapi_broker_process_host.cc @@ -9,10 +9,10 @@ #include "base/process_util.h" #include "base/utf_string_conversions.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/render_messages.h" #include "content/browser/plugin_service.h" #include "content/browser/renderer_host/render_message_filter.h" +#include "content/common/pepper_plugin_registry.h" #include "ipc/ipc_switches.h" #include "ppapi/proxy/ppapi_messages.h" diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index a19e57a..f1729d8 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc @@ -9,10 +9,10 @@ #include "base/process_util.h" #include "base/utf_string_conversions.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/render_messages.h" #include "content/browser/plugin_service.h" #include "content/browser/renderer_host/render_message_filter.h" +#include "content/common/pepper_plugin_registry.h" #include "ipc/ipc_switches.h" #include "ppapi/proxy/ppapi_messages.h" diff --git a/content/browser/zygote_main_linux.cc b/content/browser/zygote_main_linux.cc index a0d0ef0..ef9dd0b 100644 --- a/content/browser/zygote_main_linux.cc +++ b/content/browser/zygote_main_linux.cc @@ -38,10 +38,10 @@ #include "crypto/nss_util.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/pepper_plugin_registry.h" #include "content/common/chrome_descriptors.h" #include "content/common/font_config_ipc_linux.h" #include "content/common/main_function_params.h" +#include "content/common/pepper_plugin_registry.h" #include "content/common/process_watcher.h" #include "content/common/result_codes.h" #include "content/common/sandbox_methods_linux.h" diff --git a/content/common/content_client.h b/content/common/content_client.h index 9b7da6f..f0a272e 100644 --- a/content/common/content_client.h +++ b/content/common/content_client.h @@ -6,10 +6,13 @@ #define CONTENT_COMMON_CONTENT_CLIENT_H_ #pragma once +#include <vector> + #include "base/basictypes.h" class GURL; struct GPUInfo; +struct PepperPluginInfo; namespace content { @@ -36,13 +39,15 @@ class ContentClient { ContentRendererClient* renderer() { return renderer_; } void set_renderer(ContentRendererClient* r) { renderer_ = r; } - // Sets the URL that is logged if the child process crashes. Use GURL() to - // clear the URL. + // Sets the currently active URL. Use GURL() to clear the URL. virtual void SetActiveURL(const GURL& url) {} // Sets the data on the current gpu. virtual void SetGpuInfo(const GPUInfo& gpu_info) {} + // Gives the embedder a chance to register its own pepper plugins. + virtual void AddPepperPlugins(std::vector<PepperPluginInfo>* plugins) {} + private: // The embedder API for participating in browser logic. ContentBrowserClient* browser_; diff --git a/content/common/pepper_plugin_registry.cc b/content/common/pepper_plugin_registry.cc new file mode 100644 index 0000000..2da9a0f --- /dev/null +++ b/content/common/pepper_plugin_registry.cc @@ -0,0 +1,233 @@ +// Copyright (c) 2011 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. + +#include "content/common/pepper_plugin_registry.h" + +#include "base/command_line.h" +#include "base/file_util.h" +#include "base/native_library.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" +#include "content/common/child_process.h" +#include "content/common/content_client.h" +#include "content/common/content_switches.h" +#include "webkit/plugins/npapi/plugin_list.h" + +namespace { + +// Appends any plugins from the command line to the given vector. +void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) { + bool out_of_process = + CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiOutOfProcess); + const std::string value = + CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kRegisterPepperPlugins); + if (value.empty()) + return; + + // FORMAT: + // command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> ) + // plugin-entry = + // <file-path> + + // ["#" + <name> + ["#" + <description> + ["#" + <version>]]] + + // *1( LWS + ";" + LWS + <mime-type> ) + + std::vector<std::string> modules; + base::SplitString(value, ',', &modules); + for (size_t i = 0; i < modules.size(); ++i) { + std::vector<std::string> parts; + base::SplitString(modules[i], ';', &parts); + if (parts.size() < 2) { + DLOG(ERROR) << "Required mime-type not found"; + continue; + } + + std::vector<std::string> name_parts; + base::SplitString(parts[0], '#', &name_parts); + + PepperPluginInfo plugin; + plugin.is_out_of_process = out_of_process; +#if defined(OS_WIN) + // This means we can't provide plugins from non-ASCII paths, but + // since this switch is only for development I don't think that's + // too awful. + plugin.path = FilePath(ASCIIToUTF16(name_parts[0])); +#else + plugin.path = FilePath(name_parts[0]); +#endif + if (name_parts.size() > 1) + plugin.name = name_parts[1]; + if (name_parts.size() > 2) + plugin.description = name_parts[2]; + if (name_parts.size() > 3) + plugin.version = name_parts[3]; + for (size_t j = 1; j < parts.size(); ++j) { + webkit::npapi::WebPluginMimeType mime_type(parts[j], + std::string(), + plugin.description); + plugin.mime_types.push_back(mime_type); + } + + plugins->push_back(plugin); + } +} + +} // namespace + +webkit::npapi::WebPluginInfo PepperPluginInfo::ToWebPluginInfo() const { + webkit::npapi::WebPluginInfo info; + + info.name = name.empty() ? path.BaseName().LossyDisplayName() : + ASCIIToUTF16(name); + info.path = path; + info.version = ASCIIToUTF16(version); + info.desc = ASCIIToUTF16(description); + info.mime_types = mime_types; + + webkit::npapi::WebPluginInfo::EnabledStates enabled_state = + webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED; + + if (!enabled) { + enabled_state = + webkit::npapi::WebPluginInfo::USER_DISABLED_POLICY_UNMANAGED; + } + + info.enabled = enabled_state; + return info; +} + +PepperPluginInfo::PepperPluginInfo() + : is_internal(false), + is_out_of_process(false), + enabled(true) { +} + +PepperPluginInfo::~PepperPluginInfo() { +} + +// static +PepperPluginRegistry* PepperPluginRegistry::GetInstance() { + static PepperPluginRegistry* registry = NULL; + // This object leaks. It is a temporary hack to work around a crash. + // http://code.google.com/p/chromium/issues/detail?id=63234 + if (!registry) + registry = new PepperPluginRegistry; + return registry; +} + +// static +void PepperPluginRegistry::ComputeList(std::vector<PepperPluginInfo>* plugins) { + content::GetContentClient()->AddPepperPlugins(plugins); + ComputePluginsFromCommandLine(plugins); +} + +// static +void PepperPluginRegistry::PreloadModules() { + std::vector<PepperPluginInfo> plugins; + ComputeList(&plugins); + for (size_t i = 0; i < plugins.size(); ++i) { + if (!plugins[i].is_internal) { + base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path); + LOG_IF(WARNING, !library) << "Unable to load plugin " + << plugins[i].path.value(); + } + } +} + +const PepperPluginInfo* PepperPluginRegistry::GetInfoForPlugin( + const FilePath& path) const { + for (size_t i = 0; i < plugin_list_.size(); ++i) { + if (path == plugin_list_[i].path) + return &plugin_list_[i]; + } + return NULL; +} + +webkit::ppapi::PluginModule* PepperPluginRegistry::GetLiveModule( + const FilePath& path) { + NonOwningModuleMap::iterator it = live_modules_.find(path); + if (it == live_modules_.end()) + return NULL; + return it->second; +} + +void PepperPluginRegistry::AddLiveModule(const FilePath& path, + webkit::ppapi::PluginModule* module) { + DCHECK(live_modules_.find(path) == live_modules_.end()); + live_modules_[path] = module; +} + +void PepperPluginRegistry::PluginModuleDead( + webkit::ppapi::PluginModule* dead_module) { + // DANGER: Don't dereference the dead_module pointer! It may be in the + // process of being deleted. + + // Modules aren't destroyed very often and there are normally at most a + // couple of them. So for now we just do a brute-force search. + for (NonOwningModuleMap::iterator i = live_modules_.begin(); + i != live_modules_.end(); ++i) { + if (i->second == dead_module) { + live_modules_.erase(i); + return; + } + } + NOTREACHED(); // Should have always found the module above. +} + +PepperPluginRegistry::~PepperPluginRegistry() { + // Explicitly clear all preloaded modules first. This will cause callbacks + // to erase these modules from the live_modules_ list, and we don't want + // that to happen implicitly out-of-order. + preloaded_modules_.clear(); + + DCHECK(live_modules_.empty()); +} + +PepperPluginRegistry::PepperPluginRegistry() { + ComputeList(&plugin_list_); + + // Note that in each case, AddLiveModule must be called before completing + // initialization. If we bail out (in the continue clauses) before saving + // the initialized module, it will still try to unregister itself in its + // destructor. + for (size_t i = 0; i < plugin_list_.size(); i++) { + const PepperPluginInfo& current = plugin_list_[i]; + if (current.is_out_of_process) + continue; // Out of process plugins need no special pre-initialization. + + scoped_refptr<webkit::ppapi::PluginModule> module = + new webkit::ppapi::PluginModule(current.name, current.path, this); + AddLiveModule(current.path, module); + if (current.is_internal) { + if (!module->InitAsInternalPlugin(current.internal_entry_points)) { + DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); + continue; + } + } else { + // Preload all external plugins we're not running out of process. + if (!module->InitAsLibrary(current.path)) { + DLOG(ERROR) << "Failed to load pepper module: " << current.path.value(); + continue; + } + } + preloaded_modules_[current.path] = module; + } +} + +MessageLoop* PepperPluginRegistry::GetIPCMessageLoop() { + // This is called only in the renderer so we know we have a child process. + DCHECK(ChildProcess::current()) << "Must be in the renderer."; + return ChildProcess::current()->io_message_loop(); +} + +base::WaitableEvent* PepperPluginRegistry::GetShutdownEvent() { + DCHECK(ChildProcess::current()) << "Must be in the renderer."; + return ChildProcess::current()->GetShutDownEvent(); +} + +std::set<PP_Instance>* PepperPluginRegistry::GetGloballySeenInstanceIDSet() { + // This function is not needed on the host side of the proxy. + return NULL; +} diff --git a/content/common/pepper_plugin_registry.h b/content/common/pepper_plugin_registry.h new file mode 100644 index 0000000..22de281 --- /dev/null +++ b/content/common/pepper_plugin_registry.h @@ -0,0 +1,125 @@ +// Copyright (c) 2011 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. + +#ifndef CONTENT_COMMON_PEPPER_PLUGIN_REGISTRY_H_ +#define CONTENT_COMMON_PEPPER_PLUGIN_REGISTRY_H_ +#pragma once + +#include <list> +#include <map> +#include <string> +#include <vector> + +#include "base/file_path.h" +#include "ppapi/proxy/dispatcher.h" +#include "webkit/plugins/npapi/webplugininfo.h" +#include "webkit/plugins/ppapi/plugin_delegate.h" +#include "webkit/plugins/ppapi/plugin_module.h" + +struct PepperPluginInfo { + PepperPluginInfo(); + ~PepperPluginInfo(); + + webkit::npapi::WebPluginInfo ToWebPluginInfo() const; + + // Indicates internal plugins for which there's not actually a library. + // These plugins are implemented in the Chrome binary using a separate set + // of entry points (see internal_entry_points below). + // Defaults to false. + bool is_internal; + + // True when this plugin should be run out of process. Defaults to false. + bool is_out_of_process; + + // Whether the plugin is enabled. Defaults to true. + bool enabled; + + FilePath path; // Internal plugins have "internal-[name]" as path. + std::string name; + std::string description; + std::string version; + std::vector<webkit::npapi::WebPluginMimeType> mime_types; + + // When is_internal is set, this contains the function pointers to the + // entry points for the internal plugins. + webkit::ppapi::PluginModule::EntryPoints internal_entry_points; +}; + +// This class holds references to all of the known pepper plugin modules. +// +// It keeps two lists. One list of preloaded in-process modules, and one list +// is a list of all live modules (some of which may be out-of-process and hence +// not preloaded). +class PepperPluginRegistry + : public webkit::ppapi::PluginDelegate::ModuleLifetime, + public pp::proxy::Dispatcher::Delegate { + public: + ~PepperPluginRegistry(); + + static PepperPluginRegistry* GetInstance(); + + // Computes the list of known pepper plugins. + // + // This method is static so that it can be used by the browser process, which + // has no need to load the pepper plugin modules. It will re-compute the + // plugin list every time it is called. Generally, code in the registry should + // be using the cached plugin_list_ instead. + static void ComputeList(std::vector<PepperPluginInfo>* plugins); + + // Loads the (native) libraries but does not initialize them (i.e., does not + // call PPP_InitializeModule). This is needed by the zygote on Linux to get + // access to the plugins before entering the sandbox. + static void PreloadModules(); + + // Retrieves the information associated with the given plugin path. The + // return value will be NULL if there is no such plugin. + // + // The returned pointer is owned by the PluginRegistry. + const PepperPluginInfo* GetInfoForPlugin(const FilePath& path) const; + + // Returns an existing loaded module for the given path. It will search for + // both preloaded in-process or currently active (non crashed) out-of-process + // plugins matching the given name. Returns NULL if the plugin hasn't been + // loaded. + webkit::ppapi::PluginModule* GetLiveModule(const FilePath& path); + + // Notifies the registry that a new non-preloaded module has been created. + // This is normally called for out-of-process plugins. Once this is called, + // the module is available to be returned by GetModule(). The module will + // automatically unregister itself by calling PluginModuleDestroyed(). + void AddLiveModule(const FilePath& path, webkit::ppapi::PluginModule* module); + + // ModuleLifetime implementation. + virtual void PluginModuleDead(webkit::ppapi::PluginModule* dead_module); + + private: + PepperPluginRegistry(); + + // Dispatcher::Delegate implementation. + virtual MessageLoop* GetIPCMessageLoop(); + virtual base::WaitableEvent* GetShutdownEvent(); + virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet(); + + // All known pepper plugins. + std::vector<PepperPluginInfo> plugin_list_; + + // Plugins that have been preloaded so they can be executed in-process in + // the renderer (the sandbox prevents on-demand loading). + typedef std::map<FilePath, scoped_refptr<webkit::ppapi::PluginModule> > + OwningModuleMap; + OwningModuleMap preloaded_modules_; + + // A list of non-owning pointers to all currently-live plugin modules. This + // includes both preloaded ones in preloaded_modules_, and out-of-process + // modules whose lifetime is managed externally. This will contain only + // non-crashed modules. If an out-of-process module crashes, it may + // continue as long as there are WebKit references to it, but it will not + // appear in this list. + typedef std::map<FilePath, webkit::ppapi::PluginModule*> NonOwningModuleMap; + NonOwningModuleMap live_modules_; + + DISALLOW_COPY_AND_ASSIGN(PepperPluginRegistry); +}; + +#endif // CONTENT_COMMON_PEPPER_PLUGIN_REGISTRY_H_ diff --git a/content/content_common.gypi b/content/content_common.gypi index 7a4c001..6a427c6 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi @@ -159,6 +159,8 @@ 'common/pepper_file_messages.h', 'common/pepper_messages.cc', 'common/pepper_messages.h', + 'common/pepper_plugin_registry.cc', + 'common/pepper_plugin_registry.h', 'common/plugin_carbon_interpose_constants_mac.cc', 'common/plugin_carbon_interpose_constants_mac.h', 'common/plugin_messages.h', diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc index f17a21f6..840c36e 100644 --- a/content/renderer/pepper_plugin_delegate_impl.cc +++ b/content/renderer/pepper_plugin_delegate_impl.cc @@ -15,13 +15,13 @@ #include "base/sync_socket.h" #include "base/task.h" #include "base/time.h" -#include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/render_messages.h" #include "content/common/audio_messages.h" #include "content/common/child_process_messages.h" #include "content/common/child_thread.h" #include "content/common/file_system/file_system_dispatcher.h" #include "content/common/pepper_file_messages.h" +#include "content/common/pepper_plugin_registry.h" #include "content/common/pepper_messages.h" #include "content/common/view_messages.h" #include "content/renderer/audio_message_filter.h" diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index a8c30e5..ec7bb75 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -21,7 +21,6 @@ #include "base/sys_string_conversions.h" #include "base/time.h" #include "base/utf_string_conversions.h" -#include "chrome/common/pepper_plugin_registry.h" #include "chrome/common/render_messages.h" #include "content/common/appcache/appcache_dispatcher.h" #include "content/common/bindings_policy.h" @@ -35,6 +34,7 @@ #include "content/common/json_value_serializer.h" #include "content/common/notification_service.h" #include "content/common/pepper_messages.h" +#include "content/common/pepper_plugin_registry.h" #include "content/common/quota_dispatcher.h" #include "content/common/renderer_preferences.h" #include "content/common/url_constants.h" |