summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/task_manager/task_manager_resource_providers.cc3
-rw-r--r--content/browser/plugin_service.cc76
-rw-r--r--content/browser/plugin_service.h8
-rw-r--r--content/browser/ppapi_broker_process_host.cc179
-rw-r--r--content/browser/ppapi_broker_process_host.h81
-rw-r--r--content/browser/ppapi_plugin_process_host.h6
-rw-r--r--content/browser/renderer_host/render_message_filter.cc41
-rw-r--r--content/browser/renderer_host/render_message_filter.h3
-rw-r--r--content/common/child_process_info.cc2
-rw-r--r--content/common/child_process_info.h3
-rw-r--r--content/common/view_messages.h17
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/renderer/pepper_plugin_delegate_impl.cc100
-rw-r--r--content/renderer/pepper_plugin_delegate_impl.h39
-rw-r--r--content/renderer/render_view.cc7
-rw-r--r--content/renderer/render_view.h2
-rw-r--r--ppapi/proxy/ppapi_messages.h2
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.cc1
-rw-r--r--webkit/plugins/ppapi/mock_plugin_delegate.h3
-rw-r--r--webkit/plugins/ppapi/plugin_delegate.h18
-rw-r--r--webkit/plugins/ppapi/plugin_module.cc11
-rw-r--r--webkit/plugins/ppapi/plugin_module.h6
-rw-r--r--webkit/plugins/ppapi/ppb_broker_impl.cc4
-rw-r--r--webkit/plugins/ppapi/ppb_broker_impl.h2
24 files changed, 574 insertions, 42 deletions
diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc
index 19747c0..559e8d7 100644
--- a/chrome/browser/task_manager/task_manager_resource_providers.cc
+++ b/chrome/browser/task_manager/task_manager_resource_providers.cc
@@ -933,7 +933,8 @@ string16 TaskManagerChildProcessResource::GetLocalizedTitle() const {
return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX);
case ChildProcessInfo::PLUGIN_PROCESS:
- case ChildProcessInfo::PPAPI_PLUGIN_PROCESS: {
+ case ChildProcessInfo::PPAPI_PLUGIN_PROCESS:
+ case ChildProcessInfo::PPAPI_BROKER_PROCESS: {
return l10n_util::GetStringFUTF16(
IDS_TASK_MANAGER_PLUGIN_PREFIX, title,
WideToUTF16Hack(child_process_.version()));
diff --git a/content/browser/plugin_service.cc b/content/browser/plugin_service.cc
index 409bd67..1a12a36 100644
--- a/content/browser/plugin_service.cc
+++ b/content/browser/plugin_service.cc
@@ -223,6 +223,22 @@ PpapiPluginProcessHost* PluginService::FindPpapiPluginProcess(
return NULL;
}
+PpapiBrokerProcessHost* PluginService::FindPpapiBrokerProcess(
+ const FilePath& broker_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ for (BrowserChildProcessHost::Iterator iter(
+ ChildProcessInfo::PPAPI_BROKER_PROCESS);
+ !iter.Done(); ++iter) {
+ PpapiBrokerProcessHost* broker =
+ static_cast<PpapiBrokerProcessHost*>(*iter);
+ if (broker->broker_path() == broker_path)
+ return broker;
+ }
+
+ return NULL;
+}
+
PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess(
const FilePath& plugin_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -254,15 +270,8 @@ PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess(
if (plugin_host)
return plugin_host;
- // Validate that the plugin is actually registered. There should generally
- // be very few plugins so a brute-force search is fine.
- PepperPluginInfo* info = NULL;
- for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
- if (ppapi_plugins_[i].path == plugin_path) {
- info = &ppapi_plugins_[i];
- break;
- }
- }
+ // Validate that the plugin is actually registered.
+ PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
if (!info)
return NULL;
@@ -275,6 +284,32 @@ PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess(
return new_host.release();
}
+PpapiBrokerProcessHost* PluginService::FindOrStartPpapiBrokerProcess(
+ const FilePath& plugin_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PpapiBrokerProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
+ if (plugin_host)
+ return plugin_host;
+
+ // Validate that the plugin is actually registered.
+ PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
+ if (!info)
+ return NULL;
+
+ // TODO(ddorwin): Uncomment once out of process is supported.
+ // DCHECK(info->is_out_of_process);
+
+ // This broker isn't loaded by any broker process, so create a new process.
+ scoped_ptr<PpapiBrokerProcessHost> new_host(
+ new PpapiBrokerProcessHost);
+ if (!new_host->Init(*info)) {
+ NOTREACHED(); // Init is not expected to fail.
+ return NULL;
+ }
+ return new_host.release();
+}
+
void PluginService::OpenChannelToNpapiPlugin(
int render_process_id,
int render_view_id,
@@ -300,6 +335,16 @@ void PluginService::OpenChannelToPpapiPlugin(
client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
}
+void PluginService::OpenChannelToPpapiBroker(
+ const FilePath& path,
+ PpapiBrokerProcessHost::Client* client) {
+ PpapiBrokerProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
+ if (plugin_host)
+ plugin_host->OpenChannelToPpapiBroker(client);
+ else // Send error.
+ client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
+}
+
void PluginService::GetAllowedPluginForOpenChannelToPlugin(
int render_process_id,
int render_view_id,
@@ -503,6 +548,19 @@ void PluginService::RegisterPepperPlugins() {
}
}
+// There should generally be very few plugins so a brute-force search is fine.
+PepperPluginInfo* PluginService::GetRegisteredPpapiPluginInfo(
+ const FilePath& plugin_path) {
+ PepperPluginInfo* info = NULL;
+ for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
+ if (ppapi_plugins_[i].path == plugin_path) {
+ info = &ppapi_plugins_[i];
+ break;
+ }
+ }
+ return info;
+}
+
#if defined(OS_LINUX)
// static
void PluginService::RegisterFilePathWatcher(
diff --git a/content/browser/plugin_service.h b/content/browser/plugin_service.h
index 4943d42..5c37c01 100644
--- a/content/browser/plugin_service.h
+++ b/content/browser/plugin_service.h
@@ -21,6 +21,7 @@
#include "build/build_config.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/ppapi_plugin_process_host.h"
+#include "content/browser/ppapi_broker_process_host.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "googleurl/src/gurl.h"
@@ -84,6 +85,7 @@ class PluginService
// started.
PluginProcessHost* FindNpapiPluginProcess(const FilePath& plugin_path);
PpapiPluginProcessHost* FindPpapiPluginProcess(const FilePath& plugin_path);
+ PpapiBrokerProcessHost* FindPpapiBrokerProcess(const FilePath& broker_path);
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. This will start a process to host the
@@ -93,6 +95,8 @@ class PluginService
const FilePath& plugin_path);
PpapiPluginProcessHost* FindOrStartPpapiPluginProcess(
const FilePath& plugin_path);
+ PpapiBrokerProcessHost* FindOrStartPpapiBrokerProcess(
+ const FilePath& plugin_path);
// Opens a channel to a plugin process for the given mime type, starting
// a new plugin process if necessary. This must be called on the IO thread
@@ -104,6 +108,8 @@ class PluginService
PluginProcessHost::Client* client);
void OpenChannelToPpapiPlugin(const FilePath& path,
PpapiPluginProcessHost::Client* client);
+ void OpenChannelToPpapiBroker(const FilePath& path,
+ PpapiBrokerProcessHost::Client* client);
// Gets the first allowed plugin in the list of plugins that matches
// the given url and mime type. Must be called on the FILE thread.
@@ -152,6 +158,8 @@ class PluginService
void RegisterPepperPlugins();
+ PepperPluginInfo* GetRegisteredPpapiPluginInfo(const FilePath& plugin_path);
+
// Helper so we can do the plugin lookup on the FILE thread.
void GetAllowedPluginForOpenChannelToPlugin(
int render_process_id,
diff --git a/content/browser/ppapi_broker_process_host.cc b/content/browser/ppapi_broker_process_host.cc
new file mode 100644
index 0000000..78c8c9b
--- /dev/null
+++ b/content/browser/ppapi_broker_process_host.cc
@@ -0,0 +1,179 @@
+// 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/browser/ppapi_broker_process_host.h"
+
+#include "base/command_line.h"
+#include "base/file_path.h"
+#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 "ipc/ipc_switches.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+PpapiBrokerProcessHost::PpapiBrokerProcessHost()
+ : BrowserChildProcessHost(
+ ChildProcessInfo::PPAPI_BROKER_PROCESS, NULL) {
+}
+
+PpapiBrokerProcessHost::~PpapiBrokerProcessHost() {
+ CancelRequests();
+}
+
+bool PpapiBrokerProcessHost::Init(const PepperPluginInfo& info) {
+ broker_path_ = info.path;
+ set_name(UTF8ToWide(info.name));
+ set_version(UTF8ToWide(info.version));
+
+ if (!CreateChannel())
+ return false;
+
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ // Use the same launcher mechanism as ppapi plugins.
+ CommandLine::StringType plugin_launcher =
+ browser_command_line.GetSwitchValueNative(switches::kPpapiPluginLauncher);
+
+ FilePath exe_path = ChildProcessHost::GetChildPath(plugin_launcher.empty());
+ if (exe_path.empty())
+ return false;
+
+ CommandLine* cmd_line = new CommandLine(exe_path);
+ cmd_line->AppendSwitchASCII(switches::kProcessType,
+ switches::kPpapiBrokerProcess);
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+
+ if (!plugin_launcher.empty())
+ cmd_line->PrependWrapper(plugin_launcher);
+
+ // On posix, having a plugin launcher means we need to use another process
+ // instead of just forking the zygote.
+ Launch(
+#if defined(OS_WIN)
+ FilePath(),
+#elif defined(OS_POSIX)
+ false, // Never use the zygote for the broker.
+ base::environment_vector(),
+#endif
+ cmd_line);
+ return true;
+}
+
+void PpapiBrokerProcessHost::OpenChannelToPpapiBroker(Client* client) {
+ if (opening_channel()) {
+ // The channel is already in the process of being opened. Put
+ // this "open channel" request into a queue of requests that will
+ // be run once the channel is open.
+ pending_requests_.push_back(client);
+ return;
+ }
+
+ // We already have an open channel, send a request right away to broker.
+ RequestPpapiBrokerChannel(client);
+}
+
+void PpapiBrokerProcessHost::RequestPpapiBrokerChannel(
+ Client* client) {
+ base::ProcessHandle process_handle;
+ int renderer_id;
+ client->GetChannelInfo(&process_handle, &renderer_id);
+
+ // We can't send any sync messages from the browser because it might lead to
+ // a hang. See the similar code in PluginProcessHost for more description.
+ PpapiMsg_CreateChannel* msg = new PpapiMsg_CreateChannel(process_handle,
+ renderer_id);
+ msg->set_unblock(true);
+ if (Send(msg))
+ sent_requests_.push(client);
+ else
+ client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
+}
+
+bool PpapiBrokerProcessHost::CanShutdown() {
+ return true;
+}
+
+void PpapiBrokerProcessHost::OnProcessLaunched() {
+}
+
+bool PpapiBrokerProcessHost::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PpapiBrokerProcessHost, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated,
+ OnRendererPpapiBrokerChannelCreated)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ DCHECK(handled);
+ return handled;
+}
+
+// Called when the browser <--> ppapi broker channel has been established.
+void PpapiBrokerProcessHost::OnChannelConnected(int32 peer_pid) {
+ // This will actually load the ppapi broker. Errors will actually not be
+ // reported back at this point. Instead, the broker will fail to establish the
+ // connections when we request them on behalf of the renderer(s).
+ Send(new PpapiMsg_LoadPlugin(broker_path_));
+
+ // Process all pending channel requests from the renderers.
+ for (size_t i = 0; i < pending_requests_.size(); i++)
+ RequestPpapiBrokerChannel(pending_requests_[i]);
+ pending_requests_.clear();
+}
+
+// Called when the browser <--> broker channel has an error. This normally
+// means the broker has crashed.
+void PpapiBrokerProcessHost::OnChannelError() {
+ // We don't need to notify the renderers that were communicating with the
+ // broker since they have their own channels which will go into the error
+ // state at the same time. Instead, we just need to notify any renderers
+ // that have requested a connection but have not yet received one.
+ CancelRequests();
+}
+
+void PpapiBrokerProcessHost::CancelRequests() {
+ for (size_t i = 0; i < pending_requests_.size(); i++) {
+ pending_requests_[i]->OnChannelOpened(base::kNullProcessHandle,
+ IPC::ChannelHandle());
+ }
+ pending_requests_.clear();
+
+ while (!sent_requests_.empty()) {
+ sent_requests_.front()->OnChannelOpened(base::kNullProcessHandle,
+ IPC::ChannelHandle());
+ sent_requests_.pop();
+ }
+}
+
+// Called when a new broker <--> renderer channel has been created.
+void PpapiBrokerProcessHost::OnRendererPpapiBrokerChannelCreated(
+ const IPC::ChannelHandle& channel_handle) {
+ if (sent_requests_.empty())
+ return;
+
+ // All requests should be processed FIFO, so the next item in the
+ // sent_requests_ queue should be the one that the plugin just created.
+ Client* client = sent_requests_.front();
+ sent_requests_.pop();
+
+ // Prepare the handle to send to the renderer.
+ base::ProcessHandle broker_process = GetChildProcessHandle();
+#if defined(OS_WIN)
+ base::ProcessHandle renderer_process;
+ int renderer_id;
+ client->GetChannelInfo(&renderer_process, &renderer_id);
+
+ base::ProcessHandle renderers_broker_handle = NULL;
+ ::DuplicateHandle(::GetCurrentProcess(), broker_process,
+ renderer_process, &renderers_broker_handle,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+#elif defined(OS_POSIX)
+ // Don't need to duplicate anything on POSIX since it's just a PID.
+ base::ProcessHandle renderers_broker_handle = broker_process;
+#endif
+
+ client->OnChannelOpened(renderers_broker_handle, channel_handle);
+}
diff --git a/content/browser/ppapi_broker_process_host.h b/content/browser/ppapi_broker_process_host.h
new file mode 100644
index 0000000..38a0314
--- /dev/null
+++ b/content/browser/ppapi_broker_process_host.h
@@ -0,0 +1,81 @@
+// 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_BROWSER_PPAPI_BROKER_PROCESS_HOST_H_
+#define CONTENT_BROWSER_PPAPI_BROKER_PROCESS_HOST_H_
+#pragma once
+
+#include <queue>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "content/browser/browser_child_process_host.h"
+
+struct PepperPluginInfo;
+
+// TODO(ddorwin): Consider merging this with PpapiPluginProcessHost after
+// finishing broker implementation.
+class PpapiBrokerProcessHost : public BrowserChildProcessHost {
+ public:
+ class Client {
+ public:
+ // Gets the information about the renderer that's requesting the channel.
+ virtual void GetChannelInfo(base::ProcessHandle* renderer_handle,
+ int* renderer_id) = 0;
+
+ // Called when the channel is asynchronously opened to the broker or on
+ // error. On error, the parameters should be:
+ // base::kNullProcessHandle
+ // IPC::ChannelHandle()
+ virtual void OnChannelOpened(base::ProcessHandle broker_process_handle,
+ const IPC::ChannelHandle& channel_handle) = 0;
+ };
+
+ // You must call Init before doing anything else.
+ PpapiBrokerProcessHost();
+ virtual ~PpapiBrokerProcessHost();
+
+ // Actually launches the process with the given plugin info. Returns true
+ // on success (the process was spawned).
+ bool Init(const PepperPluginInfo& info);
+
+ // Opens a new channel to the plugin. The client will be notified when the
+ // channel is ready or if there's an error.
+ void OpenChannelToPpapiBroker(Client* client);
+
+ const FilePath& broker_path() const { return broker_path_; }
+
+ // The client pointer must remain valid until its callback is issued.
+
+ private:
+
+ void RequestPpapiBrokerChannel(Client* client);
+
+ virtual bool CanShutdown();
+ virtual void OnProcessLaunched();
+
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+
+ void CancelRequests();
+
+ // IPC message handlers.
+ void OnRendererPpapiBrokerChannelCreated(const IPC::ChannelHandle& handle);
+
+ // Channel requests that we are waiting to send to the plugin process once
+ // the channel is opened.
+ std::vector<Client*> pending_requests_;
+
+ // Channel requests that we have already sent to the plugin process, but
+ // haven't heard back about yet.
+ std::queue<Client*> sent_requests_;
+
+ // Path to the plugin library.
+ FilePath broker_path_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpapiBrokerProcessHost);
+};
+
+#endif // CONTENT_BROWSER_PPAPI_BROKER_PROCESS_HOST_H_
diff --git a/content/browser/ppapi_plugin_process_host.h b/content/browser/ppapi_plugin_process_host.h
index aa6bc47..0412c25 100644
--- a/content/browser/ppapi_plugin_process_host.h
+++ b/content/browser/ppapi_plugin_process_host.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -30,8 +30,8 @@ class PpapiPluginProcessHost : public BrowserChildProcessHost {
const IPC::ChannelHandle& channel_handle) = 0;
};
- // You must call init before doing anything else.
- explicit PpapiPluginProcessHost();
+ // You must call Init before doing anything else.
+ PpapiPluginProcessHost();
virtual ~PpapiPluginProcessHost();
// Actually launches the process with the given plugin info. Returns true
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 42a6e2e..699e266 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -34,6 +34,7 @@
#include "content/browser/plugin_process_host.h"
#include "content/browser/plugin_service.h"
#include "content/browser/ppapi_plugin_process_host.h"
+#include "content/browser/ppapi_broker_process_host.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_notification_task.h"
#include "content/browser/renderer_host/render_widget_helper.h"
@@ -182,6 +183,37 @@ class OpenChannelToPpapiPluginCallback : public RenderMessageCompletionCallback,
}
};
+class OpenChannelToPpapiBrokerCallback : public PpapiBrokerProcessHost::Client {
+ public:
+ OpenChannelToPpapiBrokerCallback(RenderMessageFilter* filter,
+ int routing_id,
+ int request_id)
+ : filter_(filter),
+ routing_id_(routing_id),
+ request_id_(request_id) {
+ }
+
+ virtual void GetChannelInfo(base::ProcessHandle* renderer_handle,
+ int* renderer_id) {
+ *renderer_handle = filter_->peer_handle();
+ *renderer_id = filter_->render_process_id();
+ }
+
+ virtual void OnChannelOpened(base::ProcessHandle plugin_process_handle,
+ const IPC::ChannelHandle& channel_handle) {
+ filter_->Send(
+ new ViewMsg_PpapiBrokerChannelCreated(routing_id_,
+ request_id_,
+ channel_handle));
+ delete this;
+ }
+
+ private:
+ scoped_refptr<RenderMessageFilter> filter_;
+ int routing_id_;
+ int request_id_;
+};
+
// Class to assist with clearing out the cache when we want to preserve
// the sslhostinfo entries. It's not very efficient, but its just for debug.
class DoomEntriesHelper {
@@ -323,6 +355,8 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message,
OnOpenChannelToPlugin)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin,
OnOpenChannelToPepperPlugin)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_OpenChannelToPpapiBroker,
+ OnOpenChannelToPpapiBroker)
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
render_widget_helper_->DidReceiveUpdateMsg(message))
IPC_MESSAGE_HANDLER(DesktopNotificationHostMsg_CheckPermission,
@@ -605,6 +639,13 @@ void RenderMessageFilter::OnOpenChannelToPepperPlugin(
path, new OpenChannelToPpapiPluginCallback(this, reply_msg));
}
+void RenderMessageFilter::OnOpenChannelToPpapiBroker(int routing_id,
+ int request_id,
+ const FilePath& path) {
+ plugin_service_->OpenChannelToPpapiBroker(
+ path, new OpenChannelToPpapiBrokerCallback(this, routing_id, request_id));
+}
+
void RenderMessageFilter::OnGenerateRoutingID(int* route_id) {
*route_id = render_widget_helper_->GetNextRoutingID();
}
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 2e9181b..266316d 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -157,6 +157,9 @@ class RenderMessageFilter : public BrowserMessageFilter {
IPC::Message* reply_msg);
void OnOpenChannelToPepperPlugin(const FilePath& path,
IPC::Message* reply_msg);
+ void OnOpenChannelToPpapiBroker(int routing_id,
+ int request_id,
+ const FilePath& path);
void OnGenerateRoutingID(int* route_id);
void OnDownloadUrl(const IPC::Message& message,
const GURL& url,
diff --git a/content/common/child_process_info.cc b/content/common/child_process_info.cc
index 4775d7b..5ffe92c 100644
--- a/content/common/child_process_info.cc
+++ b/content/common/child_process_info.cc
@@ -76,6 +76,8 @@ std::string ChildProcessInfo::GetTypeNameInEnglish(
return "GPU";
case PPAPI_PLUGIN_PROCESS:
return "Pepper Plugin";
+ case PPAPI_BROKER_PROCESS:
+ return "Pepper Broker";
case UNKNOWN_PROCESS:
default:
DCHECK(false) << "Unknown child process type!";
diff --git a/content/common/child_process_info.h b/content/common/child_process_info.h
index e36ee52..4b709bd 100644
--- a/content/common/child_process_info.h
+++ b/content/common/child_process_info.h
@@ -29,7 +29,8 @@ class ChildProcessInfo {
SANDBOX_HELPER_PROCESS,
NACL_BROKER_PROCESS,
GPU_PROCESS,
- PPAPI_PLUGIN_PROCESS
+ PPAPI_PLUGIN_PROCESS,
+ PPAPI_BROKER_PROCESS
};
// NOTE: Do not remove or reorder the elements in this enum, and only add new
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 54435bc..06f3362 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -1146,6 +1146,11 @@ IPC_MESSAGE_ROUTED1(ViewMsg_AccessibilityDoDefaultAction,
// message was processed and it can send addition notifications.
IPC_MESSAGE_ROUTED0(ViewMsg_AccessibilityNotifications_ACK)
+// Reply to ViewHostMsg_OpenChannelToPpapiBroker
+// Tells the renderer that the channel to the broker has been created.
+IPC_MESSAGE_ROUTED2(ViewMsg_PpapiBrokerChannelCreated,
+ int /* request_id */,
+ IPC::ChannelHandle /* handle */)
// Messages sent from the renderer to the browser.
@@ -1582,7 +1587,7 @@ IPC_MESSAGE_ROUTED3(ViewHostMsg_WebUISend,
std::string /* args (as a JSON string) */)
// A renderer sends this to the browser process when it wants to
-// create a pepper plugin. The browser will create the plugin process if
+// create a ppapi plugin. The browser will create the plugin process if
// necessary, and will return a handle to the channel on success.
// On error an empty string is returned.
IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_OpenChannelToPepperPlugin,
@@ -1590,6 +1595,16 @@ IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_OpenChannelToPepperPlugin,
base::ProcessHandle /* plugin_process_handle */,
IPC::ChannelHandle /* handle to channel */)
+// A renderer sends this to the browser process when it wants to
+// create a ppapi broker. The browser will create the broker process
+// if necessary, and will return a handle to the channel on success.
+// On error an empty string is returned.
+// The browser will respond with ViewMsg_PpapiBrokerChannelCreated.
+IPC_MESSAGE_CONTROL3(ViewHostMsg_OpenChannelToPpapiBroker,
+ int /* routing_id */,
+ int /* request_id */,
+ FilePath /* path */)
+
#if defined(USE_X11)
// A renderer sends this when it needs a browser-side widget for
// hosting a windowed plugin. id is the XID of the plugin window, for which
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 923362c..7cfa306 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -164,6 +164,8 @@
'browser/mime_registry_message_filter.h',
'browser/ppapi_plugin_process_host.cc',
'browser/ppapi_plugin_process_host.h',
+ 'browser/ppapi_broker_process_host.cc',
+ 'browser/ppapi_broker_process_host.h',
'browser/plugin_process_host.cc',
'browser/plugin_process_host.h',
'browser/plugin_process_host_mac.cc',
diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc
index 5a62f25..8ba9f4f 100644
--- a/content/renderer/pepper_plugin_delegate_impl.cc
+++ b/content/renderer/pepper_plugin_delegate_impl.cc
@@ -35,7 +35,6 @@
#include "content/renderer/render_widget_fullscreen_pepper.h"
#include "content/renderer/webgraphicscontext3d_command_buffer_impl.h"
#include "content/renderer/webplugin_delegate_proxy.h"
-#include "ipc/ipc_channel_handle.h"
#include "ppapi/c/dev/pp_video_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_flash.h"
@@ -330,6 +329,45 @@ bool DispatcherWrapper::Init(
} // namespace
+PpapiBrokerImpl::PpapiBrokerImpl() {
+}
+
+// If the channel is not ready, queue the connection.
+void PpapiBrokerImpl::Connect(webkit::ppapi::PPB_Broker_Impl* client) {
+ if (channel_handle_.name.empty()) {
+ pending_connects_.push_back(client);
+ return;
+ }
+ DCHECK(pending_connects_.empty());
+
+ RequestPpapiBrokerPipe(client);
+}
+
+void PpapiBrokerImpl::Disconnect(webkit::ppapi::PPB_Broker_Impl* client) {
+ // TODO(ddorwin): Send message using channel_handle_ and clean up any pending
+ // connects or pipes.
+}
+
+void PpapiBrokerImpl::OnBrokerChannelConnected(
+ const IPC::ChannelHandle& channel_handle) {
+ channel_handle_ = channel_handle;
+
+ // Process all pending channel requests from the renderers.
+ for (size_t i = 0; i < pending_connects_.size(); i++)
+ RequestPpapiBrokerPipe(pending_connects_[i]);
+ pending_connects_.clear();
+}
+
+void PpapiBrokerImpl::RequestPpapiBrokerPipe(
+ webkit::ppapi::PPB_Broker_Impl* client) {
+ // TOOD(ddorwin): Send an asynchronous message to the broker using
+ // channel_handle_, queue the client with an ID, then return.
+ // The broker will create the pipe, which will be provided in a message.
+ // That message handler will call then client->BrokerConnected().
+ // Temporarily, just call back.
+ client->BrokerConnected(1);
+}
+
PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderView* render_view)
: render_view_(render_view),
has_saved_context_menu_action_(false),
@@ -391,6 +429,45 @@ PepperPluginDelegateImpl::CreatePepperPlugin(
return module;
}
+scoped_refptr<webkit::ppapi::PluginDelegate::PpapiBroker>
+PepperPluginDelegateImpl::CreatePpapiBroker(
+ webkit::ppapi::PluginModule* plugin_module) {
+ DCHECK(plugin_module);
+ DCHECK(!plugin_module->GetBroker());
+
+ // The broker path is the same as the plugin.
+ const FilePath& broker_path = plugin_module->path();
+
+ scoped_refptr<PpapiBrokerImpl> broker = new PpapiBrokerImpl;
+ plugin_module->SetBroker(broker);
+
+ int request_id =
+ pending_connect_broker_.Add(new scoped_refptr<PpapiBrokerImpl>(broker));
+
+ // Have the browser start the broker process for us.
+ IPC::ChannelHandle channel_handle;
+ IPC::Message* msg =
+ new ViewHostMsg_OpenChannelToPpapiBroker(render_view_->routing_id(),
+ request_id,
+ broker_path);
+ if (!render_view_->Send(msg)) {
+ pending_connect_broker_.Remove(request_id);
+ return scoped_refptr<webkit::ppapi::PluginDelegate::PpapiBroker>();
+ }
+
+ return broker;
+}
+
+void PepperPluginDelegateImpl::OnPpapiBrokerChannelCreated(
+ int request_id,
+ const IPC::ChannelHandle& handle) {
+ scoped_refptr<PpapiBrokerImpl> broker =
+ *pending_connect_broker_.Lookup(request_id);
+ pending_connect_broker_.Remove(request_id);
+
+ broker->OnBrokerChannelConnected(handle);
+}
+
void PepperPluginDelegateImpl::ViewInitiatedPaint() {
// Notify all of our instances that we started painting. This is used for
// internal bookkeeping only, so we know that the set can not change under
@@ -560,22 +637,23 @@ PepperPluginDelegateImpl::CreateAudio(
}
}
+// If a broker has not already been created for this plugin, creates one.
webkit::ppapi::PluginDelegate::PpapiBroker*
PepperPluginDelegateImpl::ConnectToPpapiBroker(
- webkit::ppapi::PluginInstance* instance,
webkit::ppapi::PPB_Broker_Impl* client) {
- CHECK(instance);
CHECK(client);
- // TODO(ddorwin): Add IPC to broker process to do the following.
- // 1) Check if there is an existing broker for instance->module().
- // 2) If not, create.
- // 3) broker->Connect(client).
- // * Asynchronously launches broker if necessary, establishes pipe, and
- // calls BrokerConnected.
- // 4) Return pointer to broker.
+ webkit::ppapi::PluginModule* plugin_module = client->instance()->module();
+ scoped_refptr<webkit::ppapi::PluginDelegate::PpapiBroker> broker =
+ plugin_module->GetBroker();
+ if (!broker) {
+ broker = CreatePpapiBroker(plugin_module);
+ if (!broker)
+ return NULL;
+ }
- return NULL;
+ broker->Connect(client);
+ return broker;
}
bool PepperPluginDelegateImpl::RunFileChooser(
diff --git a/content/renderer/pepper_plugin_delegate_impl.h b/content/renderer/pepper_plugin_delegate_impl.h
index 4186b96..b2ee87e 100644
--- a/content/renderer/pepper_plugin_delegate_impl.h
+++ b/content/renderer/pepper_plugin_delegate_impl.h
@@ -8,12 +8,15 @@
#include <set>
#include <string>
+#include <vector>
#include "base/basictypes.h"
#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "ipc/ipc_channel_handle.h"
#include "webkit/plugins/ppapi/plugin_delegate.h"
+#include "webkit/plugins/ppapi/ppb_broker_impl.h"
#include "webkit/plugins/ppapi/ppb_flash_menu_impl.h"
class FilePath;
@@ -43,6 +46,30 @@ struct CustomContextMenuContext;
class TransportDIB;
+class PpapiBrokerImpl : public webkit::ppapi::PluginDelegate::PpapiBroker {
+ public:
+ PpapiBrokerImpl();
+
+ // PpapiBroker implementation.
+ virtual void Connect(webkit::ppapi::PPB_Broker_Impl* client);
+ virtual void Disconnect(webkit::ppapi::PPB_Broker_Impl* client);
+
+ // Called when the channel to the broker has been established.
+ void OnBrokerChannelConnected(const IPC::ChannelHandle& channel_handle);
+
+ // Asynchronously requests a pipe for this instance from the broker.
+ void RequestPpapiBrokerPipe(webkit::ppapi::PPB_Broker_Impl* client);
+
+ protected:
+ IPC::ChannelHandle channel_handle_;
+
+ std::vector<scoped_refptr<webkit::ppapi::PPB_Broker_Impl> > pending_connects_;
+ std::vector<scoped_refptr<webkit::ppapi::PPB_Broker_Impl> > pending_pipes_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpapiBrokerImpl);
+};
+
+
class PepperPluginDelegateImpl
: public webkit::ppapi::PluginDelegate,
public base::SupportsWeakPtr<PepperPluginDelegateImpl> {
@@ -81,6 +108,10 @@ class PepperPluginDelegateImpl
base::PlatformFile file,
int message_id);
+ // Called by RenderView when ViewMsg_PpapiBrokerChannelCreated.
+ void OnPpapiBrokerChannelCreated(int request_id,
+ const IPC::ChannelHandle& handle);
+
// Notification that the render view has been focused or defocused. This
// notifies all of the plugins.
void OnSetFocus(bool has_focus);
@@ -101,7 +132,6 @@ class PepperPluginDelegateImpl
virtual PlatformVideoDecoder* CreateVideoDecoder(
PP_VideoDecoderConfig_Dev* decoder_config);
virtual PpapiBroker* ConnectToPpapiBroker(
- webkit::ppapi::PluginInstance* instance,
webkit::ppapi::PPB_Broker_Impl* client);
virtual void NumberOfFindResultsChanged(int identifier,
int total,
@@ -193,6 +223,10 @@ class PepperPluginDelegateImpl
virtual webkit_glue::P2PTransport* CreateP2PTransport();
private:
+ // Asynchronously attempts to create a PPAPI broker for the given plugin.
+ scoped_refptr<webkit::ppapi::PluginDelegate::PpapiBroker> CreatePpapiBroker(
+ webkit::ppapi::PluginModule* plugin_module);
+
// Pointer to the RenderView that owns us.
RenderView* render_view_;
@@ -213,6 +247,9 @@ class PepperPluginDelegateImpl
IDMap<scoped_refptr<webkit::ppapi::PPB_Flash_Menu_Impl>,
IDMapOwnPointer> pending_context_menus_;
+ IDMap<scoped_refptr<PpapiBrokerImpl>, IDMapOwnPointer>
+ pending_connect_broker_;
+
DISALLOW_COPY_AND_ASSIGN(PepperPluginDelegateImpl);
};
diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc
index 1a41f03..4ea0bcc 100644
--- a/content/renderer/render_view.cc
+++ b/content/renderer/render_view.cc
@@ -932,6 +932,8 @@ bool RenderView::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_AccessibilityNotifications_ACK,
OnAccessibilityNotificationsAck)
IPC_MESSAGE_HANDLER(ViewMsg_AsyncOpenFile_ACK, OnAsyncFileOpened)
+ IPC_MESSAGE_HANDLER(ViewMsg_PpapiBrokerChannelCreated,
+ OnPpapiBrokerChannelCreated)
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
#endif
@@ -4801,6 +4803,11 @@ void RenderView::OnAsyncFileOpened(base::PlatformFileError error_code,
message_id);
}
+void RenderView::OnPpapiBrokerChannelCreated(int request_id,
+ const IPC::ChannelHandle& handle) {
+ pepper_delegate_.OnPpapiBrokerChannelCreated(request_id, handle);
+}
+
#if defined(OS_MACOSX)
void RenderView::OnSelectPopupMenuItem(int selected_index) {
if (external_popup_menu_ == NULL) {
diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h
index 6fdc8f6..efe2323 100644
--- a/content/renderer/render_view.h
+++ b/content/renderer/render_view.h
@@ -746,6 +746,8 @@ class RenderView : public RenderWidget,
void OnAsyncFileOpened(base::PlatformFileError error_code,
IPC::PlatformFileForTransit file_for_transit,
int message_id);
+ void OnPpapiBrokerChannelCreated(int request_id,
+ const IPC::ChannelHandle& handle);
void OnCancelDownload(int32 download_id);
void OnClearFocusedNode();
void OnClosePage(const ViewMsg_ClosePage_Params& params);
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index 057874e..270af84 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -29,7 +29,7 @@
#define IPC_MESSAGE_START PpapiMsgStart
-// These are from the plugin to the renderer
+// These are from the browser to the plugin.
// Loads the given plugin.
IPC_MESSAGE_CONTROL1(PpapiMsg_LoadPlugin, FilePath /* path */)
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.cc b/webkit/plugins/ppapi/mock_plugin_delegate.cc
index a9da765..e896bcd 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.cc
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.cc
@@ -53,7 +53,6 @@ MockPluginDelegate::PlatformAudio* MockPluginDelegate::CreateAudio(
}
MockPluginDelegate::PpapiBroker* MockPluginDelegate::ConnectToPpapiBroker(
- PluginInstance* instance,
PPB_Broker_Impl* client) {
return NULL;
}
diff --git a/webkit/plugins/ppapi/mock_plugin_delegate.h b/webkit/plugins/ppapi/mock_plugin_delegate.h
index 78d59a2..101f788 100644
--- a/webkit/plugins/ppapi/mock_plugin_delegate.h
+++ b/webkit/plugins/ppapi/mock_plugin_delegate.h
@@ -26,8 +26,7 @@ class MockPluginDelegate : public PluginDelegate {
virtual PlatformAudio* CreateAudio(uint32_t sample_rate,
uint32_t sample_count,
PlatformAudio::Client* client);
- virtual PpapiBroker* ConnectToPpapiBroker(PluginInstance* instance,
- PPB_Broker_Impl* client);
+ virtual PpapiBroker* ConnectToPpapiBroker(PPB_Broker_Impl* client);
virtual void NumberOfFindResultsChanged(int identifier,
int total,
bool final_result);
diff --git a/webkit/plugins/ppapi/plugin_delegate.h b/webkit/plugins/ppapi/plugin_delegate.h
index 786e924..d986e95 100644
--- a/webkit/plugins/ppapi/plugin_delegate.h
+++ b/webkit/plugins/ppapi/plugin_delegate.h
@@ -210,15 +210,18 @@ class PluginDelegate {
};
// Provides access to the ppapi broker.
- class PpapiBroker {
+ class PpapiBroker : public base::RefCountedThreadSafe<PpapiBroker> {
public:
- virtual ~PpapiBroker() {}
+ virtual void Connect(webkit::ppapi::PPB_Broker_Impl* client) = 0;
- // Decrements the references to the broker for the instance.
- // When the references reach 0 for all instances in this renderer, this
- // object may be destroyed. When the references reach 0 for all instances
- // using the same module, the broker may shut down.
- virtual void Release(PluginInstance* instance) = 0;
+ // Decrements the references to the broker.
+ // When there are no more references, this renderer's dispatcher is
+ // destroyed, allowing the broker to shutdown if appropriate.
+ virtual void Disconnect(webkit::ppapi::PPB_Broker_Impl* client) = 0;
+
+ protected:
+ friend class base::RefCountedThreadSafe<PpapiBroker>;
+ ~PpapiBroker() {}
};
// Notification that the given plugin has crashed. When a plugin crashes, all
@@ -259,7 +262,6 @@ class PluginDelegate {
// The caller is responsible for calling Release() on the returned pointer
// to clean up the corresponding resources allocated during this call.
virtual PpapiBroker* ConnectToPpapiBroker(
- PluginInstance* instance,
webkit::ppapi::PPB_Broker_Impl* client) = 0;
// Notifies that the number of find results has changed.
diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc
index d469860..6fc7f7c 100644
--- a/webkit/plugins/ppapi/plugin_module.cc
+++ b/webkit/plugins/ppapi/plugin_module.cc
@@ -389,6 +389,7 @@ PluginModule::PluginModule(const std::string& name,
: lifetime_delegate_(lifetime_delegate),
callback_tracker_(new CallbackTracker),
is_crashed_(false),
+ broker_(NULL),
library_(NULL),
name_(name),
path_(path),
@@ -527,6 +528,16 @@ bool PluginModule::ReserveInstanceID(PP_Instance instance) {
return true; // Instance ID is usable.
}
+void PluginModule::SetBroker(
+ scoped_refptr<PluginDelegate::PpapiBroker> broker) {
+ DCHECK(!broker_.get());
+ broker_ = broker;
+}
+
+scoped_refptr<PluginDelegate::PpapiBroker> PluginModule::GetBroker(){
+ return broker_;
+}
+
bool PluginModule::InitializeModule() {
DCHECK(!out_of_process_proxy_.get()) << "Don't call for proxied modules.";
int retval = entry_points_.initialize_module(pp_module(), &GetInterface);
diff --git a/webkit/plugins/ppapi/plugin_module.h b/webkit/plugins/ppapi/plugin_module.h
index dabd032..e462f3a 100644
--- a/webkit/plugins/ppapi/plugin_module.h
+++ b/webkit/plugins/ppapi/plugin_module.h
@@ -145,6 +145,9 @@ class PluginModule : public base::RefCounted<PluginModule>,
PP_Bool (*reserve)(PP_Module, PP_Instance));
bool ReserveInstanceID(PP_Instance instance);
+ void SetBroker(scoped_refptr<PluginDelegate::PpapiBroker> broker);
+ scoped_refptr<PluginDelegate::PpapiBroker> GetBroker();
+
private:
// Calls the InitializeModule entrypoint. The entrypoint must have been
// set and the plugin must not be out of process (we don't maintain
@@ -167,6 +170,9 @@ class PluginModule : public base::RefCounted<PluginModule>,
// entry_points_ aren't valid.
scoped_ptr<PluginDelegate::OutOfProcessProxy> out_of_process_proxy_;
+ // Trusted broker for this plugin module.
+ scoped_refptr<PluginDelegate::PpapiBroker> broker_;
+
// Holds a reference to the base::NativeLibrary handle if this PluginModule
// instance wraps functions loaded from a library. Can be NULL. If
// |library_| is non-NULL, PluginModule will attempt to unload the library
diff --git a/webkit/plugins/ppapi/ppb_broker_impl.cc b/webkit/plugins/ppapi/ppb_broker_impl.cc
index 9e0cb5c..83912c5 100644
--- a/webkit/plugins/ppapi/ppb_broker_impl.cc
+++ b/webkit/plugins/ppapi/ppb_broker_impl.cc
@@ -72,7 +72,7 @@ PPB_Broker_Impl::PPB_Broker_Impl(PluginInstance* instance)
PPB_Broker_Impl::~PPB_Broker_Impl() {
if (broker_) {
- broker_->Release(instance());
+ broker_->Disconnect(this);
broker_ = NULL;
}
@@ -94,7 +94,7 @@ int32_t PPB_Broker_Impl::Connect(
return PP_ERROR_FAILED;
}
- broker_ = plugin_delegate->ConnectToPpapiBroker(instance(), this);
+ broker_ = plugin_delegate->ConnectToPpapiBroker(this);
if (!broker_)
return PP_ERROR_FAILED;
diff --git a/webkit/plugins/ppapi/ppb_broker_impl.h b/webkit/plugins/ppapi/ppb_broker_impl.h
index f83d280..66454b9 100644
--- a/webkit/plugins/ppapi/ppb_broker_impl.h
+++ b/webkit/plugins/ppapi/ppb_broker_impl.h
@@ -38,7 +38,7 @@ class PPB_Broker_Impl : public Resource {
private:
// PluginDelegate ppapi broker object.
// We don't own this pointer but are responsible for calling Release on it.
- PluginDelegate::PpapiBroker* broker_;
+ scoped_refptr<PluginDelegate::PpapiBroker> broker_;
// Callback invoked from BrokerConnected.
scoped_refptr<TrackedCompletionCallback> connect_callback_;