summaryrefslogtreecommitdiffstats
path: root/chrome/common
diff options
context:
space:
mode:
authorjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-10 22:28:11 +0000
committerjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-10 22:28:11 +0000
commit514411fcb4657f575eeb3e39a9056478a28306a0 (patch)
treebe2bcacf0d4cffd91ceded1f4e03bc3d6ae3d6e6 /chrome/common
parentf20b9e922a26e045af6bc7a5c3c46d78abb04aac (diff)
downloadchromium_src-514411fcb4657f575eeb3e39a9056478a28306a0.zip
chromium_src-514411fcb4657f575eeb3e39a9056478a28306a0.tar.gz
chromium_src-514411fcb4657f575eeb3e39a9056478a28306a0.tar.bz2
Refactor IPC::Channel to have a common header.
Review URL: http://codereview.chromium.org/11024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6743 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
-rw-r--r--chrome/common/common.scons2
-rw-r--r--chrome/common/common.vcproj2
-rw-r--r--chrome/common/ipc_channel.h111
-rw-r--r--chrome/common/ipc_channel_posix.cc71
-rw-r--r--chrome/common/ipc_channel_posix.h93
-rw-r--r--chrome/common/ipc_channel_proxy.h2
-rw-r--r--chrome/common/ipc_channel_win.cc (renamed from chrome/common/ipc_channel.cc)82
-rw-r--r--chrome/common/ipc_channel_win.h81
-rw-r--r--chrome/common/ipc_fuzzing_tests.cc4
-rw-r--r--chrome/common/resource_dispatcher.cc1
-rw-r--r--chrome/common/resource_dispatcher.h2
11 files changed, 295 insertions, 156 deletions
diff --git a/chrome/common/common.scons b/chrome/common/common.scons
index 0116edf..5f4d8fa 100644
--- a/chrome/common/common.scons
+++ b/chrome/common/common.scons
@@ -90,7 +90,7 @@ if env['PLATFORM'] == 'win32':
'gfx/icon_util.cc',
'gfx/path.cc',
'gfx/text_elider.cc',
- 'ipc_channel.cc',
+ 'ipc_channel_win.cc',
'ipc_channel_proxy.cc',
'ipc_logging.cc',
'ipc_message_utils.cc',
diff --git a/chrome/common/common.vcproj b/chrome/common/common.vcproj
index 7293656..e1331e0 100644
--- a/chrome/common/common.vcproj
+++ b/chrome/common/common.vcproj
@@ -221,7 +221,7 @@
Name="ipc"
>
<File
- RelativePath=".\ipc_channel.cc"
+ RelativePath=".\ipc_channel_win.cc"
>
</File>
<File
diff --git a/chrome/common/ipc_channel.h b/chrome/common/ipc_channel.h
index ac234b8..bd7bf05 100644
--- a/chrome/common/ipc_channel.h
+++ b/chrome/common/ipc_channel.h
@@ -5,22 +5,13 @@
#ifndef CHROME_COMMON_IPC_CHANNEL_H_
#define CHROME_COMMON_IPC_CHANNEL_H_
-#include <queue>
-
-#include "base/message_loop.h"
#include "chrome/common/ipc_message.h"
namespace IPC {
//------------------------------------------------------------------------------
-class Channel : public Message::Sender,
-#if defined(OS_WIN)
- public MessageLoopForIO::IOHandler
-#elif defined(OS_POSIX)
- public MessageLoopForIO::FileWatcher
-#endif
- {
+class Channel : public Message::Sender {
// Security tests need access to the pipe handle.
friend class ChannelTest;
@@ -47,10 +38,13 @@ class Channel : public Message::Sender,
MODE_CLIENT
};
- // The maximum message size in bytes. Attempting to receive a
- // message of this size or bigger results in a channel error.
enum {
- kMaximumMessageSize = 256 * 1024 * 1024
+ // The maximum message size in bytes. Attempting to receive a
+ // message of this size or bigger results in a channel error.
+ kMaximumMessageSize = 256 * 1024 * 1024,
+
+ // Ammount of data to read at once from the pipe.
+ kReadBufferSize = 4 * 1024
};
// Initialize a Channel.
@@ -65,7 +59,7 @@ class Channel : public Message::Sender,
//
Channel(const std::wstring& channel_id, Mode mode, Listener* listener);
- ~Channel() { Close(); }
+ ~Channel();
// Connect the pipe. On the server side, this will initiate
// waiting for connections. On the client, it attempts to
@@ -78,7 +72,7 @@ class Channel : public Message::Sender,
void Close();
// Modify the Channel's listener.
- void set_listener(Listener* listener) { listener_ = listener; }
+ void set_listener(Listener* listener);
// Send a message over the Channel to the listener on the other end.
//
@@ -92,87 +86,9 @@ class Channel : public Message::Sender,
virtual bool Send(Message* message);
private:
- const std::wstring PipeName(const std::wstring& channel_id) const;
- bool CreatePipe(const std::wstring& channel_id, Mode mode);
-#if defined(OS_WIN)
- bool ProcessConnection();
- bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context,
- DWORD bytes_read);
- bool ProcessOutgoingMessages(MessageLoopForIO::IOContext* context,
- DWORD bytes_written);
-
- // MessageLoop::IOHandler implementation.
- virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
- DWORD bytes_transfered, DWORD error);
- private:
- enum {
- BUF_SIZE = 4096
- };
-
- struct State {
- explicit State(Channel* channel);
- ~State();
- MessageLoopForIO::IOContext context;
- bool is_pending;
- };
-
- State input_state_;
- State output_state_;
-
- HANDLE pipe_;
-#elif defined(OS_POSIX)
- bool ProcessIncomingMessages();
- bool ProcessOutgoingMessages();
-
- void OnFileReadReady(int fd);
- void OnFileWriteReady(int fd);
-
-
- Mode mode_;
-
- // TODO(playmobil): do we need to change BUF_SIZE ?
- private:
- enum {
- BUF_SIZE = 4096
- };
-
- // PIMPL to encapsulate libevent structures.
- struct EventHolder;
- EventHolder *server_listen_connection_event_;
- EventHolder *read_event_;
- EventHolder *write_event_;
-
- // If sending a message blocks then we use this variable
- // to keep track of where we are.
- size_t message_send_bytes_written_;
-
- int server_listen_pipe_;
- int pipe_;
- std::string pipe_name_;
-#endif // defined(OS_POSIX)
- Listener* listener_;
-
- // Messages to be sent are queued here.
- std::queue<Message*> output_queue_;
-
- // We read from the pipe into this buffer
- char input_buf_[BUF_SIZE];
-
- // Large messages that span multiple pipe buffers, get built-up using
- // this buffer.
- std::string input_overflow_buf_;
-
- // In server-mode, we have to wait for the client to connect before we
- // can begin reading. We make use of the input_state_ when performing
- // the connect operation in overlapped mode.
- bool waiting_connect_;
-
- // This flag is set when processing incoming messages. It is used to
- // avoid recursing through ProcessIncomingMessages, which could cause
- // problems. TODO(darin): make this unnecessary
- bool processing_incoming_;
-
- ScopedRunnableMethodFactory<Channel> factory_;
+ // PIMPL to which all channel calls are delegated.
+ class ChannelImpl;
+ ChannelImpl *channel_impl_;
// The Hello message is internal to the Channel class. It is sent
// by the peer when the channel is connected. The message contains
@@ -186,7 +102,6 @@ class Channel : public Message::Sender,
};
};
-}
+} // namespace IPC
#endif // CHROME_COMMON_IPC_CHANNEL_H_
-
diff --git a/chrome/common/ipc_channel_posix.cc b/chrome/common/ipc_channel_posix.cc
index 092e8a1..45573ae 100644
--- a/chrome/common/ipc_channel_posix.cc
+++ b/chrome/common/ipc_channel_posix.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/common/ipc_channel.h"
+#include "chrome/common/ipc_channel_posix.h"
#include <fcntl.h>
#include <sys/types.h>
@@ -17,7 +17,6 @@
#include "base/string_util.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/ipc_message_utils.h"
-#include "third_party/libevent/event.h"
namespace IPC {
@@ -140,25 +139,10 @@ bool ClientConnectToFifo(const std::string &pipe_name, int* client_socket) {
}
} // namespace
-
//------------------------------------------------------------------------------
-// PIMPL wrapper for libevent event.
-// TODO(playmobil): MessageLoopForIO needs to better encapsulate libevent.
-struct Channel::EventHolder {
- EventHolder() : is_active(false) {}
- ~EventHolder() {}
-
- bool is_active;
-
- // libevent's set functions set all the needed members of this struct, so no
- // need to initialize before use.
- struct event event;
-};
-
-//------------------------------------------------------------------------------
-
-Channel::Channel(const std::wstring& channel_id, Mode mode, Listener* listener)
+Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
+ Listener* listener)
: mode_(mode),
server_listen_connection_event_(new EventHolder()),
read_event_(new EventHolder()),
@@ -178,7 +162,8 @@ Channel::Channel(const std::wstring& channel_id, Mode mode, Listener* listener)
}
}
-const std::wstring Channel::PipeName(const std::wstring& channel_id) const {
+const std::wstring Channel::ChannelImpl::PipeName(
+ const std::wstring& channel_id) const {
std::wostringstream ss;
// TODO(playmobil): This should live in the Chrome user data directory.
// TODO(playmobil): Cleanup any stale fifos.
@@ -186,7 +171,8 @@ const std::wstring Channel::PipeName(const std::wstring& channel_id) const {
return ss.str();
}
-bool Channel::CreatePipe(const std::wstring& channel_id, Mode mode) {
+bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
+ Mode mode) {
DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
// TODO(playmobil): Should we just change pipe_name to be a normal string
@@ -217,7 +203,7 @@ bool Channel::CreatePipe(const std::wstring& channel_id, Mode mode) {
return true;
}
-bool Channel::Connect() {
+bool Channel::ChannelImpl::Connect() {
if (mode_ == MODE_SERVER) {
if (server_listen_pipe_ == -1) {
return false;
@@ -245,7 +231,7 @@ bool Channel::Connect() {
return true;
}
-bool Channel::ProcessIncomingMessages() {
+bool Channel::ChannelImpl::ProcessIncomingMessages() {
ssize_t bytes_read = 0;
for (;;) {
@@ -257,7 +243,7 @@ bool Channel::ProcessIncomingMessages() {
// recv() returns 0 if the connection has closed or EAGAIN if no data is
// waiting on the pipe.
do {
- bytes_read = read(pipe_, input_buf_, BUF_SIZE);
+ bytes_read = read(pipe_, input_buf_, Channel::kReadBufferSize);
} while (bytes_read == -1 && errno == EINTR);
if (bytes_read < 0) {
if (errno == EAGAIN) {
@@ -322,7 +308,7 @@ bool Channel::ProcessIncomingMessages() {
return true;
}
-bool Channel::ProcessOutgoingMessages() {
+bool Channel::ChannelImpl::ProcessOutgoingMessages() {
DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
// no connection?
@@ -384,7 +370,7 @@ bool Channel::ProcessOutgoingMessages() {
return true;
}
-bool Channel::Send(Message* message) {
+bool Channel::ChannelImpl::Send(Message* message) {
chrome::Counters::ipc_send_counter().Increment();
#ifdef IPC_MESSAGE_DEBUG_EXTRA
DLOG(INFO) << "sending message @" << message << " on channel @" << this
@@ -409,7 +395,7 @@ bool Channel::Send(Message* message) {
}
// Called by libevent when we can read from th pipe without blocking.
-void Channel::OnFileReadReady(int fd) {
+void Channel::ChannelImpl::OnFileReadReady(int fd) {
bool send_server_hello_msg = false;
if (waiting_connect_ && mode_ == MODE_SERVER) {
if (!ServerAcceptFifoConnection(server_listen_pipe_, &pipe_)) {
@@ -449,14 +435,14 @@ void Channel::OnFileReadReady(int fd) {
}
// Called by libevent when we can write to the pipe without blocking.
-void Channel::OnFileWriteReady(int fd) {
+void Channel::ChannelImpl::OnFileWriteReady(int fd) {
if (!ProcessOutgoingMessages()) {
Close();
listener_->OnChannelError();
}
}
-void Channel::Close() {
+void Channel::ChannelImpl::Close() {
// Close can be called multiple time, so we need to make sure we're
// idempotent.
@@ -501,4 +487,31 @@ void Channel::Close() {
}
}
+//------------------------------------------------------------------------------
+// Channel's methods simply call through to ChannelImpl.
+Channel::Channel(const std::wstring& channel_id, Mode mode,
+ Listener* listener)
+ : channel_impl_(new ChannelImpl(channel_id, mode, listener)) {
+}
+
+Channel::~Channel() {
+ delete channel_impl_;
+}
+
+bool Channel::Connect() {
+ return channel_impl_->Connect();
+}
+
+void Channel::Close() {
+ channel_impl_->Close();
+}
+
+void Channel::set_listener(Listener* listener) {
+ channel_impl_->set_listener(listener);
+}
+
+bool Channel::Send(Message* message) {
+ return channel_impl_->Send(message);
+}
+
} // namespace IPC
diff --git a/chrome/common/ipc_channel_posix.h b/chrome/common/ipc_channel_posix.h
new file mode 100644
index 0000000..b2849dc
--- /dev/null
+++ b/chrome/common/ipc_channel_posix.h
@@ -0,0 +1,93 @@
+// Copyright (c) 2008 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_POSIX_H_
+#define CHROME_COMMON_IPC_CHANNEL_POSIX_H_
+
+#include "chrome/common/ipc_channel.h"
+
+#include <queue>
+#include <string>
+
+#include "base/message_loop.h"
+#include "third_party/libevent/event.h"
+
+namespace IPC {
+
+class Channel::ChannelImpl : public MessageLoopForIO::FileWatcher {
+ public:
+ // Mirror methods of Channel, see ipc_channel.h for description.
+ ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
+ ~ChannelImpl() { Close(); }
+ bool Connect();
+ void Close();
+ void set_listener(Listener* listener) { listener_ = listener; }
+ bool Send(Message* message);
+ private:
+ const std::wstring PipeName(const std::wstring& channel_id) const;
+ bool CreatePipe(const std::wstring& channel_id, Mode mode);
+
+ bool ProcessIncomingMessages();
+ bool ProcessOutgoingMessages();
+
+ void OnFileReadReady(int fd);
+ void OnFileWriteReady(int fd);
+
+ Mode mode_;
+
+ // Wrapper for Libevent event.
+ // TODO(playmobil): MessageLoopForIO needs to better encapsulate libevent.
+ struct EventHolder {
+ EventHolder() : is_active(false) {}
+ ~EventHolder() {}
+
+ bool is_active;
+
+ // libevent's set functions set all the needed members of this struct, so no
+ // need to initialize before use.
+ struct event event;
+ };
+
+ EventHolder *server_listen_connection_event_;
+ EventHolder *read_event_;
+ EventHolder *write_event_;
+
+ // If sending a message blocks then we use this variable
+ // to keep track of where we are.
+ size_t message_send_bytes_written_;
+
+ int server_listen_pipe_;
+ int pipe_;
+ std::string pipe_name_;
+
+ Listener* listener_;
+
+ // Messages to be sent are queued here.
+ std::queue<Message*> output_queue_;
+
+ // We read from the pipe into this buffer
+ char input_buf_[Channel::kReadBufferSize];
+
+ // Large messages that span multiple pipe buffers, get built-up using
+ // this buffer.
+ std::string input_overflow_buf_;
+
+ // In server-mode, we have to wait for the client to connect before we
+ // can begin reading. We make use of the input_state_ when performing
+ // the connect operation in overlapped mode.
+ bool waiting_connect_;
+
+ // This flag is set when processing incoming messages. It is used to
+ // avoid recursing through ProcessIncomingMessages, which could cause
+ // problems. TODO(darin): make this unnecessary
+ bool processing_incoming_;
+
+ ScopedRunnableMethodFactory<ChannelImpl> factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
+};
+
+} // namespace IPC
+
+#endif // CHROME_COMMON_IPC_CHANNEL_POSIX_H_
diff --git a/chrome/common/ipc_channel_proxy.h b/chrome/common/ipc_channel_proxy.h
index 2b08c09..0b88cb7 100644
--- a/chrome/common/ipc_channel_proxy.h
+++ b/chrome/common/ipc_channel_proxy.h
@@ -10,6 +10,8 @@
#include "base/ref_counted.h"
#include "chrome/common/ipc_channel.h"
+class MessageLoop;
+
namespace IPC {
//-----------------------------------------------------------------------------
diff --git a/chrome/common/ipc_channel.cc b/chrome/common/ipc_channel_win.cc
index 4ffadc3..a38305a 100644
--- a/chrome/common/ipc_channel.cc
+++ b/chrome/common/ipc_channel_win.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/common/ipc_channel.h"
+#include "chrome/common/ipc_channel_win.h"
#include <windows.h>
#include <sstream>
@@ -14,24 +14,23 @@
#include "chrome/common/ipc_logging.h"
#include "chrome/common/ipc_message_utils.h"
-using namespace std;
-
namespace IPC {
-
//------------------------------------------------------------------------------
-Channel::State::State(Channel* channel) : is_pending(false) {
+Channel::ChannelImpl::State::State(ChannelImpl* channel) : is_pending(false) {
memset(&context.overlapped, 0, sizeof(context.overlapped));
context.handler = channel;
}
-Channel::State::~State() {
- COMPILE_ASSERT(!offsetof(Channel::State, context), starts_with_io_context);
+Channel::ChannelImpl::State::~State() {
+ COMPILE_ASSERT(!offsetof(Channel::ChannelImpl::State, context),
+ starts_with_io_context);
}
//------------------------------------------------------------------------------
-Channel::Channel(const wstring& channel_id, Mode mode, Listener* listener)
+Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
+ Listener* listener)
: ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)),
pipe_(INVALID_HANDLE_VALUE),
@@ -46,7 +45,7 @@ Channel::Channel(const wstring& channel_id, Mode mode, Listener* listener)
}
}
-void Channel::Close() {
+void Channel::ChannelImpl::Close() {
bool waited = false;
if (input_state_.is_pending || output_state_.is_pending) {
CancelIo(pipe_);
@@ -77,7 +76,7 @@ void Channel::Close() {
}
}
-bool Channel::Send(Message* message) {
+bool Channel::ChannelImpl::Send(Message* message) {
chrome::Counters::ipc_send_counter().Increment();
#ifdef IPC_MESSAGE_DEBUG_EXTRA
DLOG(INFO) << "sending message @" << message << " on channel @" << this
@@ -101,16 +100,18 @@ bool Channel::Send(Message* message) {
return true;
}
-const wstring Channel::PipeName(const wstring& channel_id) const {
- wostringstream ss;
+const std::wstring Channel::ChannelImpl::PipeName(const std::wstring& channel_id)
+ const {
+ std::wostringstream ss;
// XXX(darin): get application name from somewhere else
ss << L"\\\\.\\pipe\\chrome." << channel_id;
return ss.str();
}
-bool Channel::CreatePipe(const wstring& channel_id, Mode mode) {
+bool Channel::ChannelImpl::CreatePipe(const std::wstring& channel_id,
+ Mode mode) {
DCHECK(pipe_ == INVALID_HANDLE_VALUE);
- const wstring pipe_name = PipeName(channel_id);
+ const std::wstring pipe_name = PipeName(channel_id);
if (mode == MODE_SERVER) {
SECURITY_ATTRIBUTES security_attributes = {0};
security_attributes.bInheritHandle = FALSE;
@@ -126,8 +127,10 @@ bool Channel::CreatePipe(const wstring& channel_id, Mode mode) {
FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
1, // number of pipe instances
- BUF_SIZE, // output buffer size (XXX tune)
- BUF_SIZE, // input buffer size (XXX tune)
+ // output buffer size (XXX tune)
+ Channel::kReadBufferSize,
+ // input buffer size (XXX tune)
+ Channel::kReadBufferSize,
5000, // timeout in milliseconds (XXX tune)
&security_attributes);
LocalFree(security_attributes.lpSecurityDescriptor);
@@ -161,7 +164,7 @@ bool Channel::CreatePipe(const wstring& channel_id, Mode mode) {
return true;
}
-bool Channel::Connect() {
+bool Channel::ChannelImpl::Connect() {
DLOG(WARNING) << "Connect called twice";
if (pipe_ == INVALID_HANDLE_VALUE)
@@ -178,7 +181,7 @@ bool Channel::Connect() {
// to true, we indicate to OnIOCompleted that this is the special
// initialization signal.
MessageLoopForIO::current()->PostTask(FROM_HERE, factory_.NewRunnableMethod(
- &Channel::OnIOCompleted, &input_state_.context, 0, 0));
+ &Channel::ChannelImpl::OnIOCompleted, &input_state_.context, 0, 0));
}
if (!waiting_connect_)
@@ -186,7 +189,7 @@ bool Channel::Connect() {
return true;
}
-bool Channel::ProcessConnection() {
+bool Channel::ChannelImpl::ProcessConnection() {
if (input_state_.is_pending)
input_state_.is_pending = false;
@@ -219,8 +222,9 @@ bool Channel::ProcessConnection() {
return true;
}
-bool Channel::ProcessIncomingMessages(MessageLoopForIO::IOContext* context,
- DWORD bytes_read) {
+bool Channel::ChannelImpl::ProcessIncomingMessages(
+ MessageLoopForIO::IOContext* context,
+ DWORD bytes_read) {
if (input_state_.is_pending) {
input_state_.is_pending = false;
DCHECK(context);
@@ -240,7 +244,7 @@ bool Channel::ProcessIncomingMessages(MessageLoopForIO::IOContext* context,
// Read from pipe...
BOOL ok = ReadFile(pipe_,
input_buf_,
- BUF_SIZE,
+ Channel::kReadBufferSize,
&bytes_read,
&input_state_.context.overlapped);
if (!ok) {
@@ -304,8 +308,9 @@ bool Channel::ProcessIncomingMessages(MessageLoopForIO::IOContext* context,
return true;
}
-bool Channel::ProcessOutgoingMessages(MessageLoopForIO::IOContext* context,
- DWORD bytes_written) {
+bool Channel::ChannelImpl::ProcessOutgoingMessages(
+ MessageLoopForIO::IOContext* context,
+ DWORD bytes_written) {
DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
// no connection?
@@ -362,7 +367,7 @@ bool Channel::ProcessOutgoingMessages(MessageLoopForIO::IOContext* context,
return true;
}
-void Channel::OnIOCompleted(MessageLoopForIO::IOContext* context,
+void Channel::ChannelImpl::OnIOCompleted(MessageLoopForIO::IOContext* context,
DWORD bytes_transfered, DWORD error) {
bool ok;
if (context == &input_state_.context) {
@@ -392,4 +397,31 @@ void Channel::OnIOCompleted(MessageLoopForIO::IOContext* context,
}
}
+//------------------------------------------------------------------------------
+// Channel's methods simply call through to ChannelImpl.
+Channel::Channel(const std::wstring& channel_id, Mode mode,
+ Listener* listener)
+ : channel_impl_(new ChannelImpl(channel_id, mode, listener)) {
+}
+
+Channel::~Channel() {
+ delete channel_impl_;
+}
+
+bool Channel::Connect() {
+ return channel_impl_->Connect();
+}
+
+void Channel::Close() {
+ channel_impl_->Close();
+}
+
+void Channel::set_listener(Listener* listener) {
+ channel_impl_->set_listener(listener);
}
+
+bool Channel::Send(Message* message) {
+ return channel_impl_->Send(message);
+}
+
+} // namespace IPC
diff --git a/chrome/common/ipc_channel_win.h b/chrome/common/ipc_channel_win.h
new file mode 100644
index 0000000..fcd8abe
--- /dev/null
+++ b/chrome/common/ipc_channel_win.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2008 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_WIN_H_
+#define CHROME_COMMON_IPC_CHANNEL_WIN_H_
+
+#include "chrome/common/ipc_channel.h"
+
+#include <queue>
+#include <string>
+
+#include "base/message_loop.h"
+
+namespace IPC {
+
+class Channel::ChannelImpl : public MessageLoopForIO::IOHandler {
+ public:
+ // Mirror methods of Channel, see ipc_channel.h for description.
+ ChannelImpl(const std::wstring& channel_id, Mode mode, Listener* listener);
+ ~ChannelImpl() { Close(); }
+ bool Connect();
+ void Close();
+ void set_listener(Listener* listener) { listener_ = listener; }
+ bool Send(Message* message);
+ private:
+ const std::wstring PipeName(const std::wstring& channel_id) const;
+ bool CreatePipe(const std::wstring& channel_id, Mode mode);
+
+ bool ProcessConnection();
+ bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context,
+ DWORD bytes_read);
+ bool ProcessOutgoingMessages(MessageLoopForIO::IOContext* context,
+ DWORD bytes_written);
+
+ // MessageLoop::IOHandler implementation.
+ virtual void OnIOCompleted(MessageLoopForIO::IOContext* context,
+ DWORD bytes_transfered, DWORD error);
+ private:
+ struct State {
+ explicit State(ChannelImpl* channel);
+ ~State();
+ MessageLoopForIO::IOContext context;
+ bool is_pending;
+ };
+
+ State input_state_;
+ State output_state_;
+
+ HANDLE pipe_;
+
+ Listener* listener_;
+
+ // Messages to be sent are queued here.
+ std::queue<Message*> output_queue_;
+
+ // We read from the pipe into this buffer
+ char input_buf_[Channel::kReadBufferSize];
+
+ // Large messages that span multiple pipe buffers, get built-up using
+ // this buffer.
+ std::string input_overflow_buf_;
+
+ // In server-mode, we have to wait for the client to connect before we
+ // can begin reading. We make use of the input_state_ when performing
+ // the connect operation in overlapped mode.
+ bool waiting_connect_;
+
+ // This flag is set when processing incoming messages. It is used to
+ // avoid recursing through ProcessIncomingMessages, which could cause
+ // problems. TODO(darin): make this unnecessary
+ bool processing_incoming_;
+
+ ScopedRunnableMethodFactory<ChannelImpl> factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChannelImpl);
+};
+
+} // namespace IPC
+
+#endif // CHROME_COMMON_IPC_CHANNEL_WIN_H_
diff --git a/chrome/common/ipc_fuzzing_tests.cc b/chrome/common/ipc_fuzzing_tests.cc
index cec05fb..0c729f8 100644
--- a/chrome/common/ipc_fuzzing_tests.cc
+++ b/chrome/common/ipc_fuzzing_tests.cc
@@ -7,13 +7,13 @@
#include <string>
#include <sstream>
-#include "chrome/common/ipc_tests.h"
-
+#include "base/message_loop.h"
#include "base/platform_thread.h"
#include "base/process_util.h"
#include "chrome/common/ipc_channel.h"
#include "chrome/common/ipc_channel_proxy.h"
#include "chrome/common/ipc_message_utils.h"
+#include "chrome/common/ipc_tests.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/multiprocess_func_list.h"
diff --git a/chrome/common/resource_dispatcher.cc b/chrome/common/resource_dispatcher.cc
index d3c7a33..ecf58e6 100644
--- a/chrome/common/resource_dispatcher.cc
+++ b/chrome/common/resource_dispatcher.cc
@@ -7,6 +7,7 @@
#include "chrome/common/resource_dispatcher.h"
#include "base/basictypes.h"
+#include "base/message_loop.h"
#include "base/shared_memory.h"
#include "base/string_util.h"
#include "chrome/common/render_messages.h"
diff --git a/chrome/common/resource_dispatcher.h b/chrome/common/resource_dispatcher.h
index c290e10..e948045 100644
--- a/chrome/common/resource_dispatcher.h
+++ b/chrome/common/resource_dispatcher.h
@@ -9,6 +9,8 @@
#include <windows.h>
+#include <queue>
+
#include "base/hash_tables.h"
#include "base/task.h"
#include "chrome/common/ipc_channel.h"