diff options
Diffstat (limited to 'ipc/chromium/src/chrome/common/ipc_channel_win.h')
-rw-r--r-- | ipc/chromium/src/chrome/common/ipc_channel_win.h | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/ipc/chromium/src/chrome/common/ipc_channel_win.h b/ipc/chromium/src/chrome/common/ipc_channel_win.h new file mode 100644 index 0000000000..5c141ebe34 --- /dev/null +++ b/ipc/chromium/src/chrome/common/ipc_channel_win.h @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +// 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 "chrome/common/ipc_channel_capability.h" +#include "chrome/common/ipc_message.h" + +#include <atomic> +#include <string> + +#include "base/message_loop.h" +#include "base/task.h" +#include "nsISupportsImpl.h" + +#include "mozilla/EventTargetCapability.h" +#include "mozilla/Maybe.h" +#include "mozilla/Mutex.h" +#include "mozilla/Queue.h" +#include "mozilla/UniquePtr.h" + +namespace IPC { + +class Channel::ChannelImpl : public MessageLoopForIO::IOHandler { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET( + ChannelImpl, IOThread().GetEventTarget()); + + using ChannelId = Channel::ChannelId; + using ChannelHandle = Channel::ChannelHandle; + + // Mirror methods of Channel, see ipc_channel.h for description. + ChannelImpl(const ChannelId& channel_id, Mode mode, Listener* listener); + ChannelImpl(ChannelHandle pipe, Mode mode, Listener* listener); + bool Connect() MOZ_EXCLUDES(SendMutex()); + void Close() MOZ_EXCLUDES(SendMutex()); + void StartAcceptingHandles(Mode mode) MOZ_EXCLUDES(SendMutex()); + Listener* set_listener(Listener* listener) { + IOThread().AssertOnCurrentThread(); + chan_cap_.NoteOnIOThread(); + Listener* old = listener_; + listener_ = listener; + return old; + } + // NOTE: `Send` may be called on threads other than the I/O thread. + bool Send(mozilla::UniquePtr<Message> message) MOZ_EXCLUDES(SendMutex()); + + int32_t OtherPid() { + IOThread().AssertOnCurrentThread(); + chan_cap_.NoteOnIOThread(); + return other_pid_; + } + + // See the comment in ipc_channel.h for info on IsClosed() + // NOTE: `IsClosed` may be called on threads other than the I/O thread. + bool IsClosed() MOZ_EXCLUDES(SendMutex()) { + mozilla::MutexAutoLock lock(SendMutex()); + chan_cap_.NoteSendMutex(); + return pipe_ == INVALID_HANDLE_VALUE; + } + + private: + ~ChannelImpl() { + IOThread().AssertOnCurrentThread(); + if (pipe_ != INVALID_HANDLE_VALUE || + other_process_ != INVALID_HANDLE_VALUE) { + Close(); + } + } + + void Init(Mode mode, Listener* listener) + MOZ_REQUIRES(SendMutex(), IOThread()); + + void OutputQueuePush(mozilla::UniquePtr<Message> msg) + MOZ_REQUIRES(SendMutex()); + void OutputQueuePop() MOZ_REQUIRES(SendMutex()); + + const ChannelId PipeName(const ChannelId& channel_id, int32_t* secret) const; + bool CreatePipe(const ChannelId& channel_id, Mode mode) + MOZ_REQUIRES(SendMutex(), IOThread()); + void SetOtherPid(int other_pid) MOZ_REQUIRES(IOThread()) + MOZ_EXCLUDES(SendMutex()); + bool EnqueueHelloMessage() MOZ_REQUIRES(SendMutex(), IOThread()); + void CloseLocked() MOZ_REQUIRES(SendMutex(), IOThread()); + + bool ProcessConnection() MOZ_REQUIRES(SendMutex(), IOThread()); + bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context, + DWORD bytes_read, bool was_pending) + MOZ_REQUIRES(IOThread()); + bool ProcessOutgoingMessages(MessageLoopForIO::IOContext* context, + DWORD bytes_written, bool was_pending) + MOZ_REQUIRES(SendMutex()); + + // Called on a Message immediately before it is sent/recieved to transfer + // handles to the remote process, or accept handles from the remote process. + bool AcceptHandles(Message& msg) MOZ_REQUIRES(IOThread()); + bool TransferHandles(Message& msg) MOZ_REQUIRES(SendMutex()); + + // MessageLoop::IOHandler implementation. + virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, + DWORD bytes_transfered, DWORD error); + + const ChannelCapability::Thread& IOThread() const + MOZ_RETURN_CAPABILITY(chan_cap_.IOThread()) { + return chan_cap_.IOThread(); + } + + ChannelCapability::Mutex& SendMutex() + MOZ_RETURN_CAPABILITY(chan_cap_.SendMutex()) { + return chan_cap_.SendMutex(); + } + + private: + // Compound capability of a Mutex and the IO thread. + ChannelCapability chan_cap_; + + Mode mode_ MOZ_GUARDED_BY(IOThread()); + + struct State { + explicit State(ChannelImpl* channel); + ~State(); + MessageLoopForIO::IOContext context; + // When there is pending I/O, this holds a strong reference to the + // ChannelImpl to prevent it from going away. + RefPtr<ChannelImpl> is_pending; + }; + + State input_state_ MOZ_GUARDED_BY(IOThread()); + State output_state_ MOZ_GUARDED_BY(SendMutex()); + + HANDLE pipe_ MOZ_GUARDED_BY(chan_cap_) = INVALID_HANDLE_VALUE; + + Listener* listener_ MOZ_GUARDED_BY(IOThread()) = nullptr; + + // Messages to be sent are queued here. + mozilla::Queue<mozilla::UniquePtr<Message>, 64> output_queue_ + MOZ_GUARDED_BY(SendMutex()); + + // If sending a message blocks then we use this iterator to keep track of + // where in the message we are. It gets reset when the message is finished + // sending. + mozilla::Maybe<Pickle::BufferList::IterImpl> partial_write_iter_ + MOZ_GUARDED_BY(SendMutex()); + + // We read from the pipe into this buffer + mozilla::UniquePtr<char[]> input_buf_ MOZ_GUARDED_BY(IOThread()); + size_t input_buf_offset_ MOZ_GUARDED_BY(IOThread()) = 0; + + // Large incoming messages that span multiple pipe buffers get built-up in the + // buffers of this message. + mozilla::UniquePtr<Message> incoming_message_ MOZ_GUARDED_BY(IOThread()); + + // Timer started when a MODE_SERVER channel begins waiting for a connection, + // and cancelled when the connection completes. Will produce an error if no + // connection occurs before the timeout. + nsCOMPtr<nsITimer> connect_timeout_ MOZ_GUARDED_BY(IOThread()); + + // Will be set to `true` until `Connect()` has been called, and, if in + // server-mode, the client has connected. The `input_state_` is used to wait + // for the client to connect in overlapped mode. + bool waiting_connect_ MOZ_GUARDED_BY(chan_cap_) = true; + + // 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_ MOZ_GUARDED_BY(IOThread()) = false; + + // We keep track of the PID of the other side of this channel so that we can + // record this when generating logs of IPC messages. + int32_t other_pid_ MOZ_GUARDED_BY(chan_cap_) = -1; + + // This is a unique per-channel value used to authenticate the client end of + // a connection. If the value is non-zero, the client passes it in the hello + // and the host validates. (We don't send the zero value to preserve IPC + // compatibility with existing clients that don't validate the channel.) + int32_t shared_secret_ MOZ_GUARDED_BY(IOThread()) = 0; + + // In server-mode, we wait for the channel at the other side of the pipe to + // send us back our shared secret, if we are using one. + bool waiting_for_shared_secret_ MOZ_GUARDED_BY(IOThread()) = false; + + // Whether or not to accept handles from a remote process, and whether this + // process is the privileged side of a IPC::Channel which can transfer + // handles. + bool accept_handles_ MOZ_GUARDED_BY(chan_cap_) = false; + bool privileged_ MOZ_GUARDED_BY(chan_cap_) = false; + + // A privileged process handle used to transfer HANDLEs to and from the remote + // process. This will only be used if `privileged_` is set. + HANDLE other_process_ MOZ_GUARDED_BY(chan_cap_) = INVALID_HANDLE_VALUE; + + DISALLOW_COPY_AND_ASSIGN(ChannelImpl); +}; + +} // namespace IPC + +#endif // CHROME_COMMON_IPC_CHANNEL_WIN_H_ |