summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--chrome/ppapi_plugin/ppapi_thread.cc101
-rw-r--r--chrome/ppapi_plugin/ppapi_thread.h36
-rw-r--r--chrome/renderer/pepper_plugin_delegate_impl.cc6
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py27
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h2
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h2
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h2
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h2
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h2
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_autogen.h2
-rw-r--r--gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h2
-rw-r--r--ppapi/proxy/host_dispatcher.cc12
-rw-r--r--ppapi/proxy/host_dispatcher.h5
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc76
-rw-r--r--ppapi/proxy/plugin_dispatcher.h30
-rw-r--r--ppapi/proxy/ppapi_messages_internal.h23
-rw-r--r--ppapi/proxy/ppapi_proxy_test.cc4
30 files changed, 488 insertions, 293 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_;
diff --git a/chrome/ppapi_plugin/ppapi_thread.cc b/chrome/ppapi_plugin/ppapi_thread.cc
index 4e8c0c9..483863c 100644
--- a/chrome/ppapi_plugin/ppapi_thread.cc
+++ b/chrome/ppapi_plugin/ppapi_thread.cc
@@ -4,27 +4,33 @@
#include "chrome/ppapi_plugin/ppapi_thread.h"
+#include <limits>
+
#include "base/process_util.h"
+#include "base/rand_util.h"
#include "chrome/common/child_process.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/plugin_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
-#if defined(OS_POSIX)
-#include "base/eintr_wrapper.h"
-#include "ipc/ipc_channel_posix.h"
-#endif
-
PpapiThread::PpapiThread()
-#if defined(OS_POSIX)
- : renderer_fd_(-1)
-#endif
- {
+ : 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
@@ -37,37 +43,23 @@ PpapiThread::~PpapiThread() {
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;
}
-void PpapiThread::OnMsgLoadPlugin(base::ProcessHandle host_process_handle,
- const FilePath& path,
- int renderer_id) {
- IPC::ChannelHandle channel_handle;
- if (!LoadPluginLib(host_process_handle, path) ||
- !SetupRendererChannel(renderer_id, &channel_handle)) {
- // An empty channel handle indicates error.
- Send(new PpapiHostMsg_PluginLoaded(IPC::ChannelHandle()));
- return;
- }
-
- Send(new PpapiHostMsg_PluginLoaded(channel_handle));
-}
-
-bool PpapiThread::LoadPluginLib(base::ProcessHandle host_process_handle,
- const FilePath& path) {
+void PpapiThread::OnMsgLoadPlugin(const FilePath& path) {
base::ScopedNativeLibrary library(base::LoadNativeLibrary(path));
if (!library.is_valid())
- return false;
+ return;
// Get the GetInterface function (required).
- pp::proxy::Dispatcher::GetInterfaceFunc get_interface =
+ get_plugin_interface_ =
reinterpret_cast<pp::proxy::Dispatcher::GetInterfaceFunc>(
library.GetFunctionPointer("PPP_GetInterface"));
- if (!get_interface) {
+ if (!get_plugin_interface_) {
LOG(WARNING) << "No PPP_GetInterface in plugin library";
- return false;
+ return;
}
// Get the InitializeModule function (required).
@@ -76,26 +68,42 @@ bool PpapiThread::LoadPluginLib(base::ProcessHandle host_process_handle,
library.GetFunctionPointer("PPP_InitializeModule"));
if (!init_module) {
LOG(WARNING) << "No PPP_InitializeModule in plugin library";
- return false;
+ 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;
}
-
- // Get the ShutdownModule function (optional).
- pp::proxy::Dispatcher::ShutdownModuleFunc shutdown_module =
- reinterpret_cast<pp::proxy::Dispatcher::ShutdownModuleFunc>(
- library.GetFunctionPointer("PPP_ShutdownModule"));
library_.Reset(library.Release());
- dispatcher_.reset(new pp::proxy::PluginDispatcher(
- host_process_handle, get_interface, init_module, shutdown_module));
- return true;
}
-bool PpapiThread::SetupRendererChannel(int renderer_id,
+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) {
+ pp::proxy::PluginDispatcher* dispatcher = new pp::proxy::PluginDispatcher(
+ host_process_handle, get_plugin_interface_);
+
IPC::ChannelHandle plugin_handle;
plugin_handle.name = StringPrintf("%d.r%d", base::GetCurrentProcId(),
renderer_id);
- if (!dispatcher_->InitWithChannel(
+ if (!dispatcher->InitWithChannel(
ChildProcess::current()->io_message_loop(),
plugin_handle, false,
ChildProcess::current()->GetShutDownEvent()))
@@ -104,18 +112,9 @@ bool PpapiThread::SetupRendererChannel(int renderer_id,
handle->name = plugin_handle.name;
#if defined(OS_POSIX)
// On POSIX, pass the renderer-side FD.
- renderer_fd_ = dispatcher_->channel()->GetClientFileDescriptor();
- handle->socket = base::FileDescriptor(renderer_fd_, false);
+ handle->socket = base::FileDescriptor(dispatcher->GetRendererFD(), false);
#endif
+
return true;
}
-#if defined(OS_POSIX)
-void PpapiThread::CloseRendererFD() {
- if (renderer_fd_ != -1) {
- if (HANDLE_EINTR(close(renderer_fd_)) < 0)
- PLOG(ERROR) << "close";
- renderer_fd_ = -1;
- }
-}
-#endif
diff --git a/chrome/ppapi_plugin/ppapi_thread.h b/chrome/ppapi_plugin/ppapi_thread.h
index 08e62fc..32e45f5 100644
--- a/chrome/ppapi_plugin/ppapi_thread.h
+++ b/chrome/ppapi_plugin/ppapi_thread.h
@@ -12,6 +12,8 @@
#include "base/scoped_ptr.h"
#include "build/build_config.h"
#include "chrome/common/child_thread.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/proxy/dispatcher.h"
class FilePath;
@@ -35,35 +37,27 @@ class PpapiThread : public ChildThread {
virtual bool OnMessageReceived(const IPC::Message& msg);
// Message handlers.
- void OnMsgLoadPlugin(base::ProcessHandle renderer_handle,
- const FilePath& path,
- int renderer_id);
-
- bool LoadPluginLib(base::ProcessHandle host_process_handle,
- const FilePath& path);
+ 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(int renderer_id,
+ bool SetupRendererChannel(base::ProcessHandle host_process_handle,
+ int renderer_id,
IPC::ChannelHandle* handle);
-#if defined(OS_POSIX)
- // Close the plugin process' copy of the renderer's side of the plugin
- // channel. This can be called after the renderer is known to have its own
- // copy of renderer_fd_.
- void CloseRendererFD();
-#endif
-
base::ScopedNativeLibrary library_;
- scoped_ptr<pp::proxy::PluginDispatcher> dispatcher_;
+ pp::proxy::Dispatcher::GetInterfaceFunc get_plugin_interface_;
-#if defined(OS_POSIX)
- // FD for the renderer end of the socket. It is closed when the IPC layer
- // indicates that the channel is connected, proving that the renderer has
- // access to its side of the socket.
- int renderer_fd_;
-#endif
+ // 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_;
DISALLOW_COPY_AND_ASSIGN(PpapiThread);
};
diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc
index 87c8625..fd4a2dd 100644
--- a/chrome/renderer/pepper_plugin_delegate_impl.cc
+++ b/chrome/renderer/pepper_plugin_delegate_impl.cc
@@ -365,12 +365,6 @@ bool DispatcherWrapper::Init(
dispatcher_.reset();
return false;
}
-
- if (!dispatcher_->InitializeModule()) {
- // TODO(brettw) does the module get unloaded in this case?
- dispatcher_.reset();
- return false;
- }
return true;
}
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 88df2cb..415dea3 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -5399,16 +5399,21 @@ const PPB_OpenGLES2_Dev* PPB_OpenGLES_Impl::GetInterface() {
func.MakeOriginalArgString("")))
file.Write("}\n\n")
- file.Write("const struct PPB_OpenGLES2_Dev ppb_opengles2 = {\n")
+ file.Write("const struct PPB_OpenGLES2_Dev opengles2_interface = {\n")
file.Write(" &")
file.Write(",\n &".join(
f.name for f in self.original_functions if f.IsCoreGLFunction()))
file.Write("\n")
file.Write("};\n\n")
- file.Write("} // namespace\n")
-
file.Write("""
+InterfaceProxy* CreateOpenGLES2Proxy(Dispatcher* dispatcher,
+ const void* target_interface) {
+ return new PPB_OpenGLES2_Proxy(dispatcher, target_interface);
+}
+
+} // namespace
+
PPB_OpenGLES2_Proxy::PPB_OpenGLES2_Proxy(Dispatcher* dispatcher,
const void* target_interface)
: InterfaceProxy(dispatcher, target_interface) {
@@ -5417,12 +5422,16 @@ PPB_OpenGLES2_Proxy::PPB_OpenGLES2_Proxy(Dispatcher* dispatcher,
PPB_OpenGLES2_Proxy::~PPB_OpenGLES2_Proxy() {
}
-const void* PPB_OpenGLES2_Proxy::GetSourceInterface() const {
- return &ppb_opengles2;
-}
-
-InterfaceID PPB_OpenGLES2_Proxy::GetInterfaceId() const {
- return INTERFACE_ID_NONE;
+// static
+const InterfaceProxy::Info* PPB_OpenGLES2_Proxy::GetInfo() {
+ static const Info info = {
+ &opengles2_interface,
+ PPB_OPENGLES2_DEV_INTERFACE,
+ INTERFACE_ID_PPB_OPENGLES2,
+ false,
+ &CreateOpenGLES2Proxy,
+ };
+ return &info;
}
bool PPB_OpenGLES2_Proxy::OnMessageReceived(const IPC::Message& msg) {
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h
index 13cf792..953b22d 100644
--- a/gpu/command_buffer/client/gles2_c_lib_autogen.h
+++ b/gpu/command_buffer/client/gles2_c_lib_autogen.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.
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
index e69b7ee..2dc0687 100644
--- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
+++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.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.
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h
index 0b27f6c..a8fcfa0 100644
--- a/gpu/command_buffer/client/gles2_implementation_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_autogen.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.
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
index 22fb23a..8a37edb 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.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.
diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
index e62ca7c..fcada01 100644
--- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.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.
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
index fafbada..f4e0e9e 100644
--- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.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.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 60bf9ed..78bf68d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.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.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
index cd4c33d..0607a02 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.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.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index 7549fa9e..50715df 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.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.
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
index c528c1b..46da61e 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.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.
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
index 6a81894..f4ef6d8 100644
--- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.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.
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc
index 7978786..fce2b13 100644
--- a/ppapi/proxy/host_dispatcher.cc
+++ b/ppapi/proxy/host_dispatcher.cc
@@ -36,14 +36,6 @@ HostDispatcher::HostDispatcher(base::ProcessHandle remote_process_handle,
}
HostDispatcher::~HostDispatcher() {
- // Notify the plugin that it should exit.
- Send(new PpapiMsg_Shutdown());
-}
-
-bool HostDispatcher::InitializeModule() {
- bool init_result = false;
- Send(new PpapiMsg_InitializeModule(pp_module(), &init_result));
- return init_result;
}
// static
@@ -116,6 +108,10 @@ bool HostDispatcher::OnMessageReceived(const IPC::Message& msg) {
return proxy->OnMessageReceived(msg);
}
+void HostDispatcher::OnChannelError() {
+ // TODO(brettw) plugin has crashed, handle this.
+}
+
const void* HostDispatcher::GetProxiedInterface(const std::string& interface) {
// First see if we even have a proxy for this interface.
const InterfaceProxy::Info* info = GetPPPInterfaceInfo(interface);
diff --git a/ppapi/proxy/host_dispatcher.h b/ppapi/proxy/host_dispatcher.h
index f405f71..e38fca6 100644
--- a/ppapi/proxy/host_dispatcher.h
+++ b/ppapi/proxy/host_dispatcher.h
@@ -48,15 +48,12 @@ class HostDispatcher : public Dispatcher {
HostDispatcher* dispatcher);
static void RemoveForInstance(PP_Instance instance);
- // Calls the plugin's PPP_InitializeModule function and returns true if
- // the call succeeded.
- bool InitializeModule();
-
// Dispatcher overrides.
virtual bool IsPlugin() const;
// IPC::Channel::Listener.
virtual bool OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelError();
// Proxied version of calling GetInterface on the plugin. This will check
// if the plugin supports the given interface (with caching) and returns the
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
index b30f6da..1f4454c 100644
--- a/ppapi/proxy/plugin_dispatcher.cc
+++ b/ppapi/proxy/plugin_dispatcher.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.
@@ -16,6 +16,11 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/ppp_class_proxy.h"
+#if defined(OS_POSIX)
+#include "base/eintr_wrapper.h"
+#include "ipc/ipc_channel_posix.h"
+#endif
+
namespace pp {
namespace proxy {
@@ -24,23 +29,15 @@ namespace {
typedef std::map<PP_Instance, PluginDispatcher*> InstanceToDispatcherMap;
InstanceToDispatcherMap* g_instance_to_dispatcher = NULL;
-const void* GetInterfaceFromDispatcher(const char* interface) {
- // All interfaces the plugin requests of the browser are "PPB".
- const InterfaceProxy::Info* info = Dispatcher::GetPPBInterfaceInfo(interface);
- if (!info)
- return NULL;
- return info->interface;
-}
-
} // namespace
PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
- GetInterfaceFunc get_interface,
- InitModuleFunc init_module,
- ShutdownModuleFunc shutdown_module)
- : Dispatcher(remote_process_handle, get_interface),
- init_module_(init_module),
- shutdown_module_(shutdown_module) {
+ GetInterfaceFunc get_interface)
+ : Dispatcher(remote_process_handle, get_interface)
+#if defined(OS_POSIX)
+ , renderer_fd_(-1)
+#endif
+ {
SetSerializationRules(new PluginVarSerializationRules);
// As a plugin, we always support the PPP_Class interface. There's no
@@ -49,8 +46,9 @@ PluginDispatcher::PluginDispatcher(base::ProcessHandle remote_process_handle,
}
PluginDispatcher::~PluginDispatcher() {
- if (shutdown_module_)
- shutdown_module_();
+#if defined(OS_POSIX)
+ CloseRendererFD();
+#endif
}
// static
@@ -64,6 +62,16 @@ PluginDispatcher* PluginDispatcher::GetForInstance(PP_Instance instance) {
return found->second;
}
+// static
+const void* PluginDispatcher::GetInterfaceFromDispatcher(
+ const char* interface) {
+ // All interfaces the plugin requests of the browser are "PPB".
+ const InterfaceProxy::Info* info = GetPPBInterfaceInfo(interface);
+ if (!info)
+ return NULL;
+ return info->interface;
+}
+
bool PluginDispatcher::IsPlugin() const {
return true;
}
@@ -78,8 +86,6 @@ bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PluginDispatcher, msg)
IPC_MESSAGE_HANDLER(PpapiMsg_SupportsInterface, OnMsgSupportsInterface)
- IPC_MESSAGE_HANDLER(PpapiMsg_InitializeModule, OnMsgInitializeModule)
- IPC_MESSAGE_HANDLER(PpapiMsg_Shutdown, OnMsgShutdown)
IPC_END_MESSAGE_MAP()
return handled;
}
@@ -122,6 +128,14 @@ bool PluginDispatcher::OnMessageReceived(const IPC::Message& msg) {
return proxy->OnMessageReceived(msg);
}
+void PluginDispatcher::OnChannelError() {
+ // The renderer has crashed. This channel and all instances associated with
+ // it are no longer valid.
+ ForceFreeAllInstances();
+ // TODO(brettw) free resources too!
+ delete this;
+}
+
void PluginDispatcher::DidCreateInstance(PP_Instance instance) {
if (!g_instance_to_dispatcher)
g_instance_to_dispatcher = new InstanceToDispatcherMap;
@@ -152,16 +166,24 @@ InstanceData* PluginDispatcher::GetInstanceData(PP_Instance instance) {
return (it == instance_map_.end()) ? NULL : &it->second;
}
-void PluginDispatcher::OnMsgInitializeModule(PP_Module pp_module,
- bool* result) {
- set_pp_module(pp_module);
- *result = init_module_(pp_module, &GetInterfaceFromDispatcher) == PP_OK;
+#if defined(OS_POSIX)
+int PluginDispatcher::GetRendererFD() {
+ if (renderer_fd_ == -1)
+ renderer_fd_ = channel()->GetClientFileDescriptor();
+ return renderer_fd_;
+}
+
+void PluginDispatcher::CloseRendererFD() {
+ if (renderer_fd_ != -1) {
+ if (HANDLE_EINTR(close(renderer_fd_)) < 0)
+ PLOG(ERROR) << "close";
+ renderer_fd_ = -1;
+ }
}
+#endif
-void PluginDispatcher::OnMsgShutdown() {
- if (shutdown_module_)
- shutdown_module_();
- MessageLoop::current()->Quit();
+void PluginDispatcher::ForceFreeAllInstances() {
+ // TODO(brettw) implement freeing instances on crash.
}
void PluginDispatcher::OnMsgSupportsInterface(
diff --git a/ppapi/proxy/plugin_dispatcher.h b/ppapi/proxy/plugin_dispatcher.h
index 8f27ac0..0b219f4 100644
--- a/ppapi/proxy/plugin_dispatcher.h
+++ b/ppapi/proxy/plugin_dispatcher.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.
@@ -10,6 +10,7 @@
#include "base/hash_tables.h"
#include "base/process.h"
#include "base/scoped_ptr.h"
+#include "build/build_config.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/proxy/dispatcher.h"
@@ -36,9 +37,7 @@ class PluginDispatcher : public Dispatcher {
//
// You must call Dispatcher::InitWithChannel after the constructor.
PluginDispatcher(base::ProcessHandle remote_process_handle,
- GetInterfaceFunc get_interface,
- InitModuleFunc init_module,
- ShutdownModuleFunc shutdown_module);
+ GetInterfaceFunc get_interface);
~PluginDispatcher();
// The plugin side maintains a mapping from PP_Instance to Dispatcher so
@@ -47,11 +46,14 @@ class PluginDispatcher : public Dispatcher {
// DidCreateInstance/DidDestroyInstance.
static PluginDispatcher* GetForInstance(PP_Instance instance);
+ static const void* GetInterfaceFromDispatcher(const char* interface);
+
// Dispatcher overrides.
virtual bool IsPlugin() const;
// IPC::Channel::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelError();
// Keeps track of which dispatcher to use for each instance, active instances
// and tracks associated data like the current size.
@@ -62,16 +64,28 @@ class PluginDispatcher : public Dispatcher {
// correspond to a known instance.
InstanceData* GetInstanceData(PP_Instance instance);
+#if defined(OS_POSIX)
+ // See renderer_fd_ below.
+ int GetRendererFD();
+ void CloseRendererFD();
+#endif
+
private:
friend class PluginDispatcherTest;
+ // Notifies all live instances that they're now closed. This is used when
+ // a renderer crashes or some other error is received.
+ void ForceFreeAllInstances();
+
// IPC message handlers.
- void OnMsgInitializeModule(PP_Module pp_module, bool* result);
- void OnMsgShutdown();
void OnMsgSupportsInterface(const std::string& interface_name, bool* result);
- InitModuleFunc init_module_;
- ShutdownModuleFunc shutdown_module_;
+#if defined(OS_POSIX)
+ // FD for the renderer end of the socket. It is closed when the IPC layer
+ // indicates that the channel is connected, proving that the renderer has
+ // access to its side of the socket.
+ int renderer_fd_;
+#endif
// All target proxies currently created. These are ones that receive
// messages.
diff --git a/ppapi/proxy/ppapi_messages_internal.h b/ppapi/proxy/ppapi_messages_internal.h
index b181b2e..7cab708 100644
--- a/ppapi/proxy/ppapi_messages_internal.h
+++ b/ppapi/proxy/ppapi_messages_internal.h
@@ -12,16 +12,13 @@
// These are from the plugin to the renderer
// Loads the given plugin.
-IPC_MESSAGE_CONTROL3(PpapiMsg_LoadPlugin,
- base::ProcessHandle /* host_process_handle */,
- FilePath /* path */,
- int /* renderer_id */)
-
-IPC_SYNC_MESSAGE_CONTROL1_1(PpapiMsg_InitializeModule,
- PP_Module /* module_id */,
- bool /* result */)
+IPC_MESSAGE_CONTROL1(PpapiMsg_LoadPlugin, FilePath /* path */)
-IPC_MESSAGE_CONTROL0(PpapiMsg_Shutdown)
+// Creates a channel to talk to a renderer. The plugin will respond with
+// PpapiHostMsg_ChannelCreated.
+IPC_MESSAGE_CONTROL2(PpapiMsg_CreateChannel,
+ base::ProcessHandle /* host_process_handle */,
+ int /* renderer_id */);
// Sent in both directions to see if the other side supports the given
// interface.
@@ -152,8 +149,12 @@ IPC_MESSAGE_ROUTED3(PpapiMsg_PPBURLLoader_ReadResponseBody_Ack,
// -----------------------------------------------------------------------------
// These are from the plugin to the renderer.
-// Reply to PpapiMsg_LoadPlugin.
-IPC_MESSAGE_CONTROL1(PpapiHostMsg_PluginLoaded,
+
+// Reply to PpapiMsg_CreateChannel. The handle will be NULL if the channel
+// could not be established. This could be because the IPC could not be created
+// for some weird reason, but more likely that the plugin failed to load or
+// initialize properly.
+IPC_MESSAGE_CONTROL1(PpapiHostMsg_ChannelCreated,
IPC::ChannelHandle /* handle */)
// PPB_Audio.
diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc
index 1b75001..fffb20c 100644
--- a/ppapi/proxy/ppapi_proxy_test.cc
+++ b/ppapi/proxy/ppapi_proxy_test.cc
@@ -94,9 +94,7 @@ void PluginProxyTest::SetUp() {
plugin_dispatcher_.reset(new PluginDispatcher(
base::Process::Current().handle(),
- &MockGetInterface,
- &MockInitModule,
- &MockShutdownModuleFunc));
+ &MockGetInterface));
plugin_dispatcher_->InitWithTestSink(&sink());
plugin_dispatcher_->DidCreateInstance(pp_instance());
}