ipc_channel_win.h (5244B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 // Copyright (c) 2008 The Chromium Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 #ifndef CHROME_COMMON_IPC_CHANNEL_WIN_H_ 8 #define CHROME_COMMON_IPC_CHANNEL_WIN_H_ 9 10 #include "chrome/common/ipc_channel.h" 11 #include "chrome/common/ipc_message.h" 12 13 #include <atomic> 14 15 #include "base/message_loop.h" 16 #include "base/process.h" 17 #include "base/task.h" 18 #include "nsISupportsImpl.h" 19 20 #include "mozilla/EventTargetCapability.h" 21 #include "mozilla/Maybe.h" 22 #include "mozilla/EventTargetAndLockCapability.h" 23 #include "mozilla/Mutex.h" 24 #include "mozilla/Queue.h" 25 #include "mozilla/UniquePtr.h" 26 27 namespace IPC { 28 29 class ChannelWin : public Channel, public MessageLoopForIO::IOHandler { 30 public: 31 ChannelWin(mozilla::UniqueFileHandle pipe, Mode mode, 32 base::ProcessId other_pid); 33 34 bool Connect(Listener* listener) MOZ_EXCLUDES(SendMutex()) override; 35 void Close() MOZ_EXCLUDES(SendMutex()) override; 36 // NOTE: `Send` may be called on threads other than the I/O thread. 37 bool Send(mozilla::UniquePtr<Message> message) 38 MOZ_EXCLUDES(SendMutex()) override; 39 40 void SetOtherPid(base::ProcessId other_pid) override; 41 42 const ChannelKind* GetKind() const override { return &sKind; } 43 44 static const ChannelKind sKind; 45 46 private: 47 ~ChannelWin() { 48 IOThread().AssertOnCurrentThread(); 49 if (pipe_ != INVALID_HANDLE_VALUE || 50 other_process_ != INVALID_HANDLE_VALUE) { 51 Close(); 52 } 53 } 54 55 static bool CreateRawPipe(ChannelHandle* server, ChannelHandle* client); 56 static uint32_t NumRelayedAttachments(const IPC::Message& message); 57 static bool IsValidHandle(const ChannelHandle& handle); 58 59 void Init(Mode mode) MOZ_REQUIRES(SendMutex(), IOThread()); 60 61 void OutputQueuePush(mozilla::UniquePtr<Message> msg) 62 MOZ_REQUIRES(SendMutex()); 63 void OutputQueuePop() MOZ_REQUIRES(SendMutex()); 64 65 bool EnqueueHelloMessage() MOZ_REQUIRES(SendMutex(), IOThread()); 66 void MaybeOpenProcessHandle() MOZ_REQUIRES(SendMutex(), IOThread()); 67 void CloseLocked() MOZ_REQUIRES(SendMutex(), IOThread()); 68 69 bool ProcessIncomingMessages(MessageLoopForIO::IOContext* context, 70 DWORD bytes_read, bool was_pending) 71 MOZ_REQUIRES(IOThread()); 72 bool ProcessOutgoingMessages(MessageLoopForIO::IOContext* context, 73 DWORD bytes_written, bool was_pending) 74 MOZ_REQUIRES(SendMutex()); 75 76 // Called on a Message immediately before it is sent/recieved to transfer 77 // handles to the remote process, or accept handles from the remote process. 78 bool AcceptHandles(Message& msg) MOZ_REQUIRES(IOThread()); 79 bool TransferHandles(Message& msg) MOZ_REQUIRES(SendMutex()); 80 81 // MessageLoop::IOHandler implementation. 82 virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, 83 DWORD bytes_transfered, DWORD error); 84 85 private: 86 Mode mode_ MOZ_GUARDED_BY(chan_cap_); 87 88 struct State { 89 explicit State(ChannelWin* channel); 90 ~State(); 91 MessageLoopForIO::IOContext context; 92 // When there is pending I/O, this holds a strong reference to the 93 // ChannelWin to prevent it from going away. 94 RefPtr<ChannelWin> is_pending; 95 }; 96 97 State input_state_ MOZ_GUARDED_BY(IOThread()); 98 State output_state_ MOZ_GUARDED_BY(SendMutex()); 99 100 HANDLE pipe_ MOZ_GUARDED_BY(chan_cap_) = INVALID_HANDLE_VALUE; 101 102 Listener* listener_ MOZ_GUARDED_BY(IOThread()) = nullptr; 103 104 // Messages to be sent are queued here. 105 mozilla::Queue<mozilla::UniquePtr<Message>, 64> output_queue_ 106 MOZ_GUARDED_BY(SendMutex()); 107 108 // If sending a message blocks then we use this iterator to keep track of 109 // where in the message we are. It gets reset when the message is finished 110 // sending. 111 mozilla::Maybe<Pickle::BufferList::IterImpl> partial_write_iter_ 112 MOZ_GUARDED_BY(SendMutex()); 113 114 // We read from the pipe into this buffer 115 mozilla::UniquePtr<char[]> input_buf_ MOZ_GUARDED_BY(IOThread()); 116 size_t input_buf_offset_ MOZ_GUARDED_BY(IOThread()) = 0; 117 118 // Large incoming messages that span multiple pipe buffers get built-up in the 119 // buffers of this message. 120 mozilla::UniquePtr<Message> incoming_message_ MOZ_GUARDED_BY(IOThread()); 121 122 // Will be set to `true` until `Connect()` has been called. 123 bool waiting_connect_ MOZ_GUARDED_BY(chan_cap_) = true; 124 125 // This flag is set when processing incoming messages. It is used to 126 // avoid recursing through ProcessIncomingMessages, which could cause 127 // problems. TODO(darin): make this unnecessary 128 bool processing_incoming_ MOZ_GUARDED_BY(IOThread()) = false; 129 130 // We keep track of the PID of the other side of this channel so that we can 131 // record this when generating logs of IPC messages. 132 base::ProcessId other_pid_ MOZ_GUARDED_BY(chan_cap_) = 133 base::kInvalidProcessId; 134 135 // A privileged process handle used to transfer HANDLEs to and from the remote 136 // process. This will only be used if `mode_ == MODE_BROKER_SERVER`. 137 HANDLE other_process_ MOZ_GUARDED_BY(chan_cap_) = INVALID_HANDLE_VALUE; 138 }; 139 140 } // namespace IPC 141 142 #endif // CHROME_COMMON_IPC_CHANNEL_WIN_H_