From 76724d00d3498f952d945d775a3f33f751624121 Mon Sep 17 00:00:00 2001 From: "evan@chromium.org" Date: Sat, 20 Jun 2009 03:10:51 +0000 Subject: posix: two related changes to make plugin IPC work on POSIX. [retry, fix windows compile failure] * use a new ChannelHandle type when passing IPC channels over IPC The current POSIX code assumes that one end of a channel is always a new child process (a renderer). For plugins we need to be able to construct channels between each of the browser, plugin, and renderer. This change augments the messages related to creating channels to allow passing in a base::FileDescriptor containing the socket. The intent is that the browser process, as the initial interchange between plugin and renderer, creates the socketpair() on their behalf and hands each their respective end of the connection. * register channel endpoint names in the global pipe map The plugin code assumes it can map from a string to a channel endpoint at basically any time. So whenever we get a channel endpoint over IPC, we install it in a global map of channel endpoints. Review URL: http://codereview.chromium.org/113157 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18888 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/plugin_process_host.cc | 50 +++++++++++-- chrome/browser/plugin_process_host.h | 10 ++- chrome/browser/plugin_service.cc | 2 +- .../renderer_host/resource_message_filter.cc | 2 +- chrome/chrome.gyp | 1 + chrome/common/ipc_channel_handle.h | 45 +++++++++++ chrome/common/ipc_channel_posix.cc | 87 ++++++++++++++-------- chrome/common/ipc_channel_posix.h | 18 ++++- chrome/common/ipc_message_utils.h | 29 ++++++++ chrome/common/plugin_messages_internal.h | 15 ++++ chrome/common/render_messages_internal.h | 11 +-- chrome/plugin/plugin_channel.cc | 14 +++- chrome/plugin/plugin_channel.h | 8 +- chrome/plugin/plugin_thread.cc | 13 +++- chrome/plugin/plugin_thread.h | 14 +++- chrome/plugin/webplugin_delegate_stub.cc | 6 +- chrome/renderer/webplugin_delegate_proxy.cc | 18 ++++- 17 files changed, 283 insertions(+), 60 deletions(-) create mode 100644 chrome/common/ipc_channel_handle.h diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index 5216755..e704a5f 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -40,6 +40,7 @@ #include "chrome/common/logging_chrome.h" #include "chrome/common/plugin_messages.h" #include "chrome/common/render_messages.h" +#include "chrome/common/ipc_channel_handle.h" #include "net/base/cookie_monster.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" @@ -53,6 +54,10 @@ #include "sandbox/src/sandbox.h" #endif +#if defined(OS_POSIX) +#include "chrome/common/ipc_channel_posix.h" +#endif + static const char kDefaultPluginFinderURL[] = "http://dl.google.com/chrome/plugins/plugins2.xml"; @@ -454,7 +459,7 @@ void PluginProcessHost::OnChannelConnected(int32 peer_pid) { void PluginProcessHost::OnChannelError() { for (size_t i = 0; i < pending_requests_.size(); ++i) { ReplyToRenderer(pending_requests_[i].renderer_message_filter_.get(), - std::string(), + IPC::ChannelHandle(), FilePath(), pending_requests_[i].reply_msg); } @@ -468,8 +473,17 @@ void PluginProcessHost::OpenChannelToPlugin( IPC::Message* reply_msg) { InstanceCreated(); 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. + // + // On POSIX, we'll only create the pipe when we get around to actually + // making this request. So the socket fd is -1 for now. (On Windows, + // socket_fd is unused.) + int socket_fd = -1; pending_requests_.push_back( - ChannelRequest(renderer_message_filter, mime_type, reply_msg)); + ChannelRequest(renderer_message_filter, mime_type, reply_msg, + socket_fd)); return; } @@ -506,7 +520,8 @@ void PluginProcessHost::OnResolveProxyCompleted(IPC::Message* reply_msg, void PluginProcessHost::ReplyToRenderer( ResourceMessageFilter* renderer_message_filter, - const std::string& channel, const FilePath& plugin_path, + const IPC::ChannelHandle& channel, + const FilePath& plugin_path, IPC::Message* reply_msg) { ViewHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg, channel, plugin_path); @@ -522,29 +537,48 @@ URLRequestContext* PluginProcessHost::GetRequestContext( void PluginProcessHost::RequestPluginChannel( ResourceMessageFilter* renderer_message_filter, const std::string& mime_type, IPC::Message* reply_msg) { + // We're about to send the request for a plugin channel. + // On POSIX, we create the channel endpoints here, so we can send the + // endpoints to the plugin and renderer. + int plugin_fd = -1, renderer_fd = -1; +#if defined(OS_POSIX) + // On POSIX, we create the channel endpoints here. + IPC::SocketPair(&plugin_fd, &renderer_fd); +#endif + // We can't send any sync messages from the browser because it might lead to // a hang. However this async messages must be answered right away by the // plugin process (i.e. unblocks a Send() call like a sync message) otherwise // a deadlock can occur if the plugin creation request from the renderer is // a result of a sync message by the plugin process. PluginProcessMsg_CreateChannel* msg = new PluginProcessMsg_CreateChannel( +#if defined(OS_POSIX) + // Takes ownership of plugin_fd. + base::FileDescriptor(plugin_fd, true), +#endif renderer_message_filter->GetProcessId(), renderer_message_filter->off_the_record()); msg->set_unblock(true); if (Send(msg)) { sent_requests_.push(ChannelRequest( - renderer_message_filter, mime_type, reply_msg)); + renderer_message_filter, mime_type, reply_msg, renderer_fd)); } else { - ReplyToRenderer(renderer_message_filter, std::string(), FilePath(), + ReplyToRenderer(renderer_message_filter, IPC::ChannelHandle(), FilePath(), reply_msg); } } void PluginProcessHost::OnChannelCreated(const std::string& channel_name) { - ReplyToRenderer(sent_requests_.front().renderer_message_filter_.get(), - channel_name, + const ChannelRequest& request = sent_requests_.front(); + IPC::ChannelHandle channel_handle(channel_name +#if defined(OS_POSIX) + , base::FileDescriptor(request.socket, true) +#endif + ); + ReplyToRenderer(request.renderer_message_filter_.get(), + channel_handle, info_.path, - sent_requests_.front().reply_msg); + request.reply_msg); sent_requests_.pop(); } diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h index 56004f6..9a74dff 100644 --- a/chrome/browser/plugin_process_host.h +++ b/chrome/browser/plugin_process_host.h @@ -18,6 +18,7 @@ #include "chrome/browser/net/resolve_proxy_msg_helper.h" #include "chrome/browser/renderer_host/resource_message_filter.h" #include "chrome/common/child_process_host.h" +#include "chrome/common/ipc_channel_handle.h" #include "webkit/glue/webplugininfo.h" class URLRequestContext; @@ -65,7 +66,7 @@ class PluginProcessHost : public ChildProcessHost, // Sends the reply to an open channel request to the renderer with the given // channel name. static void ReplyToRenderer(ResourceMessageFilter* renderer_message_filter, - const std::string& channel, + const IPC::ChannelHandle& channel, const FilePath& plugin_path, IPC::Message* reply_msg); @@ -113,12 +114,15 @@ class PluginProcessHost : public ChildProcessHost, struct ChannelRequest { ChannelRequest(ResourceMessageFilter* renderer_message_filter, - const std::string& m, IPC::Message* r) : + const std::string& m, IPC::Message* r, + int s) : mime_type(m), reply_msg(r), - renderer_message_filter_(renderer_message_filter) { } + renderer_message_filter_(renderer_message_filter), + socket(s) { } std::string mime_type; IPC::Message* reply_msg; scoped_refptr renderer_message_filter_; + int socket; }; // These are channel requests that we are waiting to send to the diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index 773698a..c49d56d 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -167,7 +167,7 @@ void PluginService::OpenChannelToPlugin( plugin_host->OpenChannelToPlugin(renderer_msg_filter, mime_type, reply_msg); } else { PluginProcessHost::ReplyToRenderer(renderer_msg_filter, - std::string(), + IPC::ChannelHandle(), FilePath(), reply_msg); } diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 2121378..4728b17 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -176,7 +176,7 @@ void ResourceMessageFilter::OnFilterAdded(IPC::Channel* channel) { // Called on the IPC thread: void ResourceMessageFilter::OnChannelConnected(int32 peer_pid) { - DCHECK(!handle()); + DCHECK(!handle()) << " " << handle(); base::ProcessHandle peer_handle; if (!base::OpenProcessHandle(peer_pid, &peer_handle)) { NOTREACHED(); diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index bace7a5f..346986f 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -347,6 +347,7 @@ 'common/important_file_writer.cc', 'common/important_file_writer.h', 'common/ipc_channel.h', + 'common/ipc_channel_handle.h', 'common/ipc_channel_posix.cc', 'common/ipc_channel_posix.h', 'common/ipc_channel_proxy.cc', diff --git a/chrome/common/ipc_channel_handle.h b/chrome/common/ipc_channel_handle.h new file mode 100644 index 0000000..2bb6380 --- /dev/null +++ b/chrome/common/ipc_channel_handle.h @@ -0,0 +1,45 @@ +// Copyright (c) 2009 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 CHROME_COMMON_IPC_CHANNEL_HANDLE_H_ +#define CHROME_COMMON_IPC_CHANNEL_HANDLE_H_ + +#include "build/build_config.h" + +#if defined(OS_POSIX) +#include "base/file_descriptor_posix.h" +#endif + +// On Windows, any process can create an IPC channel and others can fetch +// it by name. We pass around the channel names over IPC. +// On POSIX, we instead pass around handles to channel endpoints via IPC. +// When it's time to IPC a new channel endpoint around, we send both the +// channel name as well as a base::FileDescriptor, which is itself a special +// type that knows how to copy a socket endpoint over IPC. +// +// In sum, when passing a handle to a channel over IPC, use this data structure +// to work on both Windows and POSIX. + +namespace IPC { + +struct ChannelHandle { + // Note that serialization for this object is defined in the ParamTraits + // template specialization in ipc_message_utils.h. + std::string name; +#if defined(OS_POSIX) + base::FileDescriptor socket; +#endif + + ChannelHandle() {} +#if defined(OS_POSIX) + ChannelHandle(const std::string& n, const base::FileDescriptor& s) + : name(n), socket(s) {} +#else + ChannelHandle(const std::string& n) : name(n) {} +#endif +}; + +} // namespace IPC + +#endif // CHROME_COMMON_IPC_CHANNEL_HANDLE_H_ diff --git a/chrome/common/ipc_channel_posix.cc b/chrome/common/ipc_channel_posix.cc index babc16c..63f2703 100644 --- a/chrome/common/ipc_channel_posix.cc +++ b/chrome/common/ipc_channel_posix.cc @@ -104,9 +104,9 @@ class PipeMap { DCHECK(fd != -1); ChannelToFDMap::const_iterator i = map_.find(channel_id); - CHECK(i == map_.end()) << "Creating second IPC server for '" - << channel_id - << "' while first still exists"; + CHECK(i == map_.end()) << "Creating second IPC server (fd " << fd << ") " + << "for '" << channel_id << "' while first " + << "(fd " << i->second << ") still exists"; map_[channel_id] = fd; } @@ -116,16 +116,20 @@ class PipeMap { ChannelToFDMap map_; }; -// Used to map a channel name to the equivalent FD # in the client process. -int ChannelNameToClientFD(const std::string& channel_id) { +// Used to map a channel name to the equivalent FD # in the current process. +// Returns -1 if the channel is unknown. +int ChannelNameToFD(const std::string& channel_id) { // See the large block comment above PipeMap for the reasoning here. const int fd = Singleton()->Lookup(channel_id); - if (fd != -1) - return dup(fd); - // If we don't find an entry, we assume that the correct value has been - // inserted in the magic slot. - return Singleton()->Get(kPrimaryIPCChannel); + if (fd != -1) { + int dup_fd = dup(fd); + if (dup_fd < 0) + LOG(FATAL) << "dup(" << fd << "): " << strerror(errno); + return dup_fd; + } + + return fd; } //------------------------------------------------------------------------------ @@ -261,6 +265,34 @@ Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, } } +// static +void AddChannelSocket(const std::string& name, int socket) { + Singleton()->Insert(name, socket); +} + +// static +bool SocketPair(int* fd1, int* fd2) { + int pipe_fds[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) { + LOG(ERROR) << "socketpair(): " << strerror(errno); + return false; + } + + // Set both ends to be non-blocking. + if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 || + fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) { + LOG(ERROR) << "fcntl(O_NONBLOCK): " << strerror(errno); + HANDLE_EINTR(close(pipe_fds[0])); + HANDLE_EINTR(close(pipe_fds[1])); + return false; + } + + *fd1 = pipe_fds[0]; + *fd2 = pipe_fds[1]; + + return true; +} + bool Channel::ChannelImpl::CreatePipe(const std::string& channel_id, Mode mode) { DCHECK(server_listen_pipe_ == -1 && pipe_ == -1); @@ -282,27 +314,24 @@ bool Channel::ChannelImpl::CreatePipe(const std::string& channel_id, waiting_connect_ = false; } } else { - // socketpair() + // This is the normal (non-unit-test) case, where we're using sockets. + // Three possible cases: + // 1) It's for a channel we already have a pipe for; reuse it. + // 2) It's the initial IPC channel: + // 2a) Server side: create the pipe. + // 2b) Client side: Pull the pipe out of the GlobalDescriptors set. pipe_name_ = channel_id; - if (mode == MODE_SERVER) { - int pipe_fds[2]; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipe_fds) != 0) { - return false; - } - // Set both ends to be non-blocking. - if (fcntl(pipe_fds[0], F_SETFL, O_NONBLOCK) == -1 || - fcntl(pipe_fds[1], F_SETFL, O_NONBLOCK) == -1) { - HANDLE_EINTR(close(pipe_fds[0])); - HANDLE_EINTR(close(pipe_fds[1])); - return false; + pipe_ = ChannelNameToFD(pipe_name_); + if (pipe_ < 0) { + // Initial IPC channel. + if (mode == MODE_SERVER) { + if (!SocketPair(&pipe_, &client_pipe_)) + return false; + AddChannelSocket(pipe_name_, client_pipe_); + } else { + pipe_ = Singleton()->Get(kPrimaryIPCChannel); } - pipe_ = pipe_fds[0]; - client_pipe_ = pipe_fds[1]; - - Singleton()->Insert(pipe_name_, client_pipe_); } else { - pipe_ = ChannelNameToClientFD(pipe_name_); - DCHECK(pipe_ > 0); waiting_connect_ = false; } } @@ -612,7 +641,7 @@ bool Channel::ChannelImpl::ProcessOutgoingMessages() { return false; } #endif // OS_MACOSX - LOG(ERROR) << "pipe error: " << strerror(errno); + LOG(ERROR) << "pipe error on " << pipe_ << ": " << strerror(errno); return false; } diff --git a/chrome/common/ipc_channel_posix.h b/chrome/common/ipc_channel_posix.h index ed3d727..5e8d977 100644 --- a/chrome/common/ipc_channel_posix.h +++ b/chrome/common/ipc_channel_posix.h @@ -18,6 +18,15 @@ namespace IPC { +// Store that channel name |name| is available via socket |socket|. +// Used when the channel has been precreated by another process on +// our behalf and they've just shipped us the socket. +void AddChannelSocket(const std::string& name, int socket); + +// Construct a socket pair appropriate for IPC: UNIX domain, nonblocking. +// Returns false on error. +bool SocketPair(int* fd1, int* fd2); + // An implementation of ChannelImpl for POSIX systems that works via // socketpairs. See the .cc file for an overview of the implementation. class Channel::ChannelImpl : public MessageLoopForIO::Watcher { @@ -60,9 +69,16 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher { // a socketpair(). bool uses_fifo_; + // File descriptor we're listening on for new connections in the FIFO case; + // unused otherwise. int server_listen_pipe_; + + // The pipe used for communication. int pipe_; - int client_pipe_; // The client end of our socketpair(). + + // For a server, the client end of our socketpair() -- the other end of our + // pipe_ that is passed to the client. + int client_pipe_; // The "name" of our pipe. On Windows this is the global identifier for // the pipe. On POSIX it's used as a key in a local map of file descriptors. diff --git a/chrome/common/ipc_message_utils.h b/chrome/common/ipc_message_utils.h index 3f0f7b2..2ae2ab5 100644 --- a/chrome/common/ipc_message_utils.h +++ b/chrome/common/ipc_message_utils.h @@ -16,6 +16,7 @@ #if defined(OS_POSIX) #include "chrome/common/file_descriptor_set_posix.h" #endif +#include "chrome/common/ipc_channel_handle.h" #include "chrome/common/ipc_sync_message.h" #include "chrome/common/thumbnail_score.h" #include "chrome/common/transport_dib.h" @@ -726,6 +727,34 @@ struct ParamTraits { }; #endif // defined(OS_POSIX) +// A ChannelHandle is basically a platform-inspecific wrapper around the +// fact that IPC endpoints are handled specially on POSIX. See above comments +// on FileDescriptor for more background. +template<> +struct ParamTraits { + typedef ChannelHandle param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, p.name); +#if defined(OS_POSIX) + WriteParam(m, p.socket); +#endif + } + static bool Read(const Message* m, void** iter, param_type* r) { + return ReadParam(m, iter, &r->name) +#if defined(OS_POSIX) + && ReadParam(m, iter, &r->socket) +#endif + ; + } + static void Log(const param_type& p, std::wstring* l) { + l->append(StringPrintf(L"ChannelHandle(%s", p.name.c_str())); +#if defined(OS_POSIX) + ParamTraits::Log(p.socket, l); +#endif + l->append(L")"); + } +}; + template<> struct ParamTraits { typedef ThumbnailScore param_type; diff --git a/chrome/common/plugin_messages_internal.h b/chrome/common/plugin_messages_internal.h index b2805fc..500bd93 100644 --- a/chrome/common/plugin_messages_internal.h +++ b/chrome/common/plugin_messages_internal.h @@ -3,9 +3,14 @@ // found in the LICENSE file. #include "base/shared_memory.h" +#include "build/build_config.h" #include "chrome/common/ipc_message_macros.h" #include "webkit/glue/webcursor.h" +#if defined(OS_POSIX) +#include "base/file_descriptor_posix.h" +#endif + //----------------------------------------------------------------------------- // PluginProcess messages // These are messages sent from the browser to the plugin process. @@ -15,9 +20,19 @@ IPC_BEGIN_MESSAGES(PluginProcess) // PluginProcessHostMsg_ChannelCreated message. The renderer's process_id is // passed so that the plugin process reuses an existing channel to that // process if it exists. + // It would be nice to use #ifdefs inside the parameter list to not need to + // duplicate this across POSIX/Windows but the Visual Studio compiler doesn't + // like that. +#if defined(OS_WIN) IPC_MESSAGE_CONTROL2(PluginProcessMsg_CreateChannel, int /* process_id */, bool /* off_the_record */) +#elif defined(OS_POSIX) + IPC_MESSAGE_CONTROL3(PluginProcessMsg_CreateChannel, + base::FileDescriptor /* socket for new channel */, + int /* process_id */, + bool /* off_the_record */) +#endif // Allows a chrome plugin loaded in the browser process to send arbitrary // data to an instance of the same plugin loaded in a plugin process. diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index d96220d..5debd5f 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -17,6 +17,7 @@ #include "base/gfx/native_widget_types.h" #include "base/shared_memory.h" #include "base/values.h" +#include "chrome/common/ipc_channel_handle.h" #include "chrome/common/ipc_message_macros.h" #include "chrome/common/transport_dib.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -924,16 +925,16 @@ IPC_BEGIN_MESSAGES(ViewHost) std::string /* origin */, std::string /* target */) - // A renderer sends this to the browser process when it wants to create a - // plugin. The browser will create the plugin process if necessary, and - // will return the channel name on success. On error an empty string is - // returned. + // A renderer sends this to the browser process when it wants to + // create a 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_CONTROL4_2(ViewHostMsg_OpenChannelToPlugin, GURL /* url */, std::string /* mime_type */, std::string /* clsid */, std::wstring /* locale */, - std::string /* channel_name */, + IPC::ChannelHandle /* handle to channel */, FilePath /* plugin_path */) // Clipboard IPC messages diff --git a/chrome/plugin/plugin_channel.cc b/chrome/plugin/plugin_channel.cc index 4ff7b2b..b9e7a52 100644 --- a/chrome/plugin/plugin_channel.cc +++ b/chrome/plugin/plugin_channel.cc @@ -7,17 +7,29 @@ #include "base/command_line.h" #include "base/process_util.h" #include "base/string_util.h" +#include "build/build_config.h" #include "chrome/common/child_process.h" #include "chrome/common/plugin_messages.h" #include "chrome/common/chrome_switches.h" #include "chrome/plugin/plugin_thread.h" +#if defined(OS_POSIX) +#include "chrome/common/ipc_channel_posix.h" +#endif + PluginChannel* PluginChannel::GetPluginChannel( - int process_id, MessageLoop* ipc_message_loop) { + int process_id, MessageLoop* ipc_message_loop, int channel_fd) { // map renderer's process id to a (single) channel to that process std::string channel_name = StringPrintf( "%d.r%d", base::GetCurrentProcId(), process_id); +#if defined(OS_POSIX) + // If we were provided an already-open channel, associate it with + // the channel name in this process's name<->socket map. + if (channel_fd > 0) + IPC::AddChannelSocket(channel_name, channel_fd); +#endif + return static_cast(PluginChannelBase::GetChannel( channel_name, IPC::Channel::MODE_SERVER, diff --git a/chrome/plugin/plugin_channel.h b/chrome/plugin/plugin_channel.h index f0bba80..21373fb 100644 --- a/chrome/plugin/plugin_channel.h +++ b/chrome/plugin/plugin_channel.h @@ -15,8 +15,12 @@ // process. On the renderer side there's a corresponding PluginChannelHost. class PluginChannel : public PluginChannelBase { public: - static PluginChannel* GetPluginChannel( - int process_id, MessageLoop* ipc_message_loop); + // Get a new PluginChannel object for the current process. + // POSIX only: If |channel_fd| > 0, use that file descriptor for the + // channel socket. + static PluginChannel* GetPluginChannel(int process_id, + MessageLoop* ipc_message_loop, + int channel_fd); ~PluginChannel(); diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc index cb92de4..2f9c2ec 100644 --- a/chrome/plugin/plugin_thread.cc +++ b/chrome/plugin/plugin_thread.cc @@ -102,10 +102,19 @@ void PluginThread::CleanUp() { lazy_tls.Pointer()->Set(NULL); } -void PluginThread::OnCreateChannel(int process_id, bool off_the_record) { +void PluginThread::OnCreateChannel( +#if defined(OS_POSIX) + base::FileDescriptor socket, +#endif + int process_id, + bool off_the_record) { + int fd = -1; +#if defined(OS_POSIX) + fd = socket.fd; +#endif std::string channel_name; scoped_refptr channel = - PluginChannel::GetPluginChannel(process_id, owner_loop()); + PluginChannel::GetPluginChannel(process_id, owner_loop(), fd); if (channel.get()) { channel_name = channel->channel_name(); channel->set_off_the_record(off_the_record); diff --git a/chrome/plugin/plugin_thread.h b/chrome/plugin/plugin_thread.h index 052be0a..911940a 100644 --- a/chrome/plugin/plugin_thread.h +++ b/chrome/plugin/plugin_thread.h @@ -7,10 +7,15 @@ #include "base/file_path.h" #include "base/native_library.h" +#include "build/build_config.h" #include "chrome/common/child_thread.h" #include "chrome/plugin/plugin_channel.h" #include "webkit/glue/plugins/plugin_lib.h" +#if defined(OS_POSIX) +#include "base/file_descriptor_posix.h" +#endif + class NotificationService; // The PluginThread class represents a background thread where plugin instances @@ -31,7 +36,14 @@ class PluginThread : public ChildThread { virtual void Init(); virtual void CleanUp(); - void OnCreateChannel(int process_id, bool off_the_record); + // Callback for when a channel has been created. + // On POSIX, |socket| is the channel endpoint socket. + void OnCreateChannel( +#if defined(OS_POSIX) + base::FileDescriptor socket, +#endif + int process_id, + bool off_the_record); void OnPluginMessage(const std::vector &data); scoped_ptr notification_service_; diff --git a/chrome/plugin/webplugin_delegate_stub.cc b/chrome/plugin/webplugin_delegate_stub.cc index 800db41..8cc3273 100644 --- a/chrome/plugin/webplugin_delegate_stub.cc +++ b/chrome/plugin/webplugin_delegate_stub.cc @@ -135,9 +135,9 @@ void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params, delegate_ = WebPluginDelegate::Create( path, mime_type_, gfx::NativeViewFromId(params.containing_window)); #else - // We don't have gfx::NativeViewFromId on Linux - NOTIMPLEMENTED(); - delegate_ = NULL; + NOTIMPLEMENTED() << " need to figure out nativeview id business"; + delegate_ = WebPluginDelegate::Create( + path, mime_type_, NULL); #endif if (delegate_) { diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 87d3ec1..8117acf 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -41,6 +41,10 @@ #include "chrome/common/gfx/emf.h" #endif +#if defined(OS_POSIX) +#include "chrome/common/ipc_channel_posix.h" +#endif + using WebKit::WebInputEvent; using WebKit::WebDragData; using WebKit::WebVector; @@ -207,16 +211,24 @@ bool WebPluginDelegateProxy::Initialize(const GURL& url, char** argn, char** argv, int argc, WebPlugin* plugin, bool load_manually) { - std::string channel_name; + IPC::ChannelHandle channel_handle; FilePath plugin_path; if (!RenderThread::current()->Send(new ViewHostMsg_OpenChannelToPlugin( url, mime_type_, clsid_, webkit_glue::GetWebKitLocale(), - &channel_name, &plugin_path))) + &channel_handle, &plugin_path))) { return false; + } + +#if defined(OS_POSIX) + // If we received a ChannelHandle, register it now. + if (channel_handle.socket.fd >= 0) + IPC::AddChannelSocket(channel_handle.name, channel_handle.socket.fd); +#endif MessageLoop* ipc_message_loop = RenderThread::current()->owner_loop(); scoped_refptr channel_host = - PluginChannelHost::GetPluginChannelHost(channel_name, ipc_message_loop); + PluginChannelHost::GetPluginChannelHost(channel_handle.name, + ipc_message_loop); if (!channel_host.get()) return false; -- cgit v1.1