Plumb a testing-only API for forcing resizes.
[chromium-blink-merge.git] / ipc / ipc_sync_message.cc
blob52268788fb44c96f5b986b9ee60c62e4b79f8159
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "build/build_config.h"
7 #if defined(OS_WIN)
8 #include <windows.h>
9 #endif
10 #include <stack>
12 #include "base/atomic_sequence_num.h"
13 #include "base/lazy_instance.h"
14 #include "base/logging.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "ipc/ipc_sync_message.h"
18 namespace {
20 struct WaitableEventLazyInstanceTraits
21 : public base::DefaultLazyInstanceTraits<base::WaitableEvent> {
22 static base::WaitableEvent* New(void* instance) {
23 // Use placement new to initialize our instance in our preallocated space.
24 return new (instance) base::WaitableEvent(true, true);
28 base::LazyInstance<base::WaitableEvent, WaitableEventLazyInstanceTraits>
29 dummy_event = LAZY_INSTANCE_INITIALIZER;
31 base::StaticAtomicSequenceNumber g_next_id;
33 } // namespace
35 namespace IPC {
37 #define kSyncMessageHeaderSize 4
39 SyncMessage::SyncMessage(
40 int32 routing_id,
41 uint32 type,
42 MessageReplyDeserializer* deserializer)
43 : Message(routing_id, type),
44 deserializer_(deserializer),
45 pump_messages_event_(NULL)
47 set_sync();
48 set_unblock(true);
50 // Add synchronous message data before the message payload.
51 SyncHeader header;
52 header.message_id = g_next_id.GetNext();
53 WriteSyncHeader(this, header);
56 SyncMessage::~SyncMessage() {
59 MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() {
60 DCHECK(deserializer_.get());
61 return deserializer_.release();
64 void SyncMessage::EnableMessagePumping() {
65 DCHECK(!pump_messages_event_);
66 set_pump_messages_event(dummy_event.Pointer());
69 bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) {
70 if (!msg.is_reply())
71 return false;
73 return GetMessageId(msg) == request_id;
76 PickleIterator SyncMessage::GetDataIterator(const Message* msg) {
77 PickleIterator iter(*msg);
78 if (!iter.SkipBytes(kSyncMessageHeaderSize))
79 return PickleIterator();
80 else
81 return iter;
84 int SyncMessage::GetMessageId(const Message& msg) {
85 if (!msg.is_sync() && !msg.is_reply())
86 return 0;
88 SyncHeader header;
89 if (!ReadSyncHeader(msg, &header))
90 return 0;
92 return header.message_id;
95 Message* SyncMessage::GenerateReply(const Message* msg) {
96 DCHECK(msg->is_sync());
98 Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID);
99 reply->set_reply();
101 SyncHeader header;
103 // use the same message id, but this time reply bit is set
104 header.message_id = GetMessageId(*msg);
105 WriteSyncHeader(reply, header);
107 return reply;
110 bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) {
111 DCHECK(msg.is_sync() || msg.is_reply());
113 PickleIterator iter(msg);
114 bool result = msg.ReadInt(&iter, &header->message_id);
115 if (!result) {
116 NOTREACHED();
117 return false;
120 return true;
123 bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) {
124 DCHECK(msg->is_sync() || msg->is_reply());
125 DCHECK(msg->payload_size() == 0);
126 bool result = msg->WriteInt(header.message_id);
127 if (!result) {
128 NOTREACHED();
129 return false;
132 // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
133 DCHECK(kSyncMessageHeaderSize == msg->payload_size());
135 return true;
139 bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) {
140 return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg));
143 } // namespace IPC