summaryrefslogtreecommitdiffstats
path: root/ipc/ipc_channel_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/ipc_channel_win.cc')
-rw-r--r--ipc/ipc_channel_win.cc47
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);
}