diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-14 16:52:58 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-14 16:52:58 +0000 |
commit | 184808f27fbc5cf8dc4a9c637d644bda31c6cfe8 (patch) | |
tree | 0db99fde76ca2142910775f750596e458c5353fc /content | |
parent | 254004a393625cbcf09254e1ce127319f8a3addd (diff) | |
download | chromium_src-184808f27fbc5cf8dc4a9c637d644bda31c6cfe8.zip chromium_src-184808f27fbc5cf8dc4a9c637d644bda31c6cfe8.tar.gz chromium_src-184808f27fbc5cf8dc4a9c637d644bda31c6cfe8.tar.bz2 |
Move ppapi_plugin to content.
TBR=brettw
Review URL: http://codereview.chromium.org/6679041
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78042 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/content.gyp | 1 | ||||
-rw-r--r-- | content/content_ppapi_plugin.gypi | 28 | ||||
-rw-r--r-- | content/ppapi_plugin/DEPS | 4 | ||||
-rw-r--r-- | content/ppapi_plugin/plugin_process_dispatcher.cc | 38 | ||||
-rw-r--r-- | content/ppapi_plugin/plugin_process_dispatcher.h | 24 | ||||
-rw-r--r-- | content/ppapi_plugin/ppapi_plugin_main.cc | 28 | ||||
-rw-r--r-- | content/ppapi_plugin/ppapi_process.cc | 11 | ||||
-rw-r--r-- | content/ppapi_plugin/ppapi_process.h | 20 | ||||
-rw-r--r-- | content/ppapi_plugin/ppapi_thread.cc | 129 | ||||
-rw-r--r-- | content/ppapi_plugin/ppapi_thread.h | 74 |
10 files changed, 357 insertions, 0 deletions
diff --git a/content/content.gyp b/content/content.gyp index cc3fe6a..62c12eb 100644 --- a/content/content.gyp +++ b/content/content.gyp @@ -10,6 +10,7 @@ 'content_browser.gypi', 'content_common.gypi', 'content_gpu.gypi', + 'content_ppapi_plugin.gypi', 'content_worker.gypi', ], } diff --git a/content/content_ppapi_plugin.gypi b/content/content_ppapi_plugin.gypi new file mode 100644 index 0000000..d504fd5 --- /dev/null +++ b/content/content_ppapi_plugin.gypi @@ -0,0 +1,28 @@ +# 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. + +{ + 'targets': [ + { + 'target_name': 'content_ppapi_plugin', + 'type': '<(library)', + 'dependencies': [ + '../base/base.gyp:base', + '../ppapi/ppapi.gyp:ppapi_proxy', + ], + 'sources': [ + 'ppapi_plugin/plugin_process_dispatcher.cc', + 'ppapi_plugin/plugin_process_dispatcher.h', + 'ppapi_plugin/ppapi_plugin_main.cc', + 'ppapi_plugin/ppapi_process.cc', + 'ppapi_plugin/ppapi_process.h', + 'ppapi_plugin/ppapi_thread.cc', + 'ppapi_plugin/ppapi_thread.h', + ], + 'include_dirs': [ + '..', + ], + }, + ], +} diff --git a/content/ppapi_plugin/DEPS b/content/ppapi_plugin/DEPS new file mode 100644 index 0000000..ba39a68 --- /dev/null +++ b/content/ppapi_plugin/DEPS @@ -0,0 +1,4 @@ +include_rules = [ + "+ppapi/c", + "+ppapi/proxy", +] diff --git a/content/ppapi_plugin/plugin_process_dispatcher.cc b/content/ppapi_plugin/plugin_process_dispatcher.cc new file mode 100644 index 0000000..08528e7 --- /dev/null +++ b/content/ppapi_plugin/plugin_process_dispatcher.cc @@ -0,0 +1,38 @@ +// 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/ppapi_plugin/plugin_process_dispatcher.h" + +#include "content/common/child_process.h" + +namespace { + +class PluginReleaseTask : public Task { + public: + void Run() { + ChildProcess::current()->ReleaseProcess(); + } +}; + +// How long we wait before releasing the plugin process. +const int kPluginReleaseTimeMs = 30 * 1000; // 30 seconds. + +} // namespace + +PluginProcessDispatcher::PluginProcessDispatcher( + base::ProcessHandle remote_process_handle, + GetInterfaceFunc get_interface) + : pp::proxy::PluginDispatcher(remote_process_handle, get_interface) { + ChildProcess::current()->AddRefProcess(); +} + +PluginProcessDispatcher::~PluginProcessDispatcher() { + // Don't free the process right away. This timer allows the child process + // to be re-used if the user rapidly goes to a new page that requires this + // plugin. This is the case for common plugins where they may be used on a + // source and destination page of a navigation. We don't want to tear down + // and re-start processes each time in these cases. + MessageLoop::current()->PostDelayedTask(FROM_HERE, new PluginReleaseTask(), + kPluginReleaseTimeMs); +} diff --git a/content/ppapi_plugin/plugin_process_dispatcher.h b/content/ppapi_plugin/plugin_process_dispatcher.h new file mode 100644 index 0000000..309fe1a --- /dev/null +++ b/content/ppapi_plugin/plugin_process_dispatcher.h @@ -0,0 +1,24 @@ +// 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_PPAPI_PLUGIN_PLUGIN_PROCESS_DISPATCHER_H_ +#define CONTENT_PPAPI_PLUGIN_PLUGIN_PROCESS_DISPATCHER_H_ + +#include "base/basictypes.h" +#include "ppapi/proxy/plugin_dispatcher.h" + +// Wrapper around a PluginDispatcher that provides the necessary integration +// for plugin process management. This class is to avoid direct dependencies +// from the PPAPI proxy on the Chrome multiprocess infrastructure. +class PluginProcessDispatcher : public pp::proxy::PluginDispatcher { + public: + PluginProcessDispatcher(base::ProcessHandle remote_process_handle, + GetInterfaceFunc get_interface); + virtual ~PluginProcessDispatcher(); + + private: + DISALLOW_COPY_AND_ASSIGN(PluginProcessDispatcher); +}; + +#endif // CONTENT_PPAPI_PLUGIN_PLUGIN_PROCESS_DISPATCHER_H_ diff --git a/content/ppapi_plugin/ppapi_plugin_main.cc b/content/ppapi_plugin/ppapi_plugin_main.cc new file mode 100644 index 0000000..e18051a --- /dev/null +++ b/content/ppapi_plugin/ppapi_plugin_main.cc @@ -0,0 +1,28 @@ +// 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 "base/message_loop.h" +#include "base/threading/platform_thread.h" +#include "build/build_config.h" +#include "chrome/common/chrome_switches.h" +#include "content/common/child_process.h" +#include "content/common/main_function_params.h" +#include "content/ppapi_plugin/ppapi_thread.h" + +// Main function for starting the PPAPI plugin process. +int PpapiPluginMain(const MainFunctionParams& parameters) { + const CommandLine& command_line = parameters.command_line_; + if (command_line.HasSwitch(switches::kPpapiStartupDialog)) { + ChildProcess::WaitForDebugger("Ppapi"); + } + + MessageLoop main_message_loop(MessageLoop::TYPE_UI); + base::PlatformThread::SetName("CrPPAPIMain"); + + ChildProcess ppapi_process; + ppapi_process.set_main_thread(new PpapiThread()); + + main_message_loop.Run(); + return 0; +} diff --git a/content/ppapi_plugin/ppapi_process.cc b/content/ppapi_plugin/ppapi_process.cc new file mode 100644 index 0000000..fdf1a19 --- /dev/null +++ b/content/ppapi_plugin/ppapi_process.cc @@ -0,0 +1,11 @@ +// 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. + +#include "content/ppapi_plugin/ppapi_process.h" + +PpapiProcess::PpapiProcess() { +} + +PpapiProcess::~PpapiProcess() { +} diff --git a/content/ppapi_plugin/ppapi_process.h b/content/ppapi_plugin/ppapi_process.h new file mode 100644 index 0000000..ed0dec9 --- /dev/null +++ b/content/ppapi_plugin/ppapi_process.h @@ -0,0 +1,20 @@ +// 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_PPAPI_PLUGIN_PPAPI_PROCESS_H_ +#define CONTENT_PPAPI_PLUGIN_PPAPI_PROCESS_H_ +#pragma once + +#include "content/common/child_process.h" + +class PpapiProcess : public ChildProcess { + public: + PpapiProcess(); + ~PpapiProcess(); + + private: + DISALLOW_COPY_AND_ASSIGN(PpapiProcess); +}; + +#endif // CONTENT_PPAPI_PLUGIN_PPAPI_PROCESS_H_ diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc new file mode 100644 index 0000000..67d13a61 --- /dev/null +++ b/content/ppapi_plugin/ppapi_thread.cc @@ -0,0 +1,129 @@ +// 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/ppapi_plugin/ppapi_thread.h" + +#include <limits> + +#include "base/process_util.h" +#include "base/rand_util.h" +#include "content/common/child_process.h" +#include "content/ppapi_plugin/plugin_process_dispatcher.h" +#include "ipc/ipc_channel_handle.h" +#include "ipc/ipc_sync_channel.h" +#include "ppapi/c/pp_errors.h" +#include "ppapi/c/ppp.h" +#include "ppapi/proxy/ppapi_messages.h" + +PpapiThread::PpapiThread() + : get_plugin_interface_(NULL), + local_pp_module_( + base::RandInt(0, std::numeric_limits<PP_Module>::max())) { +} + +PpapiThread::~PpapiThread() { + if (library_.is_valid()) { + // The ShutdownModule function is optional. + pp::proxy::Dispatcher::ShutdownModuleFunc shutdown_module = + reinterpret_cast<pp::proxy::Dispatcher::ShutdownModuleFunc>( + library_.GetFunctionPointer("PPP_ShutdownModule")); + if (shutdown_module) + shutdown_module(); + } +} + +// The "regular" ChildThread implements this function and does some standard +// dispatching, then uses the message router. We don't actually need any of +// this so this function just overrides that one. +// +// Note that this function is called only for messages from the channel to the +// browser process. Messages from the renderer process are sent via a different +// channel that ends up at Dispatcher::OnMessageReceived. +bool PpapiThread::OnMessageReceived(const IPC::Message& msg) { + IPC_BEGIN_MESSAGE_MAP(PpapiThread, msg) + IPC_MESSAGE_HANDLER(PpapiMsg_LoadPlugin, OnMsgLoadPlugin) + IPC_MESSAGE_HANDLER(PpapiMsg_CreateChannel, OnMsgCreateChannel) + IPC_END_MESSAGE_MAP() + return true; +} + +MessageLoop* PpapiThread::GetIPCMessageLoop() { + return ChildProcess::current()->io_message_loop(); +} + +base::WaitableEvent* PpapiThread::GetShutdownEvent() { + return ChildProcess::current()->GetShutDownEvent(); +} + +std::set<PP_Instance>* PpapiThread::GetGloballySeenInstanceIDSet() { + return &globally_seen_instance_ids_; +} + +void PpapiThread::OnMsgLoadPlugin(const FilePath& path) { + base::ScopedNativeLibrary library(base::LoadNativeLibrary(path)); + if (!library.is_valid()) + return; + + // Get the GetInterface function (required). + get_plugin_interface_ = + reinterpret_cast<pp::proxy::Dispatcher::GetInterfaceFunc>( + library.GetFunctionPointer("PPP_GetInterface")); + if (!get_plugin_interface_) { + LOG(WARNING) << "No PPP_GetInterface in plugin library"; + return; + } + + // Get the InitializeModule function (required). + pp::proxy::Dispatcher::InitModuleFunc init_module = + reinterpret_cast<pp::proxy::Dispatcher::InitModuleFunc>( + library.GetFunctionPointer("PPP_InitializeModule")); + if (!init_module) { + LOG(WARNING) << "No PPP_InitializeModule in plugin library"; + return; + } + int32_t init_error = init_module( + local_pp_module_, + &pp::proxy::PluginDispatcher::GetInterfaceFromDispatcher); + if (init_error != PP_OK) { + LOG(WARNING) << "InitModule failed with error " << init_error; + return; + } + + library_.Reset(library.Release()); +} + +void PpapiThread::OnMsgCreateChannel(base::ProcessHandle host_process_handle, + int renderer_id) { + IPC::ChannelHandle channel_handle; + if (!library_.is_valid() || // Plugin couldn't be loaded. + !SetupRendererChannel(host_process_handle, renderer_id, + &channel_handle)) { + Send(new PpapiHostMsg_ChannelCreated(IPC::ChannelHandle())); + return; + } + + Send(new PpapiHostMsg_ChannelCreated(channel_handle)); +} + +bool PpapiThread::SetupRendererChannel(base::ProcessHandle host_process_handle, + int renderer_id, + IPC::ChannelHandle* handle) { + PluginProcessDispatcher* dispatcher = new PluginProcessDispatcher( + host_process_handle, get_plugin_interface_); + + IPC::ChannelHandle plugin_handle; + plugin_handle.name = StringPrintf("%d.r%d", base::GetCurrentProcId(), + renderer_id); + if (!dispatcher->InitWithChannel(this, plugin_handle, false)) + return false; + + handle->name = plugin_handle.name; +#if defined(OS_POSIX) + // On POSIX, pass the renderer-side FD. + handle->socket = base::FileDescriptor(dispatcher->GetRendererFD(), false); +#endif + + return true; +} + diff --git a/content/ppapi_plugin/ppapi_thread.h b/content/ppapi_plugin/ppapi_thread.h new file mode 100644 index 0000000..2ccc4be --- /dev/null +++ b/content/ppapi_plugin/ppapi_thread.h @@ -0,0 +1,74 @@ +// 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_PPAPI_PLUGIN_PPAPI_THREAD_H_ +#define CONTENT_PPAPI_PLUGIN_PPAPI_THREAD_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/process.h" +#include "base/scoped_native_library.h" +#include "base/scoped_ptr.h" +#include "build/build_config.h" +#include "content/common/child_thread.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/proxy/dispatcher.h" + +class FilePath; + +namespace IPC { +struct ChannelHandle; +} + +namespace pp { +namespace proxy { +class PluginDispatcher; +} +} + +class PpapiThread : public ChildThread, + public pp::proxy::Dispatcher::Delegate { + public: + PpapiThread(); + ~PpapiThread(); + + private: + // ChildThread overrides. + virtual bool OnMessageReceived(const IPC::Message& msg); + + // Dispatcher::Delegate implementation. + virtual MessageLoop* GetIPCMessageLoop(); + virtual base::WaitableEvent* GetShutdownEvent(); + virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet(); + + // Message handlers. + void OnMsgLoadPlugin(const FilePath& path); + void OnMsgCreateChannel(base::ProcessHandle host_process_handle, + int renderer_id); + + // Sets up the channel to the given renderer. On success, returns true and + // fills the given ChannelHandle with the information from the new channel. + bool SetupRendererChannel(base::ProcessHandle host_process_handle, + int renderer_id, + IPC::ChannelHandle* handle); + + base::ScopedNativeLibrary library_; + + pp::proxy::Dispatcher::GetInterfaceFunc get_plugin_interface_; + + // Local concept of the module ID. Some functions take this. It's necessary + // for the in-process PPAPI to handle this properly, but for proxied it's + // unnecessary. The proxy talking to multiple renderers means that each + // renderer has a different idea of what the module ID is for this plugin. + // To force people to "do the right thing" we generate a random module ID + // and pass it around as necessary. + PP_Module local_pp_module_; + + // See Dispatcher::Delegate::GetGloballySeenInstanceIDSet. + std::set<PP_Instance> globally_seen_instance_ids_; + + DISALLOW_COPY_AND_ASSIGN(PpapiThread); +}; + +#endif // CONTENT_PPAPI_PLUGIN_PPAPI_THREAD_H_ |