1 : // Copyright (c) 2006-2008 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.
4 :
5 : #include "build/build_config.h"
6 :
7 : #if defined(OS_WIN)
8 : #include <windows.h>
9 : #endif
10 : #include <stack>
11 :
12 : #include "base/logging.h"
13 : #include "base/waitable_event.h"
14 : #include "chrome/common/ipc_sync_message.h"
15 :
16 : namespace IPC {
17 :
18 : uint32 SyncMessage::next_id_ = 0;
19 : #define kSyncMessageHeaderSize 4
20 :
21 1464 : base::WaitableEvent* dummy_event = new base::WaitableEvent(true, true);
22 :
23 0 : SyncMessage::SyncMessage(
24 : int32 routing_id,
25 : uint16 type,
26 : PriorityValue priority,
27 : MessageReplyDeserializer* deserializer)
28 : : Message(routing_id, type, priority),
29 : deserializer_(deserializer),
30 0 : pump_messages_event_(NULL)
31 : {
32 0 : set_sync();
33 0 : set_unblock(true);
34 :
35 : // Add synchronous message data before the message payload.
36 : SyncHeader header;
37 0 : header.message_id = ++next_id_;
38 0 : WriteSyncHeader(this, header);
39 0 : }
40 :
41 0 : MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() {
42 0 : MessageReplyDeserializer* rv = deserializer_;
43 0 : DCHECK(rv);
44 0 : deserializer_ = NULL;
45 0 : return rv;
46 : }
47 :
48 0 : void SyncMessage::EnableMessagePumping() {
49 0 : DCHECK(!pump_messages_event_);
50 0 : set_pump_messages_event(dummy_event);
51 0 : }
52 :
53 0 : bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) {
54 0 : if (!msg.is_reply())
55 0 : return false;
56 :
57 0 : return GetMessageId(msg) == request_id;
58 : }
59 :
60 0 : void* SyncMessage::GetDataIterator(const Message* msg) {
61 0 : void* iter = const_cast<char*>(msg->payload());
62 0 : UpdateIter(&iter, kSyncMessageHeaderSize);
63 0 : return iter;
64 : }
65 :
66 0 : int SyncMessage::GetMessageId(const Message& msg) {
67 0 : if (!msg.is_sync() && !msg.is_reply())
68 0 : return 0;
69 :
70 : SyncHeader header;
71 0 : if (!ReadSyncHeader(msg, &header))
72 0 : return 0;
73 :
74 0 : return header.message_id;
75 : }
76 :
77 0 : Message* SyncMessage::GenerateReply(const Message* msg) {
78 0 : DCHECK(msg->is_sync());
79 :
80 : Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID,
81 0 : msg->priority());
82 0 : reply->set_reply();
83 :
84 : SyncHeader header;
85 :
86 : // use the same message id, but this time reply bit is set
87 0 : header.message_id = GetMessageId(*msg);
88 0 : WriteSyncHeader(reply, header);
89 :
90 0 : return reply;
91 : }
92 :
93 0 : bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) {
94 0 : DCHECK(msg.is_sync() || msg.is_reply());
95 :
96 0 : void* iter = NULL;
97 0 : bool result = msg.ReadInt(&iter, &header->message_id);
98 0 : if (!result) {
99 0 : NOTREACHED();
100 0 : return false;
101 : }
102 :
103 0 : return true;
104 : }
105 :
106 0 : bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) {
107 0 : DCHECK(msg->is_sync() || msg->is_reply());
108 0 : DCHECK(msg->payload_size() == 0);
109 0 : bool result = msg->WriteInt(header.message_id);
110 0 : if (!result) {
111 0 : NOTREACHED();
112 0 : return false;
113 : }
114 :
115 : // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
116 0 : DCHECK(kSyncMessageHeaderSize == msg->payload_size());
117 :
118 0 : return true;
119 : }
120 :
121 :
122 0 : bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) {
123 0 : return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg));
124 : }
125 :
126 4392 : } // namespace IPC
|