summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/chrome_plugin_host.cc4
-rw-r--r--chrome/browser/plugin_data_remover.cc2
-rw-r--r--chrome/browser/plugin_service.cc94
-rw-r--r--chrome/browser/plugin_service.h30
-rw-r--r--chrome/browser/plugin_service_browsertest.cc12
-rw-r--r--chrome/browser/ppapi_plugin_process_host.cc137
-rw-r--r--chrome/browser/ppapi_plugin_process_host.h54
-rw-r--r--chrome/browser/renderer_host/render_message_filter.cc102
-rw-r--r--chrome/browser/renderer_host/render_message_filter.h4
9 files changed, 305 insertions, 134 deletions
diff --git a/chrome/browser/chrome_plugin_host.cc b/chrome/browser/chrome_plugin_host.cc
index ad4462e..2b020d4 100644
--- a/chrome/browser/chrome_plugin_host.cc
+++ b/chrome/browser/chrome_plugin_host.cc
@@ -702,7 +702,7 @@ CPBool STDCALL CPB_IsPluginProcessRunning(CPID id) {
PluginService* service = PluginService::GetInstance();
if (!service)
return false;
- PluginProcessHost *host = service->FindPluginProcess(plugin->filename());
+ PluginProcessHost *host = service->FindNpapiPluginProcess(plugin->filename());
return host ? true : false;
}
@@ -720,7 +720,7 @@ CPError STDCALL CPB_SendMessage(CPID id, const void *data, uint32 data_len) {
if (!service)
return CPERR_FAILURE;
PluginProcessHost *host =
- service->FindOrStartPluginProcess(plugin->filename());
+ service->FindOrStartNpapiPluginProcess(plugin->filename());
if (!host)
return CPERR_FAILURE;
diff --git a/chrome/browser/plugin_data_remover.cc b/chrome/browser/plugin_data_remover.cc
index 188140a..a32e12b 100644
--- a/chrome/browser/plugin_data_remover.cc
+++ b/chrome/browser/plugin_data_remover.cc
@@ -49,7 +49,7 @@ base::WaitableEvent* PluginDataRemover::StartRemoving(
is_removing_ = true;
AddRef();
- PluginService::GetInstance()->OpenChannelToPlugin(
+ PluginService::GetInstance()->OpenChannelToNpapiPlugin(
0, 0, GURL(), mime_type_, this);
BrowserThread::PostDelayedTask(
diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc
index 148f65e..a65bea6 100644
--- a/chrome/browser/plugin_service.cc
+++ b/chrome/browser/plugin_service.cc
@@ -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.
@@ -18,6 +18,7 @@
#include "chrome/browser/chrome_plugin_host.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/plugin_updater.h"
+#include "chrome/browser/ppapi_plugin_process_host.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
@@ -240,7 +241,7 @@ const std::string& PluginService::GetUILocale() {
return ui_locale_;
}
-PluginProcessHost* PluginService::FindPluginProcess(
+PluginProcessHost* PluginService::FindNpapiPluginProcess(
const FilePath& plugin_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
@@ -254,11 +255,27 @@ PluginProcessHost* PluginService::FindPluginProcess(
return NULL;
}
-PluginProcessHost* PluginService::FindOrStartPluginProcess(
+PpapiPluginProcessHost* PluginService::FindPpapiPluginProcess(
const FilePath& plugin_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- PluginProcessHost* plugin_host = FindPluginProcess(plugin_path);
+ for (BrowserChildProcessHost::Iterator iter(
+ ChildProcessInfo::PPAPI_PLUGIN_PROCESS);
+ !iter.Done(); ++iter) {
+ PpapiPluginProcessHost* plugin =
+ static_cast<PpapiPluginProcessHost*>(*iter);
+ if (plugin->plugin_path() == plugin_path)
+ return plugin;
+ }
+
+ return NULL;
+}
+
+PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess(
+ const FilePath& plugin_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
if (plugin_host)
return plugin_host;
@@ -271,14 +288,42 @@ PluginProcessHost* PluginService::FindOrStartPluginProcess(
// This plugin isn't loaded by any plugin process, so create a new process.
scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
if (!new_host->Init(info, ui_locale_)) {
- NOTREACHED(); // Init is not expected to fail
+ NOTREACHED(); // Init is not expected to fail.
return NULL;
}
+ return new_host.release();
+}
+PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess(
+ const FilePath& plugin_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
+ 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;
+ }
+ }
+ if (!info)
+ return NULL;
+
+ // This plugin isn't loaded by any plugin process, so create a new process.
+ scoped_ptr<PpapiPluginProcessHost> new_host(new PpapiPluginProcessHost);
+ if (!new_host->Init(plugin_path)) {
+ NOTREACHED(); // Init is not expected to fail.
+ return NULL;
+ }
return new_host.release();
}
-void PluginService::OpenChannelToPlugin(
+void PluginService::OpenChannelToNpapiPlugin(
int render_process_id,
int render_view_id,
const GURL& url,
@@ -293,6 +338,16 @@ void PluginService::OpenChannelToPlugin(
render_process_id, render_view_id, url, mime_type, client));
}
+void PluginService::OpenChannelToPpapiPlugin(
+ const FilePath& path,
+ PpapiPluginProcessHost::Client* client) {
+ PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(path);
+ if (plugin_host)
+ plugin_host->OpenChannelToPlugin(client);
+ else // Send error.
+ client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
+}
+
void PluginService::GetAllowedPluginForOpenChannelToPlugin(
int render_process_id,
int render_view_id,
@@ -320,7 +375,7 @@ void PluginService::FinishOpenChannelToPlugin(
PluginProcessHost::Client* client) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- PluginProcessHost* plugin_host = FindOrStartPluginProcess(plugin_path);
+ PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
if (plugin_host)
plugin_host->OpenChannelToPlugin(client);
else
@@ -392,7 +447,7 @@ void PluginService::OnWaitableEventSignaled(
static void ForceShutdownPlugin(const FilePath& plugin_path) {
PluginProcessHost* plugin =
- PluginService::GetInstance()->FindPluginProcess(plugin_path);
+ PluginService::GetInstance()->FindNpapiPluginProcess(plugin_path);
if (plugin)
plugin->ForceShutdown();
}
@@ -490,26 +545,25 @@ void PluginService::OverridePluginForTab(OverriddenPlugin plugin) {
}
void PluginService::RegisterPepperPlugins() {
- std::vector<PepperPluginInfo> plugins;
- PepperPluginRegistry::ComputeList(&plugins);
- for (size_t i = 0; i < plugins.size(); ++i) {
+ PepperPluginRegistry::ComputeList(&ppapi_plugins_);
+ for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
webkit::npapi::WebPluginInfo info;
- info.path = plugins[i].path;
- info.name = plugins[i].name.empty() ?
- plugins[i].path.BaseName().LossyDisplayName() :
- ASCIIToUTF16(plugins[i].name);
- info.desc = ASCIIToUTF16(plugins[i].description);
+ info.path = ppapi_plugins_[i].path;
+ info.name = ppapi_plugins_[i].name.empty() ?
+ ppapi_plugins_[i].path.BaseName().LossyDisplayName() :
+ ASCIIToUTF16(ppapi_plugins_[i].name);
+ info.desc = ASCIIToUTF16(ppapi_plugins_[i].description);
info.enabled = webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
// TODO(evan): Pepper shouldn't require us to parse strings to get
// the list of mime types out.
if (!webkit::npapi::PluginList::ParseMimeTypes(
- JoinString(plugins[i].mime_types, '|'),
- plugins[i].file_extensions,
- ASCIIToUTF16(plugins[i].type_descriptions),
+ JoinString(ppapi_plugins_[i].mime_types, '|'),
+ ppapi_plugins_[i].file_extensions,
+ ASCIIToUTF16(ppapi_plugins_[i].type_descriptions),
&info.mime_types)) {
LOG(ERROR) << "Error parsing mime types for "
- << plugins[i].path.LossyDisplayName();
+ << ppapi_plugins_[i].path.LossyDisplayName();
return;
}
diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h
index f2732b2..1c0af96 100644
--- a/chrome/browser/plugin_service.h
+++ b/chrome/browser/plugin_service.h
@@ -20,6 +20,7 @@
#include "base/synchronization/waitable_event_watcher.h"
#include "build/build_config.h"
#include "chrome/browser/plugin_process_host.h"
+#include "chrome/browser/ppapi_plugin_process_host.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
#include "googleurl/src/gurl.h"
@@ -46,8 +47,9 @@ class Message;
}
class MessageLoop;
-class Profile;
+struct PepperPluginInfo;
class PluginDirWatcherDelegate;
+class Profile;
class ResourceDispatcherHost;
namespace net {
@@ -89,22 +91,28 @@ class PluginService
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. Returns NULL if no process has been
// started.
- PluginProcessHost* FindPluginProcess(const FilePath& plugin_path);
+ PluginProcessHost* FindNpapiPluginProcess(const FilePath& plugin_path);
+ PpapiPluginProcessHost* FindPpapiPluginProcess(const FilePath& plugin_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
// 'plugin_path' if needed. If the process fails to start, the return value
// is NULL. Must be called on the IO thread.
- PluginProcessHost* FindOrStartPluginProcess(const FilePath& plugin_path);
+ PluginProcessHost* FindOrStartNpapiPluginProcess(
+ const FilePath& plugin_path);
+ PpapiPluginProcessHost* FindOrStartPpapiPluginProcess(
+ 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
// or else a deadlock can occur.
- void OpenChannelToPlugin(int render_process_id,
- int render_view_id,
- const GURL& url,
- const std::string& mime_type,
- PluginProcessHost::Client* client);
+ void OpenChannelToNpapiPlugin(int render_process_id,
+ int render_view_id,
+ const GURL& url,
+ const std::string& mime_type,
+ PluginProcessHost::Client* client);
+ void OpenChannelToPpapiPlugin(const FilePath& path,
+ PpapiPluginProcessHost::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.
@@ -170,10 +178,6 @@ class PluginService
FilePathWatcher::Delegate* delegate);
#endif
- // mapping between plugin path and PluginProcessHost
- typedef base::hash_map<FilePath, PluginProcessHost*> PluginMap;
- PluginMap plugin_hosts_;
-
// The main thread's message loop.
MessageLoop* main_message_loop_;
@@ -212,6 +216,8 @@ class PluginService
scoped_refptr<PluginDirWatcherDelegate> file_watcher_delegate_;
#endif
+ std::vector<PepperPluginInfo> ppapi_plugins_;
+
// Set to true if chrome plugins are enabled. Defaults to true.
static bool enable_chrome_plugins_;
diff --git a/chrome/browser/plugin_service_browsertest.cc b/chrome/browser/plugin_service_browsertest.cc
index 3f31159..ee1be0c 100644
--- a/chrome/browser/plugin_service_browsertest.cc
+++ b/chrome/browser/plugin_service_browsertest.cc
@@ -72,19 +72,19 @@ IN_PROC_BROWSER_TEST_F(PluginServiceTest, StartAndFindPluginProcess) {
// Try to load the default plugin and if this is successful consecutive
// calls to FindPluginProcess should return non-zero values.
PluginProcessHost* default_plugin_process_host =
- plugin_service_->FindOrStartPluginProcess(
+ plugin_service_->FindOrStartNpapiPluginProcess(
FilePath(webkit::npapi::kDefaultPluginLibraryName));
- EXPECT_EQ(default_plugin_process_host, plugin_service_->FindPluginProcess(
- FilePath(webkit::npapi::kDefaultPluginLibraryName)));
+ EXPECT_EQ(default_plugin_process_host,
+ plugin_service_->FindNpapiPluginProcess(
+ FilePath(webkit::npapi::kDefaultPluginLibraryName)));
}
IN_PROC_BROWSER_TEST_F(PluginServiceTest, OpenChannelToPlugin) {
MockPluginProcessHostClient mock_client;
EXPECT_CALL(mock_client, SetPluginInfo(testing::_)).Times(1);
- plugin_service_->OpenChannelToPlugin(0, 0, GURL("http://google.com/"),
- "audio/mp3",
- &mock_client);
+ plugin_service_->OpenChannelToNpapiPlugin(0, 0, GURL("http://google.com/"),
+ "audio/mp3", &mock_client);
message_loop_.RunAllPending();
}
diff --git a/chrome/browser/ppapi_plugin_process_host.cc b/chrome/browser/ppapi_plugin_process_host.cc
index 225cc80..c319dd0 100644
--- a/chrome/browser/ppapi_plugin_process_host.cc
+++ b/chrome/browser/ppapi_plugin_process_host.cc
@@ -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.
@@ -7,40 +7,36 @@
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/process_util.h"
+#include "chrome/browser/plugin_service.h"
#include "chrome/browser/renderer_host/render_message_filter.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/render_messages.h"
#include "ipc/ipc_switches.h"
#include "ppapi/proxy/ppapi_messages.h"
-PpapiPluginProcessHost::PpapiPluginProcessHost(RenderMessageFilter* filter)
- : BrowserChildProcessHost(ChildProcessInfo::PPAPI_PLUGIN_PROCESS,
- filter->resource_dispatcher_host()),
- filter_(filter) {
+PpapiPluginProcessHost::PpapiPluginProcessHost()
+ : BrowserChildProcessHost(
+ ChildProcessInfo::PPAPI_PLUGIN_PROCESS,
+ PluginService::GetInstance()->resource_dispatcher_host()) {
}
PpapiPluginProcessHost::~PpapiPluginProcessHost() {
+ CancelRequests();
}
-void PpapiPluginProcessHost::Init(const FilePath& path,
- IPC::Message* reply_msg) {
+bool PpapiPluginProcessHost::Init(const FilePath& path) {
plugin_path_ = path;
- reply_msg_.reset(reply_msg);
- if (!CreateChannel()) {
- ReplyToRenderer(base::kNullProcessHandle, IPC::ChannelHandle());
- return;
- }
+ if (!CreateChannel())
+ return false;
const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
CommandLine::StringType plugin_launcher =
browser_command_line.GetSwitchValueNative(switches::kPpapiPluginLauncher);
FilePath exe_path = ChildProcessHost::GetChildPath(plugin_launcher.empty());
- if (exe_path.empty()) {
- ReplyToRenderer(base::kNullProcessHandle, IPC::ChannelHandle());
- return;
- }
+ if (exe_path.empty())
+ return false;
CommandLine* cmd_line = new CommandLine(exe_path);
cmd_line->AppendSwitchASCII(switches::kProcessType,
@@ -60,6 +56,36 @@ void PpapiPluginProcessHost::Init(const FilePath& path,
base::environment_vector(),
#endif
cmd_line);
+ return true;
+}
+
+void PpapiPluginProcessHost::OpenChannelToPlugin(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 plugin.
+ RequestPluginChannel(client);
+}
+
+void PpapiPluginProcessHost::RequestPluginChannel(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 PpapiPluginProcessHost::CanShutdown() {
@@ -72,56 +98,77 @@ void PpapiPluginProcessHost::OnProcessLaunched() {
bool PpapiPluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PpapiPluginProcessHost, msg)
- IPC_MESSAGE_HANDLER(PpapiHostMsg_PluginLoaded, OnPluginLoaded)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated,
+ OnRendererPluginChannelCreated)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled);
return handled;
}
+// Called when the browser <--> plugin channel has been established.
void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) {
-#if defined(OS_WIN)
- base::ProcessHandle plugins_renderer_handle = NULL;
- ::DuplicateHandle(::GetCurrentProcess(), filter_->peer_handle(),
- GetChildProcessHandle(), &plugins_renderer_handle,
- 0, FALSE, DUPLICATE_SAME_ACCESS);
-#elif defined(OS_POSIX)
- base::ProcessHandle plugins_renderer_handle = filter_->peer_handle();
-#endif
-
- PpapiMsg_LoadPlugin* msg = new PpapiMsg_LoadPlugin(
- plugins_renderer_handle, plugin_path_, filter_->render_process_id());
- if (!Send(msg)) // Just send an empty handle on failure.
- ReplyToRenderer(base::kNullProcessHandle, IPC::ChannelHandle());
- // This function will result in OnChannelCreated getting called to finish.
+ // This will actually load the plugin. Errors will actually not be reported
+ // back at this point. Instead, the plugin will fail to establish the
+ // connections when we request them on behalf of the renderer(s).
+ Send(new PpapiMsg_LoadPlugin(plugin_path_));
+
+ // Process all pending channel requests from the renderers.
+ for (size_t i = 0; i < pending_requests_.size(); i++)
+ RequestPluginChannel(pending_requests_[i]);
+ pending_requests_.clear();
}
+// Called when the browser <--> plugin channel has an error. This normally
+// means the plugin has crashed.
void PpapiPluginProcessHost::OnChannelError() {
- if (reply_msg_.get())
- ReplyToRenderer(base::kNullProcessHandle, IPC::ChannelHandle());
+ // We don't need to notify the renderers that were communicating with the
+ // plugin 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 PpapiPluginProcessHost::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();
+ }
}
-void PpapiPluginProcessHost::OnPluginLoaded(
+// Called when a new plugin <--> renderer channel has been created.
+void PpapiPluginProcessHost::OnRendererPluginChannelCreated(
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 plugin_process = GetChildProcessHandle();
#if defined(OS_WIN)
+ base::ProcessHandle renderer_process;
+ int renderer_id;
+ client->GetChannelInfo(&renderer_process, &renderer_id);
+
base::ProcessHandle renderers_plugin_handle = NULL;
::DuplicateHandle(::GetCurrentProcess(), plugin_process,
- filter_->peer_handle(), &renderers_plugin_handle,
+ renderer_process, &renderers_plugin_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_plugin_handle = plugin_process;
#endif
- ReplyToRenderer(renderers_plugin_handle, channel_handle);
-}
-void PpapiPluginProcessHost::ReplyToRenderer(
- base::ProcessHandle plugin_handle,
- const IPC::ChannelHandle& channel_handle) {
- DCHECK(reply_msg_.get());
- ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(reply_msg_.get(),
- plugin_handle,
- channel_handle);
- filter_->Send(reply_msg_.release());
+ client->OnChannelOpened(renderers_plugin_handle, channel_handle);
}
diff --git a/chrome/browser/ppapi_plugin_process_host.h b/chrome/browser/ppapi_plugin_process_host.h
index 227cf31..945195d 100644
--- a/chrome/browser/ppapi_plugin_process_host.h
+++ b/chrome/browser/ppapi_plugin_process_host.h
@@ -6,20 +6,48 @@
#define CHROME_BROWSER_PPAPI_PLUGIN_PROCESS_HOST_H_
#pragma once
+#include <queue>
+
#include "base/basictypes.h"
#include "base/file_path.h"
#include "chrome/browser/browser_child_process_host.h"
-class RenderMessageFilter;
-
class PpapiPluginProcessHost : public BrowserChildProcessHost {
public:
- explicit PpapiPluginProcessHost(RenderMessageFilter* filter);
+ 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 plugin or on
+ // error. On error, the parameters should be:
+ // base::kNullProcessHandle
+ // IPC::ChannelHandle()
+ virtual void OnChannelOpened(base::ProcessHandle plugin_process_handle,
+ const IPC::ChannelHandle& channel_handle) = 0;
+ };
+
+ // You must call init before doing anything else.
+ explicit PpapiPluginProcessHost();
virtual ~PpapiPluginProcessHost();
- void Init(const FilePath& path, IPC::Message* reply_msg);
+ // Actually launches the process with the given plugin path. Returns true
+ // on success (the process was spawned).
+ bool Init(const FilePath& path);
+
+ // Opens a new channel to the plugin. The client will be notified when the
+ // channel is ready or if there's an error.
+ void OpenChannelToPlugin(Client* client);
+
+ const FilePath& plugin_path() const { return plugin_path_; }
+
+ // The client pointer must remain valid until its callback is issued.
private:
+
+ void RequestPluginChannel(Client* client);
+
virtual bool CanShutdown();
virtual void OnProcessLaunched();
@@ -27,22 +55,22 @@ class PpapiPluginProcessHost : public BrowserChildProcessHost {
virtual void OnChannelConnected(int32 peer_pid);
virtual void OnChannelError();
+ void CancelRequests();
+
// IPC message handlers.
- void OnPluginLoaded(const IPC::ChannelHandle& handle);
+ void OnRendererPluginChannelCreated(const IPC::ChannelHandle& handle);
- // Sends the reply_msg_ to the renderer with the given channel info.
- void ReplyToRenderer(base::ProcessHandle plugin_handle,
- const IPC::ChannelHandle& channel_handle);
+ // Channel requests that we are waiting to send to the plugin process once
+ // the channel is opened.
+ std::vector<Client*> pending_requests_;
- RenderMessageFilter* filter_;
+ // 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 plugin_path_;
- // When we're waiting for initialization of the plugin, this contains the
- // reply message for the renderer to tell it that it can continue.
- scoped_ptr<IPC::Message> reply_msg_;
-
DISALLOW_COPY_AND_ASSIGN(PpapiPluginProcessHost);
};
diff --git a/chrome/browser/renderer_host/render_message_filter.cc b/chrome/browser/renderer_host/render_message_filter.cc
index d9d7a32..f4f8514 100644
--- a/chrome/browser/renderer_host/render_message_filter.cc
+++ b/chrome/browser/renderer_host/render_message_filter.cc
@@ -167,39 +167,62 @@ void RenderParamsFromPrintSettings(const printing::PrintSettings& settings,
params->supports_alpha_blend = settings.supports_alpha_blend();
}
-class ClearCacheCompletion : public net::CompletionCallback {
+// Common functionality for converting a sync renderer message to a callback
+// function in the browser. Derive from this, create it on the heap when
+// issuing your callback. When done, write your reply parameters into
+// reply_msg(), and then call SendReplyAndDeleteThis().
+class RenderMessageCompletionCallback {
public:
- ClearCacheCompletion(IPC::Message* reply_msg,
- RenderMessageFilter* filter)
- : reply_msg_(reply_msg),
- filter_(filter) {
+ RenderMessageCompletionCallback(RenderMessageFilter* filter,
+ IPC::Message* reply_msg)
+ : filter_(filter),
+ reply_msg_(reply_msg) {
}
- virtual void RunWithParams(const Tuple1<int>& params) {
- ViewHostMsg_ClearCache::WriteReplyParams(reply_msg_, params.a);
+ virtual ~RenderMessageCompletionCallback() {
+ }
+
+ RenderMessageFilter* filter() { return filter_.get(); }
+ IPC::Message* reply_msg() { return reply_msg_; }
+
+ void SendReplyAndDeleteThis() {
filter_->Send(reply_msg_);
delete this;
}
private:
- IPC::Message* reply_msg_;
scoped_refptr<RenderMessageFilter> filter_;
+ IPC::Message* reply_msg_;
};
-class OpenChannelToPluginCallback : public PluginProcessHost::Client {
+class ClearCacheCompletion : public RenderMessageCompletionCallback,
+ public net::CompletionCallback {
public:
- OpenChannelToPluginCallback(RenderMessageFilter* filter,
- IPC::Message* reply_msg)
- : filter_(filter),
- reply_msg_(reply_msg) {
+ ClearCacheCompletion(RenderMessageFilter* filter,
+ IPC::Message* reply_msg)
+ : RenderMessageCompletionCallback(filter, reply_msg) {
+ }
+
+ virtual void RunWithParams(const Tuple1<int>& params) {
+ ViewHostMsg_ClearCache::WriteReplyParams(reply_msg(), params.a);
+ SendReplyAndDeleteThis();
+ }
+};
+
+class OpenChannelToNpapiPluginCallback : public RenderMessageCompletionCallback,
+ public PluginProcessHost::Client {
+ public:
+ OpenChannelToNpapiPluginCallback(RenderMessageFilter* filter,
+ IPC::Message* reply_msg)
+ : RenderMessageCompletionCallback(filter, reply_msg) {
}
virtual int ID() {
- return filter_->render_process_id();
+ return filter()->render_process_id();
}
virtual bool OffTheRecord() {
- return filter_->off_the_record();
+ return filter()->off_the_record();
}
virtual void SetPluginInfo(const webkit::npapi::WebPluginInfo& info) {
@@ -207,27 +230,45 @@ class OpenChannelToPluginCallback : public PluginProcessHost::Client {
}
virtual void OnChannelOpened(const IPC::ChannelHandle& handle) {
- WriteReply(handle);
+ WriteReplyAndDeleteThis(handle);
}
virtual void OnError() {
- WriteReply(IPC::ChannelHandle());
+ WriteReplyAndDeleteThis(IPC::ChannelHandle());
}
private:
- void WriteReply(const IPC::ChannelHandle& handle) {
- ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg_,
- handle,
- info_);
- filter_->Send(reply_msg_);
- delete this;
+ void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) {
+ ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
+ handle, info_);
+ SendReplyAndDeleteThis();
}
- scoped_refptr<RenderMessageFilter> filter_;
- IPC::Message* reply_msg_;
webkit::npapi::WebPluginInfo info_;
};
+class OpenChannelToPpapiPluginCallback : public RenderMessageCompletionCallback,
+ public PpapiPluginProcessHost::Client {
+ public:
+ OpenChannelToPpapiPluginCallback(RenderMessageFilter* filter,
+ IPC::Message* reply_msg)
+ : RenderMessageCompletionCallback(filter, reply_msg) {
+ }
+
+ 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) {
+ ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(
+ reply_msg(), plugin_process_handle, channel_handle);
+ SendReplyAndDeleteThis();
+ }
+};
+
} // namespace
RenderMessageFilter::RenderMessageFilter(
@@ -719,17 +760,16 @@ void RenderMessageFilter::OnOpenChannelToPlugin(int routing_id,
const GURL& url,
const std::string& mime_type,
IPC::Message* reply_msg) {
- plugin_service_->OpenChannelToPlugin(
+ plugin_service_->OpenChannelToNpapiPlugin(
render_process_id_, routing_id, url, mime_type,
- new OpenChannelToPluginCallback(this, reply_msg));
+ new OpenChannelToNpapiPluginCallback(this, reply_msg));
}
void RenderMessageFilter::OnOpenChannelToPepperPlugin(
const FilePath& path,
IPC::Message* reply_msg) {
- PpapiPluginProcessHost* host = new PpapiPluginProcessHost(this);
- host->Init(path, reply_msg);
- ppapi_plugin_hosts_.push_back(linked_ptr<PpapiPluginProcessHost>(host));
+ plugin_service_->OpenChannelToPpapiPlugin(
+ path, new OpenChannelToPpapiPluginCallback(this, reply_msg));
}
void RenderMessageFilter::OnLaunchNaCl(
@@ -1293,7 +1333,7 @@ void RenderMessageFilter::OnClearCache(IPC::Message* reply_msg) {
http_transaction_factory()->GetCache()->GetCurrentBackend();
if (backend) {
ClearCacheCompletion* callback =
- new ClearCacheCompletion(reply_msg, this);
+ new ClearCacheCompletion(this, reply_msg);
rv = backend->DoomAllEntries(callback);
if (rv == net::ERR_IO_PENDING) {
// The callback will send the reply.
diff --git a/chrome/browser/renderer_host/render_message_filter.h b/chrome/browser/renderer_host/render_message_filter.h
index d2901715..a0339de 100644
--- a/chrome/browser/renderer_host/render_message_filter.h
+++ b/chrome/browser/renderer_host/render_message_filter.h
@@ -34,7 +34,6 @@ struct FontDescriptor;
class HostContentSettingsMap;
class HostZoomMap;
class NotificationsPrefsCache;
-class PpapiPluginProcessHost;
class Profile;
class RenderWidgetHelper;
class URLRequestContextGetter;
@@ -410,9 +409,6 @@ class RenderMessageFilter : public BrowserMessageFilter,
base::TimeTicks last_plugin_refresh_time_; // Initialized to 0.
- // A list of all Ppapi plugin processes for this renderer.
- std::vector<linked_ptr<PpapiPluginProcessHost> > ppapi_plugin_hosts_;
-
scoped_refptr<WebKitContext> webkit_context_;
int render_process_id_;