ipc: Add attachment broker code for the privileged browser process.
No intended behavior change.
This CL adds the class AttachmentBrokerPrivilegedWin, a subclass of
AttachmentBroker intended for use in the privileged browser process on the
Windows platform. No brokerable attachments are made outside of tests, so this
code is not yet active.
This CL consists of several changes:
- The class AttachmentBrokerPrivilegedWin was created.
- Common logic between AttachmentBrokerPrivilegedWin and AttachmentBrokerWin
was moved to AttachmentBroker.
- ChannelWin was given a new member prelim_queue_. This queue is normally
empty, but in some circumstances messages are queued here before being
processed for delivery. See the documentation for a full explanation.
BUG=466437
Review URL: https://codereview.chromium.org/1246103006
Cr-Commit-Position: refs/heads/master@{#340548}
diff --git a/ipc/ipc_channel_win.cc b/ipc/ipc_channel_win.cc
index 0a905a8e..a01a272 100644
--- a/ipc/ipc_channel_win.cc
+++ b/ipc/ipc_channel_win.cc
@@ -81,23 +81,38 @@
}
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 @@
#endif
message->TraceMessageBegin();
+
+ // |output_queue_| takes ownership of |message|.
output_queue_.push(message);
// ensure waiting to write
if (!waiting_connect_) {
@@ -118,6 +135,21 @@
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 @@
peer_pid_ = claimed_pid;
// Validation completed.
validate_client_ = false;
+
+ FlushPrelimQueue();
+
listener()->OnChannelConnected(claimed_pid);
}