diff options
Diffstat (limited to 'ipc/ipc_channel_win.cc')
-rw-r--r-- | ipc/ipc_channel_win.cc | 47 |
1 files changed, 41 insertions, 6 deletions
diff --git a/ipc/ipc_channel_win.cc b/ipc/ipc_channel_win.cc index 0a905a8..a01a272 100644 --- a/ipc/ipc_channel_win.cc +++ b/ipc/ipc_channel_win.cc @@ -81,23 +81,38 @@ void ChannelWin::Close() { } bool ChannelWin::Send(Message* message) { - // TODO(erikchen): Remove this DCHECK once ChannelWin fully supports - // brokerable attachments. http://crbug.com/493414. - DCHECK(!message->HasAttachments()); DCHECK(thread_check_->CalledOnValidThread()); DVLOG(2) << "sending message @" << message << " on channel @" << this << " with type " << message->type() << " (" << output_queue_.size() << " in queue)"; + if (!prelim_queue_.empty()) { + prelim_queue_.push(message); + return true; + } + + if (message->HasBrokerableAttachments() && + peer_pid_ == base::kNullProcessId) { + prelim_queue_.push(message); + return true; + } + + return ProcessMessageForDelivery(message); +} + +bool ChannelWin::ProcessMessageForDelivery(Message* message) { // Sending a brokerable attachment requires a call to Channel::Send(), so - // Send() may be re-entrant. Brokered attachments must be sent before the - // Message itself. + // both Send() and ProcessMessageForDelivery() may be re-entrant. Brokered + // attachments must be sent before the Message itself. if (message->HasBrokerableAttachments()) { DCHECK(broker_); + DCHECK(peer_pid_ != base::kNullProcessId); for (const BrokerableAttachment* attachment : message->attachment_set()->PeekBrokerableAttachments()) { - if (!broker_->SendAttachmentToProcess(attachment, peer_pid_)) + if (!broker_->SendAttachmentToProcess(attachment, peer_pid_)) { + delete message; return false; + } } } @@ -106,6 +121,8 @@ bool ChannelWin::Send(Message* message) { #endif message->TraceMessageBegin(); + + // |output_queue_| takes ownership of |message|. output_queue_.push(message); // ensure waiting to write if (!waiting_connect_) { @@ -118,6 +135,21 @@ bool ChannelWin::Send(Message* message) { return true; } +void ChannelWin::FlushPrelimQueue() { + DCHECK_NE(peer_pid_, base::kNullProcessId); + + // Due to the possibly re-entrant nature of ProcessMessageForDelivery(), it + // is critical that |prelim_queue_| appears empty. + std::queue<Message*> prelim_queue; + prelim_queue_.swap(prelim_queue); + + while (!prelim_queue.empty()) { + Message* m = prelim_queue.front(); + ProcessMessageForDelivery(m); + prelim_queue.pop(); + } +} + AttachmentBroker* ChannelWin::GetAttachmentBroker() { return broker_; } @@ -205,6 +237,9 @@ void ChannelWin::HandleInternalMessage(const Message& msg) { peer_pid_ = claimed_pid; // Validation completed. validate_client_ = false; + + FlushPrelimQueue(); + listener()->OnChannelConnected(claimed_pid); } |