diff options
author | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-08 19:28:09 +0000 |
---|---|---|
committer | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-08 19:28:09 +0000 |
commit | 42ce94ec8e98df0744cc1dea26b49c084fe185f0 (patch) | |
tree | 8b585da323dc3bbabb3c61a8941aed90e1819648 | |
parent | ade3ef65f389b00a101da5eb18a02b966d354b18 (diff) | |
download | chromium_src-42ce94ec8e98df0744cc1dea26b49c084fe185f0.zip chromium_src-42ce94ec8e98df0744cc1dea26b49c084fe185f0.tar.gz chromium_src-42ce94ec8e98df0744cc1dea26b49c084fe185f0.tar.bz2 |
Convert over to channel handles
This hides some of the internals of the posix channels from users, and gets rid
of several #ifdef POSIX blocks. Generally simplifies usage of channels xplatform.
BUG=none
TEST=build
Review URL: http://codereview.chromium.org/5598010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68621 0039d316-1c4b-4281-b951-d872f2087c98
29 files changed, 143 insertions, 262 deletions
diff --git a/chrome/browser/plugin_data_remover.cc b/chrome/browser/plugin_data_remover.cc index 4415c5f..cdfd5f4 100644 --- a/chrome/browser/plugin_data_remover.cc +++ b/chrome/browser/plugin_data_remover.cc @@ -62,12 +62,7 @@ void PluginDataRemover::SetPluginInfo(const WebPluginInfo& info) { void PluginDataRemover::OnChannelOpened(const IPC::ChannelHandle& handle) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); DCHECK(!channel_); -#if defined(OS_POSIX) - // If we received a ChannelHandle, register it now. - if (handle.socket.fd >= 0) - IPC::AddChannelSocket(handle.name, handle.socket.fd); -#endif - channel_ = new IPC::Channel(handle.name, IPC::Channel::MODE_CLIENT, this); + channel_ = new IPC::Channel(handle, IPC::Channel::MODE_CLIENT, this); if (!channel_->Connect()) { NOTREACHED() << "Couldn't connect to plugin"; SignalDone(); diff --git a/chrome/gpu/gpu_channel.cc b/chrome/gpu/gpu_channel.cc index 9d3ebd3..7741391 100644 --- a/chrome/gpu/gpu_channel.cc +++ b/chrome/gpu/gpu_channel.cc @@ -24,24 +24,12 @@ #endif GpuChannel::GpuChannel(int renderer_id) - : renderer_id_(renderer_id) -#if defined(OS_POSIX) - , renderer_fd_(-1) -#endif -{ + : renderer_id_(renderer_id) { const CommandLine* command_line = CommandLine::ForCurrentProcess(); log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages); } GpuChannel::~GpuChannel() { -#if defined(OS_POSIX) - IPC::RemoveAndCloseChannelSocket(GetChannelName()); - - // If we still have the renderer FD, close it. - if (renderer_fd_ != -1) { - close(renderer_fd_); - } -#endif } void GpuChannel::OnChannelConnected(int32 peer_pid) { @@ -242,15 +230,6 @@ bool GpuChannel::Init() { // Map renderer ID to a (single) channel to that process. std::string channel_name = GetChannelName(); -#if defined(OS_POSIX) - // This gets called when the GpuChannel is initially created. At this - // point, create the socketpair and assign the GPU side FD to the channel - // name. Keep the renderer side FD as a member variable in the PluginChannel - // to be able to transmit it through IPC. - int gpu_fd; - IPC::SocketPair(&gpu_fd, &renderer_fd_); - IPC::AddChannelSocket(channel_name, gpu_fd); -#endif channel_.reset(new IPC::SyncChannel( channel_name, IPC::Channel::MODE_SERVER, this, ChildProcess::current()->io_message_loop(), false, @@ -262,3 +241,14 @@ bool GpuChannel::Init() { std::string GpuChannel::GetChannelName() { return StringPrintf("%d.r%d", base::GetCurrentProcId(), renderer_id_); } + +#if defined(OS_POSIX) +int GpuChannel::GetRendererFileDescriptor() { + int fd = -1; + if (channel_.get()) { + fd = channel_->GetClientFileDescriptor(); + } + return fd; +} +#endif // defined(OS_POSIX) + diff --git a/chrome/gpu/gpu_channel.h b/chrome/gpu/gpu_channel.h index 3d64355..53c0d70 100644 --- a/chrome/gpu/gpu_channel.h +++ b/chrome/gpu/gpu_channel.h @@ -36,22 +36,14 @@ class GpuChannel : public IPC::Channel::Listener, std::string GetChannelName(); +#if defined(OS_POSIX) + int GetRendererFileDescriptor(); +#endif // defined(OS_POSIX) + base::ProcessHandle renderer_handle() const { return renderer_process_.handle(); } -#if defined(OS_POSIX) - // When first created, the GpuChannel gets assigned the file descriptor - // for the renderer. - // After the first time we pass it through the IPC, we don't need it anymore, - // and we close it. At that time, we reset renderer_fd_ to -1. - int DisownRendererFd() { - int value = renderer_fd_; - renderer_fd_ = -1; - return value; - } -#endif - // IPC::Channel::Listener implementation: virtual void OnMessageReceived(const IPC::Message& msg); virtual void OnChannelConnected(int32 peer_pid); @@ -96,12 +88,6 @@ class GpuChannel : public IPC::Channel::Listener, // The id of the renderer who is on the other side of the channel. int renderer_id_; -#if defined(OS_POSIX) - // FD for the renderer end of the pipe. It is stored until we send it over - // IPC after which it is cleared. It will be closed by the IPC mechanism. - int renderer_fd_; -#endif - // Used to implement message routing functionality to CommandBuffer objects MessageRouter router_; diff --git a/chrome/gpu/gpu_thread.cc b/chrome/gpu/gpu_thread.cc index 09c91f2..411fbbb 100644 --- a/chrome/gpu/gpu_thread.cc +++ b/chrome/gpu/gpu_thread.cc @@ -95,8 +95,8 @@ void GpuThread::OnEstablishChannel(int renderer_id) { #if defined(OS_POSIX) // On POSIX, pass the renderer-side FD. Also mark it as auto-close so // that it gets closed after it has been sent. - int renderer_fd = channel->DisownRendererFd(); - channel_handle.socket = base::FileDescriptor(renderer_fd, true); + int renderer_fd = channel->GetRendererFileDescriptor(); + channel_handle.socket = base::FileDescriptor(renderer_fd, false); #endif } diff --git a/chrome/plugin/plugin_channel.cc b/chrome/plugin/plugin_channel.cc index 0b6d5da..b3b12951 100644 --- a/chrome/plugin/plugin_channel.cc +++ b/chrome/plugin/plugin_channel.cc @@ -162,9 +162,6 @@ void PluginChannel::NotifyRenderersOfPendingShutdown() { PluginChannel::PluginChannel() : renderer_handle_(0), renderer_id_(-1), -#if defined(OS_POSIX) - renderer_fd_(-1), -#endif in_send_(0), off_the_record_(false), filter_(new MessageFilter()) { @@ -175,11 +172,6 @@ PluginChannel::PluginChannel() } PluginChannel::~PluginChannel() { -#if defined(OS_POSIX) - // Won't be needing this any more. - CloseRendererFD(); -#endif - if (renderer_handle_) base::CloseProcessHandle(renderer_handle_); @@ -293,12 +285,6 @@ base::WaitableEvent* PluginChannel::GetModalDialogEvent( } void PluginChannel::OnChannelConnected(int32 peer_pid) { -#if defined(OS_POSIX) - // By this point, the renderer must have its own copy of the plugin channel - // FD. - CloseRendererFD(); -#endif - base::ProcessHandle handle; if (!base::OpenProcessHandle(peer_pid, &handle)) { NOTREACHED(); @@ -308,11 +294,6 @@ void PluginChannel::OnChannelConnected(int32 peer_pid) { } void PluginChannel::OnChannelError() { -#if defined(OS_POSIX) - // Won't be needing this any more. - CloseRendererFD(); -#endif - base::CloseProcessHandle(renderer_handle_); renderer_handle_ = 0; PluginChannelBase::OnChannelError(); @@ -336,17 +317,6 @@ void PluginChannel::CleanUp() { } bool PluginChannel::Init(MessageLoop* ipc_message_loop, bool create_pipe_now) { -#if defined(OS_POSIX) - // This gets called when the PluginChannel is initially created. At this - // point, create the socketpair and assign the plugin side FD to the channel - // name. Keep the renderer side FD as a member variable in the PluginChannel - // to be able to transmit it through IPC. - int plugin_fd; - if (!IPC::SocketPair(&plugin_fd, &renderer_fd_)) - return false; - IPC::AddChannelSocket(channel_name(), plugin_fd); -#endif - if (!PluginChannelBase::Init(ipc_message_loop, create_pipe_now)) return false; @@ -354,12 +324,3 @@ bool PluginChannel::Init(MessageLoop* ipc_message_loop, bool create_pipe_now) { return true; } -#if defined(OS_POSIX) -void PluginChannel::CloseRendererFD() { - if (renderer_fd_ != -1) { - if (HANDLE_EINTR(close(renderer_fd_)) < 0) - PLOG(ERROR) << "close"; - renderer_fd_ = -1; - } -} -#endif diff --git a/chrome/plugin/plugin_channel.h b/chrome/plugin/plugin_channel.h index 2c00cf8..519e03c 100644 --- a/chrome/plugin/plugin_channel.h +++ b/chrome/plugin/plugin_channel.h @@ -50,7 +50,7 @@ class PluginChannel : public PluginChannelBase { void set_off_the_record(bool value) { off_the_record_ = value; } #if defined(OS_POSIX) - int renderer_fd() const { return renderer_fd_; } + int renderer_fd() const { return channel_->GetClientFileDescriptor(); } #endif protected: @@ -80,13 +80,6 @@ class PluginChannel : public PluginChannelBase { const std::string& domain, base::Time begin_time); -#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 - std::vector<scoped_refptr<WebPluginDelegateStub> > plugin_stubs_; // Handle to the renderer process who is on the other side of the channel. @@ -95,13 +88,6 @@ class PluginChannel : public PluginChannelBase { // The id of the renderer who is on the other side of the channel. int renderer_id_; -#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 - int in_send_; // Tracks if we're in a Send call. bool log_messages_; // True if we should log sent and received messages. bool off_the_record_; // True if the renderer is in off the record mode. diff --git a/chrome/plugin/plugin_channel_base.cc b/chrome/plugin/plugin_channel_base.cc index 6494afb..37bc1c4 100644 --- a/chrome/plugin/plugin_channel_base.cc +++ b/chrome/plugin/plugin_channel_base.cc @@ -28,11 +28,11 @@ static base::LazyInstance<std::stack<scoped_refptr<PluginChannelBase> > > static int next_pipe_id = 0; PluginChannelBase* PluginChannelBase::GetChannel( - const std::string& channel_key, IPC::Channel::Mode mode, + const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode, PluginChannelFactory factory, MessageLoop* ipc_message_loop, bool create_pipe_now) { scoped_refptr<PluginChannelBase> channel; - + std::string channel_key = channel_handle.name; PluginChannelMap::const_iterator iter = g_plugin_channels_.find(channel_key); if (iter == g_plugin_channels_.end()) { channel = factory(); @@ -43,10 +43,10 @@ PluginChannelBase* PluginChannelBase::GetChannel( DCHECK(channel != NULL); if (!channel->channel_valid()) { - channel->channel_name_ = channel_key; + channel->channel_handle_ = channel_handle; if (mode == IPC::Channel::MODE_SERVER) { - channel->channel_name_.append("."); - channel->channel_name_.append(base::IntToString(next_pipe_id++)); + channel->channel_handle_.name.append("."); + channel->channel_handle_.name.append(base::IntToString(next_pipe_id++)); } channel->mode_ = mode; if (channel->Init(ipc_message_loop, create_pipe_now)) { @@ -115,7 +115,7 @@ NPObjectBase* PluginChannelBase::GetNPObjectListenerForRoute(int route_id) { bool PluginChannelBase::Init(MessageLoop* ipc_message_loop, bool create_pipe_now) { channel_.reset(new IPC::SyncChannel( - channel_name_, mode_, this, ipc_message_loop, create_pipe_now, + channel_handle_, mode_, this, ipc_message_loop, create_pipe_now, ChildProcess::current()->GetShutDownEvent())); channel_valid_ = true; return true; @@ -219,11 +219,6 @@ void PluginChannelBase::RemoveRoute(int route_id) { for (PluginChannelMap::iterator iter = g_plugin_channels_.begin(); iter != g_plugin_channels_.end(); ++iter) { if (iter->second == this) { -#if defined(OS_POSIX) - if (channel_valid()) { - IPC::RemoveAndCloseChannelSocket(channel_name()); - } -#endif g_plugin_channels_.erase(iter); return; } @@ -239,10 +234,5 @@ void PluginChannelBase::OnControlMessageReceived(const IPC::Message& msg) { } void PluginChannelBase::OnChannelError() { -#if defined(OS_POSIX) - if (channel_valid()) { - IPC::RemoveAndCloseChannelSocket(channel_name()); - } -#endif channel_valid_ = false; } diff --git a/chrome/plugin/plugin_channel_base.h b/chrome/plugin/plugin_channel_base.h index 30fdc22..22103e8 100644 --- a/chrome/plugin/plugin_channel_base.h +++ b/chrome/plugin/plugin_channel_base.h @@ -16,6 +16,7 @@ #include "chrome/common/message_router.h" #include "chrome/plugin/npobject_base.h" #include "gfx/native_widget_types.h" +#include "ipc/ipc_channel_handle.h" #include "ipc/ipc_sync_channel.h" // Encapsulates an IPC channel between a renderer and a plugin process. @@ -38,7 +39,7 @@ class PluginChannelBase : public IPC::Channel::Listener, virtual bool Send(IPC::Message* msg); int peer_pid() { return peer_pid_; } - std::string channel_name() const { return channel_name_; } + IPC::ChannelHandle channel_handle() const { return channel_handle_; } // Returns the number of open plugin channels in this process. static int Count(); @@ -75,7 +76,7 @@ class PluginChannelBase : public IPC::Channel::Listener, // must still ref count the returned value. When there are no more routes // on the channel and its ref count is 0, the object deletes itself. static PluginChannelBase* GetChannel( - const std::string& channel_key, IPC::Channel::Mode mode, + const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode, PluginChannelFactory factory, MessageLoop* ipc_message_loop, bool create_pipe_now); @@ -105,7 +106,7 @@ class PluginChannelBase : public IPC::Channel::Listener, private: IPC::Channel::Mode mode_; - std::string channel_name_; + IPC::ChannelHandle channel_handle_; int plugin_count_; int peer_pid_; diff --git a/chrome/plugin/plugin_thread.cc b/chrome/plugin/plugin_thread.cc index 7c57f4d..7e2b921 100644 --- a/chrome/plugin/plugin_thread.cc +++ b/chrome/plugin/plugin_thread.cc @@ -143,7 +143,7 @@ void PluginThread::OnCreateChannel(int renderer_id, renderer_id, ChildProcess::current()->io_message_loop())); IPC::ChannelHandle channel_handle; if (channel.get()) { - channel_handle.name = channel->channel_name(); + channel_handle.name = channel->channel_handle().name; #if defined(OS_POSIX) // On POSIX, pass the renderer-side FD. channel_handle.socket = base::FileDescriptor(channel->renderer_fd(), false); diff --git a/chrome/ppapi_plugin/ppapi_thread.cc b/chrome/ppapi_plugin/ppapi_thread.cc index 7d8eeda..be6075d 100644 --- a/chrome/ppapi_plugin/ppapi_thread.cc +++ b/chrome/ppapi_plugin/ppapi_thread.cc @@ -99,29 +99,19 @@ bool PpapiThread::LoadPluginLib(base::ProcessHandle host_process_handle, bool PpapiThread::SetupRendererChannel(int renderer_id, IPC::ChannelHandle* handle) { - std::string channel_key = StringPrintf( - "%d.r%d", base::GetCurrentProcId(), renderer_id); - -#if defined(OS_POSIX) - // This gets called when the PluginChannel is initially created. At this - // point, create the socketpair and assign the plugin side FD to the channel - // name. Keep the renderer side FD as a member variable in the PluginChannel - // to be able to transmit it through IPC. - int plugin_fd; - if (!IPC::SocketPair(&plugin_fd, &renderer_fd_)) - return false; - IPC::AddChannelSocket(channel_key, plugin_fd); -#endif - + IPC::ChannelHandle plugin_handle; + plugin_handle.name = StringPrintf("%d.r%d", base::GetCurrentProcId(), + renderer_id); if (!dispatcher_->InitWithChannel( ChildProcess::current()->io_message_loop(), - channel_key, false, + plugin_handle, false, ChildProcess::current()->GetShutDownEvent())) return false; - handle->name = channel_key; + 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); #endif return true; diff --git a/chrome/renderer/gpu_channel_host.cc b/chrome/renderer/gpu_channel_host.cc index c59f2f1..80baea9 100644 --- a/chrome/renderer/gpu_channel_host.cc +++ b/chrome/renderer/gpu_channel_host.cc @@ -16,10 +16,10 @@ GpuChannelHost::GpuChannelHost() : state_(kUnconnected) { GpuChannelHost::~GpuChannelHost() { } -void GpuChannelHost::Connect(const std::string& channel_name) { +void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle) { // Open a channel to the GPU process. channel_.reset(new IPC::SyncChannel( - channel_name, IPC::Channel::MODE_CLIENT, this, + channel_handle, IPC::Channel::MODE_CLIENT, this, ChildProcess::current()->io_message_loop(), true, ChildProcess::current()->GetShutDownEvent())); diff --git a/chrome/renderer/gpu_channel_host.h b/chrome/renderer/gpu_channel_host.h index 818202e..8d9c684 100644 --- a/chrome/renderer/gpu_channel_host.h +++ b/chrome/renderer/gpu_channel_host.h @@ -16,6 +16,7 @@ #include "gfx/native_widget_types.h" #include "gfx/size.h" #include "ipc/ipc_channel.h" +#include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message.h" #include "ipc/ipc_sync_channel.h" @@ -43,7 +44,7 @@ class GpuChannelHost : public IPC::Channel::Listener, ~GpuChannelHost(); // Connect to GPU process channel. - void Connect(const std::string& channel_name); + void Connect(const IPC::ChannelHandle& channel_handle); State state() const { return state_; } diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc index a949ffb8..f889223 100644 --- a/chrome/renderer/pepper_plugin_delegate_impl.cc +++ b/chrome/renderer/pepper_plugin_delegate_impl.cc @@ -452,14 +452,8 @@ bool DispatcherWrapper::Init( dispatcher_.reset(new pp::proxy::HostDispatcher( plugin_process_handle, pp_module, local_get_interface)); -#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 - if (!dispatcher_->InitWithChannel( - ChildProcess::current()->io_message_loop(), channel_handle.name, + ChildProcess::current()->io_message_loop(), channel_handle, true, ChildProcess::current()->GetShutDownEvent())) { dispatcher_.reset(); return false; diff --git a/chrome/renderer/plugin_channel_host.cc b/chrome/renderer/plugin_channel_host.cc index 1a1e03f..b6a93c0 100644 --- a/chrome/renderer/plugin_channel_host.cc +++ b/chrome/renderer/plugin_channel_host.cc @@ -68,10 +68,10 @@ void PluginChannelHost::SetListening(bool flag) { } PluginChannelHost* PluginChannelHost::GetPluginChannelHost( - const std::string& channel_name, MessageLoop* ipc_message_loop) { + const IPC::ChannelHandle& channel_handle, MessageLoop* ipc_message_loop) { PluginChannelHost* result = static_cast<PluginChannelHost*>(PluginChannelBase::GetChannel( - channel_name, + channel_handle, IPC::Channel::MODE_CLIENT, ClassFactory, ipc_message_loop, @@ -87,19 +87,6 @@ PluginChannelHost::~PluginChannelHost() { bool PluginChannelHost::Init(MessageLoop* ipc_message_loop, bool create_pipe_now) { -#if defined(OS_POSIX) - if (!IPC::ChannelSocketExists(channel_name())) { - // Attempting to use this IPC channel would result in a crash - // inside IPC code within the PluginChannelBase::Init call. The plugin - // channel in the plugin process is supposed to have created this channel - // and sent it to this process, the renderer process. If this channel - // closes and is removed, it cannot be reused until the plugin process - // recreates it. - LOG(ERROR) << "Refusing use of missing IPC channel " << channel_name(); - return false; - } -#endif - bool ret = PluginChannelBase::Init(ipc_message_loop, create_pipe_now); is_listening_filter_ = new IsListeningFilter; channel_->AddFilter(is_listening_filter_); diff --git a/chrome/renderer/plugin_channel_host.h b/chrome/renderer/plugin_channel_host.h index f4e95dc..241833f 100644 --- a/chrome/renderer/plugin_channel_host.h +++ b/chrome/renderer/plugin_channel_host.h @@ -8,6 +8,7 @@ #include "base/hash_tables.h" #include "chrome/plugin/plugin_channel_base.h" +#include "ipc/ipc_channel_handle.h" class IsListeningFilter; class NPObjectBase; @@ -17,7 +18,7 @@ class NPObjectBase; class PluginChannelHost : public PluginChannelBase { public: static PluginChannelHost* GetPluginChannelHost( - const std::string& channel_name, MessageLoop* ipc_message_loop); + const IPC::ChannelHandle& channel_handle, MessageLoop* ipc_message_loop); virtual bool Init(MessageLoop* ipc_message_loop, bool create_pipe_now); diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 3fe1ff2..9fb0d6ab 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -1080,17 +1080,11 @@ void RenderThread::OnSetIsIncognitoProcess(bool is_incognito_process) { void RenderThread::OnGpuChannelEstablished( const IPC::ChannelHandle& channel_handle, const GPUInfo& gpu_info) { -#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 - gpu_channel_->set_gpu_info(gpu_info); if (channel_handle.name.size() != 0) { // Connect to the GPU process if a channel name was received. - gpu_channel_->Connect(channel_handle.name); + gpu_channel_->Connect(channel_handle); } else { // Otherwise cancel the connection. gpu_channel_ = NULL; diff --git a/chrome/renderer/webplugin_delegate_proxy.cc b/chrome/renderer/webplugin_delegate_proxy.cc index 0aaa742..5c8d550 100644 --- a/chrome/renderer/webplugin_delegate_proxy.cc +++ b/chrome/renderer/webplugin_delegate_proxy.cc @@ -292,15 +292,9 @@ bool WebPluginDelegateProxy::Initialize(const GURL& url, 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 - scoped_refptr<PluginChannelHost> channel_host( PluginChannelHost::GetPluginChannelHost( - channel_handle.name, ChildProcess::current()->io_message_loop())); + channel_handle, ChildProcess::current()->io_message_loop())); if (!channel_host.get()) return false; diff --git a/ipc/ipc_channel.h b/ipc/ipc_channel.h index 1b5d73a..d07e3e5 100644 --- a/ipc/ipc_channel.h +++ b/ipc/ipc_channel.h @@ -7,6 +7,7 @@ #pragma once #include "base/compiler_specific.h" +#include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message.h" namespace IPC { @@ -54,7 +55,10 @@ class Channel : public Message::Sender { // Initialize a Channel. // - // |channel_id| identifies the communication Channel. + // |channel_handle| identifies the communication Channel. For POSIX, if + // the file descriptor in the channel handle is != -1, the channel takes + // ownership of the file descriptor and will close it appropriately, otherwise + // it will create a new descriptor internally. // |mode| specifies whether this Channel is to operate in server mode or // client mode. In server mode, the Channel is responsible for setting up the // IPC object, whereas in client mode, the Channel merely connects to the @@ -62,7 +66,8 @@ class Channel : public Message::Sender { // |listener| receives a callback on the current thread for each newly // received message. // - Channel(const std::string& channel_id, Mode mode, Listener* listener); + Channel(const IPC::ChannelHandle &channel_handle, Mode mode, + Listener* listener); ~Channel(); diff --git a/ipc/ipc_channel_handle.h b/ipc/ipc_channel_handle.h index dc6957f..1b9a385 100644 --- a/ipc/ipc_channel_handle.h +++ b/ipc/ipc_channel_handle.h @@ -29,18 +29,19 @@ 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() {} + ChannelHandle(const std::string& n) : name(n) {} + ChannelHandle(const char* n) : name(n) {} #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 +#endif // defined(OS_POSIX) + + std::string name; +#if defined(OS_POSIX) + base::FileDescriptor socket; +#endif // defined(OS_POSIX) + }; } // namespace IPC diff --git a/ipc/ipc_channel_posix.cc b/ipc/ipc_channel_posix.cc index 781175e3..4a32f44 100644 --- a/ipc/ipc_channel_posix.cc +++ b/ipc/ipc_channel_posix.cc @@ -79,6 +79,11 @@ class PipeMap { return Singleton<PipeMap>::get(); } + ~PipeMap() { + // Shouldn't have left over pipes. + DCHECK(map_.size() == 0); + } + // Lookup a given channel id. Return -1 if not found. int Lookup(const std::string& channel_id) { AutoLock locked(lock_); @@ -274,8 +279,8 @@ bool SocketWriteErrorIsRecoverable() { } // namespace //------------------------------------------------------------------------------ -Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, - Listener* listener) +Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle, + Mode mode, Listener* listener) : mode_(mode), is_blocked_on_write_(false), message_send_bytes_written_(0), @@ -297,9 +302,9 @@ Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, if (mode_ == MODE_NAMED_CLIENT) mode_ = MODE_CLIENT; - if (!CreatePipe(channel_id, mode_)) { + if (!CreatePipe(channel_handle, mode_)) { // The pipe may have been closed already. - PLOG(WARNING) << "Unable to create pipe named \"" << channel_id + LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name << "\" in " << (mode_ == MODE_SERVER ? "server" : "client") << " mode"; } @@ -349,16 +354,16 @@ bool SocketPair(int* fd1, int* fd2) { return true; } -bool Channel::ChannelImpl::CreatePipe(const std::string& channel_id, +bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle, Mode mode) { DCHECK(server_listen_pipe_ == -1 && pipe_ == -1); - + pipe_name_ = channel_handle.name; + pipe_ = channel_handle.socket.fd; if (uses_fifo_) { // This only happens in unit tests; see the comment above PipeMap. // TODO(playmobil): We shouldn't need to create fifos on disk. // TODO(playmobil): If we do, they should be in the user data directory. // TODO(playmobil): Cleanup any stale fifos. - pipe_name_ = channel_id; if (mode == MODE_SERVER) { if (!CreateServerFifo(pipe_name_, &server_listen_pipe_)) { return false; @@ -376,8 +381,9 @@ bool Channel::ChannelImpl::CreatePipe(const std::string& channel_id, // 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; - pipe_ = ChannelNameToFD(pipe_name_); + if (pipe_ < 0) { + pipe_ = ChannelNameToFD(pipe_name_); + } if (pipe_ < 0) { // Initial IPC channel. if (mode == MODE_SERVER) { @@ -1065,9 +1071,9 @@ void Channel::ChannelImpl::Close() { //------------------------------------------------------------------------------ // Channel's methods simply call through to ChannelImpl. -Channel::Channel(const std::string& channel_id, Mode mode, +Channel::Channel(const IPC::ChannelHandle& channel_handle, Mode mode, Listener* listener) - : channel_impl_(new ChannelImpl(channel_id, mode, listener)) { + : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) { } Channel::~Channel() { diff --git a/ipc/ipc_channel_posix.h b/ipc/ipc_channel_posix.h index b7818a2..77a993e 100644 --- a/ipc/ipc_channel_posix.h +++ b/ipc/ipc_channel_posix.h @@ -19,27 +19,13 @@ 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); - -// Remove the channel name mapping, and close the corresponding socket. -void RemoveAndCloseChannelSocket(const std::string& name); - -// Returns true if a channel named |name| is available. -bool ChannelSocketExists(const std::string& name); - -// 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 { public: // Mirror methods of Channel, see ipc_channel.h for description. - ChannelImpl(const std::string& channel_id, Mode mode, Listener* listener); + ChannelImpl(const IPC::ChannelHandle &channel_handle, Mode mode, + Listener* listener); ~ChannelImpl(); bool Connect(); void Close(); @@ -48,7 +34,7 @@ class Channel::ChannelImpl : public MessageLoopForIO::Watcher { int GetClientFileDescriptor() const; private: - bool CreatePipe(const std::string& channel_id, Mode mode); + bool CreatePipe(const IPC::ChannelHandle &channel_handle, Mode mode); bool ProcessIncomingMessages(); bool ProcessOutgoingMessages(); diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc index 8450c28..fd5144c 100644 --- a/ipc/ipc_channel_proxy.cc +++ b/ipc/ipc_channel_proxy.cc @@ -65,16 +65,15 @@ ChannelProxy::Context::Context(Channel::Listener* listener, : listener_message_loop_(MessageLoop::current()), listener_(listener), ipc_message_loop_(ipc_message_loop), - channel_(NULL), peer_pid_(0), channel_connected_called_(false) { } -void ChannelProxy::Context::CreateChannel(const std::string& id, +void ChannelProxy::Context::CreateChannel(const IPC::ChannelHandle& handle, const Channel::Mode& mode) { - DCHECK(channel_ == NULL); - channel_id_ = id; - channel_ = new Channel(id, mode, this); + DCHECK(channel_.get() == NULL); + channel_id_ = handle.name; + channel_.reset(new Channel(handle, mode, this)); } bool ChannelProxy::Context::TryFilters(const Message& message) { @@ -154,14 +153,14 @@ void ChannelProxy::Context::OnChannelOpened() { } for (size_t i = 0; i < filters_.size(); ++i) - filters_[i]->OnFilterAdded(channel_); + filters_[i]->OnFilterAdded(channel_.get()); } // Called on the IPC::Channel thread void ChannelProxy::Context::OnChannelClosed() { // It's okay for IPC::ChannelProxy::Close to be called more than once, which // would result in this branch being taken. - if (!channel_) + if (!channel_.get()) return; for (size_t i = 0; i < filters_.size(); ++i) { @@ -172,8 +171,7 @@ void ChannelProxy::Context::OnChannelClosed() { // We don't need the filters anymore. filters_.clear(); - delete channel_; - channel_ = NULL; + channel_.reset(); // Balance with the reference taken during startup. This may result in // self-destruction. @@ -182,7 +180,7 @@ void ChannelProxy::Context::OnChannelClosed() { // Called on the IPC::Channel thread void ChannelProxy::Context::OnSendMessage(Message* message) { - if (!channel_) { + if (!channel_.get()) { delete message; OnChannelClosed(); return; @@ -204,8 +202,8 @@ void ChannelProxy::Context::OnAddFilter() { // If the channel has already been created, then we need to send this // message so that the filter gets access to the Channel. - if (channel_) - filters[i]->OnFilterAdded(channel_); + if (channel_.get()) + filters[i]->OnFilterAdded(channel_.get()); // Ditto for the peer process id. if (peer_pid_) filters[i]->OnChannelConnected(peer_pid_); @@ -278,38 +276,49 @@ void ChannelProxy::Context::OnDispatchError() { //----------------------------------------------------------------------------- -ChannelProxy::ChannelProxy(const std::string& channel_id, +ChannelProxy::ChannelProxy(const IPC::ChannelHandle& channel_handle, Channel::Mode mode, Channel::Listener* listener, MessageLoop* ipc_thread) : context_(new Context(listener, ipc_thread)) { - Init(channel_id, mode, ipc_thread, true); + Init(channel_handle, mode, ipc_thread, true); } -ChannelProxy::ChannelProxy(const std::string& channel_id, +ChannelProxy::ChannelProxy(const IPC::ChannelHandle& channel_handle, Channel::Mode mode, MessageLoop* ipc_thread, Context* context, bool create_pipe_now) : context_(context) { - Init(channel_id, mode, ipc_thread, create_pipe_now); + Init(channel_handle, mode, ipc_thread, create_pipe_now); } ChannelProxy::~ChannelProxy() { Close(); } -void ChannelProxy::Init(const std::string& channel_id, Channel::Mode mode, - MessageLoop* ipc_thread_loop, bool create_pipe_now) { +void ChannelProxy::Init(const IPC::ChannelHandle& channel_handle, + Channel::Mode mode, MessageLoop* ipc_thread_loop, + bool create_pipe_now) { +#if defined(OS_POSIX) + // When we are creating a server on POSIX, we need its file descriptor + // to be created immediately so that it can be accessed and passed + // to other processes. Forcing it to be created immediately avoids + // race conditions that may otherwise arise. + if (mode == Channel::MODE_SERVER) { + create_pipe_now = true; + } +#endif // defined(OS_POSIX) + if (create_pipe_now) { // Create the channel immediately. This effectively sets up the // low-level pipe so that the client can connect. Without creating // the pipe immediately, it is possible for a listener to attempt // to connect and get an error since the pipe doesn't exist yet. - context_->CreateChannel(channel_id, mode); + context_->CreateChannel(channel_handle, mode); } else { context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod( - context_.get(), &Context::CreateChannel, channel_id, mode)); + context_.get(), &Context::CreateChannel, channel_handle, mode)); } // complete initialization on the background thread @@ -360,8 +369,9 @@ void ChannelProxy::ClearIPCMessageLoop() { // ChannelProxy::Init(). // We assume that IPC::Channel::GetClientFileDescriptorMapping() is thread-safe. int ChannelProxy::GetClientFileDescriptor() const { - Channel *channel = context_.get()->channel_; - DCHECK(channel); // Channel must have been created first. + Channel *channel = context_.get()->channel_.get(); + // Channel must have been created first. + DCHECK(channel) << context_.get()->channel_id_; return channel->GetClientFileDescriptor(); } #endif diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h index a85841d..a256ab6 100644 --- a/ipc/ipc_channel_proxy.h +++ b/ipc/ipc_channel_proxy.h @@ -10,7 +10,9 @@ #include "base/lock.h" #include "base/ref_counted.h" +#include "base/scoped_ptr.h" #include "ipc/ipc_channel.h" +#include "ipc/ipc_channel_handle.h" class MessageLoop; @@ -97,7 +99,7 @@ class ChannelProxy : public Message::Sender { } }; - // Initializes a channel proxy. The channel_id and mode parameters are + // Initializes a channel proxy. The channel_handle and mode parameters are // passed directly to the underlying IPC::Channel. The listener is called on // the thread that creates the ChannelProxy. The filter's OnMessageReceived // method is called on the thread where the IPC::Channel is running. The @@ -105,7 +107,7 @@ class ChannelProxy : public Message::Sender { // on the background thread. Any message not handled by the filter will be // dispatched to the listener. The given message loop indicates where the // IPC::Channel should be created. - ChannelProxy(const std::string& channel_id, + ChannelProxy(const IPC::ChannelHandle& channel_handle, Channel::Mode mode, Channel::Listener* listener, MessageLoop* ipc_thread_loop); @@ -143,8 +145,6 @@ class ChannelProxy : public Message::Sender { #if defined(OS_POSIX) // Calls through to the underlying channel's methods. - // TODO(playmobil): For now this is only implemented in the case of - // create_pipe_now = true, we need to figure this out for the latter case. int GetClientFileDescriptor() const; #endif // defined(OS_POSIX) @@ -153,7 +153,7 @@ class ChannelProxy : public Message::Sender { // A subclass uses this constructor if it needs to add more information // to the internal state. If create_pipe_now is true, the pipe is created // immediately. Otherwise it's created on the IO thread. - ChannelProxy(const std::string& channel_id, + ChannelProxy(const IPC::ChannelHandle& channel_handle, Channel::Mode mode, MessageLoop* ipc_thread_loop, Context* context, @@ -201,7 +201,8 @@ class ChannelProxy : public Message::Sender { friend class SendTask; // Create the Channel - void CreateChannel(const std::string& id, const Channel::Mode& mode); + void CreateChannel(const IPC::ChannelHandle& channel_handle, + const Channel::Mode& mode); // Methods called on the IO thread. void OnSendMessage(Message* message_ptr); @@ -219,7 +220,7 @@ class ChannelProxy : public Message::Sender { // List of filters. This is only accessed on the IPC thread. std::vector<scoped_refptr<MessageFilter> > filters_; MessageLoop* ipc_message_loop_; - Channel* channel_; + scoped_ptr<Channel> channel_; std::string channel_id_; int peer_pid_; bool channel_connected_called_; @@ -236,7 +237,7 @@ class ChannelProxy : public Message::Sender { private: friend class SendTask; - void Init(const std::string& channel_id, Channel::Mode mode, + void Init(const IPC::ChannelHandle& channel_handle, Channel::Mode mode, MessageLoop* ipc_thread_loop, bool create_pipe_now); // By maintaining this indirection (ref-counted) to our internal state, we diff --git a/ipc/ipc_channel_win.cc b/ipc/ipc_channel_win.cc index 31d1d185..28a880d 100644 --- a/ipc/ipc_channel_win.cc +++ b/ipc/ipc_channel_win.cc @@ -97,8 +97,8 @@ Channel::ChannelImpl::State::~State() { //------------------------------------------------------------------------------ -Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, - Listener* listener) +Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle &channel_handle, + Mode mode, Listener* listener) : ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)), ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)), pipe_(INVALID_HANDLE_VALUE), @@ -106,9 +106,9 @@ Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, waiting_connect_(mode == MODE_SERVER), processing_incoming_(false), ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) { - if (!CreatePipe(channel_id, mode)) { + if (!CreatePipe(channel_handle, mode)) { // The pipe may have been closed already. - LOG(WARNING) << "Unable to create pipe named \"" << channel_id << + LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name << "\" in " << (mode == 0 ? "server" : "client") << " mode."; } } @@ -175,10 +175,10 @@ const std::wstring Channel::ChannelImpl::PipeName( return ss.str(); } -bool Channel::ChannelImpl::CreatePipe(const std::string& channel_id, +bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle, Mode mode) { DCHECK(pipe_ == INVALID_HANDLE_VALUE); - const std::wstring pipe_name = PipeName(channel_id); + const std::wstring pipe_name = PipeName(channel_handle.name); if (mode == MODE_SERVER) { SECURITY_ATTRIBUTES security_attributes = {0}; security_attributes.bInheritHandle = FALSE; @@ -469,9 +469,9 @@ void Channel::ChannelImpl::OnIOCompleted(MessageLoopForIO::IOContext* context, //------------------------------------------------------------------------------ // Channel's methods simply call through to ChannelImpl. -Channel::Channel(const std::string& channel_id, Mode mode, +Channel::Channel(const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) - : channel_impl_(new ChannelImpl(channel_id, mode, listener)) { + : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) { } Channel::~Channel() { diff --git a/ipc/ipc_channel_win.h b/ipc/ipc_channel_win.h index ccaa6f4..82b70db 100644 --- a/ipc/ipc_channel_win.h +++ b/ipc/ipc_channel_win.h @@ -21,7 +21,8 @@ namespace IPC { class Channel::ChannelImpl : public MessageLoopForIO::IOHandler { public: // Mirror methods of Channel, see ipc_channel.h for description. - ChannelImpl(const std::string& channel_id, Mode mode, Listener* listener); + ChannelImpl(const IPC::ChannelHandle &channel_handle, Mode mode, + Listener* listener); ~ChannelImpl(); bool Connect(); void Close(); @@ -29,7 +30,7 @@ class Channel::ChannelImpl : public MessageLoopForIO::IOHandler { bool Send(Message* message); private: const std::wstring PipeName(const std::string& channel_id) const; - bool CreatePipe(const std::string& channel_id, Mode mode); + bool CreatePipe(const IPC::ChannelHandle &channel_handle, Mode mode); bool ProcessConnection(); bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context, diff --git a/ipc/ipc_sync_channel.cc b/ipc/ipc_sync_channel.cc index e77846c..7425a9b 100644 --- a/ipc/ipc_sync_channel.cc +++ b/ipc/ipc_sync_channel.cc @@ -355,14 +355,14 @@ void SyncChannel::SyncContext::OnWaitableEventSignaled(WaitableEvent* event) { SyncChannel::SyncChannel( - const std::string& channel_id, + const IPC::ChannelHandle& channel_handle, Channel::Mode mode, Channel::Listener* listener, MessageLoop* ipc_message_loop, bool create_pipe_now, WaitableEvent* shutdown_event) : ChannelProxy( - channel_id, mode, ipc_message_loop, + channel_handle, mode, ipc_message_loop, new SyncContext(listener, ipc_message_loop, shutdown_event), create_pipe_now), sync_messages_with_no_timeout_allowed_(true) { diff --git a/ipc/ipc_sync_channel.h b/ipc/ipc_sync_channel.h index 3435042..fce2e38 100644 --- a/ipc/ipc_sync_channel.h +++ b/ipc/ipc_sync_channel.h @@ -13,6 +13,7 @@ #include "base/lock.h" #include "base/ref_counted.h" #include "base/waitable_event_watcher.h" +#include "ipc/ipc_channel_handle.h" #include "ipc/ipc_channel_proxy.h" #include "ipc/ipc_sync_message.h" @@ -34,7 +35,7 @@ class MessageReplyDeserializer; class SyncChannel : public ChannelProxy, public base::WaitableEventWatcher::Delegate { public: - SyncChannel(const std::string& channel_id, + SyncChannel(const IPC::ChannelHandle& channel_handle, Channel::Mode mode, Channel::Listener* listener, MessageLoop* ipc_message_loop, diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc index 072134d..3f18877 100644 --- a/ppapi/proxy/dispatcher.cc +++ b/ppapi/proxy/dispatcher.cc @@ -77,12 +77,12 @@ Dispatcher::~Dispatcher() { } bool Dispatcher::InitWithChannel(MessageLoop* ipc_message_loop, - const std::string& channel_name, + const IPC::ChannelHandle& channel_handle, bool is_client, base::WaitableEvent* shutdown_event) { IPC::Channel::Mode mode = is_client ? IPC::Channel::MODE_CLIENT : IPC::Channel::MODE_SERVER; - channel_.reset(new IPC::SyncChannel(channel_name, mode, this, + channel_.reset(new IPC::SyncChannel(channel_handle, mode, this, ipc_message_loop, false, shutdown_event)); return true; } diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h index deee5fc..1c76cb8 100644 --- a/ppapi/proxy/dispatcher.h +++ b/ppapi/proxy/dispatcher.h @@ -62,7 +62,7 @@ class Dispatcher : public IPC::Channel::Listener, ~Dispatcher(); bool InitWithChannel(MessageLoop* ipc_message_loop, - const std::string& channel_name, + const IPC::ChannelHandle& channel_handle, bool is_client, base::WaitableEvent* shutdown_event); |