• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
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/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"
17 
18 namespace {
19 
20 struct WaitableEventLazyInstanceTraits
21     : public base::DefaultLazyInstanceTraits<base::WaitableEvent> {
New__anon82bc8bfd0111::WaitableEventLazyInstanceTraits22   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);
25   }
26 };
27 
28 base::LazyInstance<base::WaitableEvent, WaitableEventLazyInstanceTraits>
29     dummy_event = LAZY_INSTANCE_INITIALIZER;
30 
31 base::StaticAtomicSequenceNumber g_next_id;
32 
33 }  // namespace
34 
35 namespace IPC {
36 
37 #define kSyncMessageHeaderSize 4
38 
SyncMessage(int32 routing_id,uint32 type,PriorityValue priority,MessageReplyDeserializer * deserializer)39 SyncMessage::SyncMessage(
40     int32 routing_id,
41     uint32 type,
42     PriorityValue priority,
43     MessageReplyDeserializer* deserializer)
44     : Message(routing_id, type, priority),
45       deserializer_(deserializer),
46       pump_messages_event_(NULL)
47       {
48   set_sync();
49   set_unblock(true);
50 
51   // Add synchronous message data before the message payload.
52   SyncHeader header;
53   header.message_id = g_next_id.GetNext();
54   WriteSyncHeader(this, header);
55 }
56 
~SyncMessage()57 SyncMessage::~SyncMessage() {
58 }
59 
GetReplyDeserializer()60 MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() {
61   DCHECK(deserializer_.get());
62   return deserializer_.release();
63 }
64 
EnableMessagePumping()65 void SyncMessage::EnableMessagePumping() {
66   DCHECK(!pump_messages_event_);
67   set_pump_messages_event(dummy_event.Pointer());
68 }
69 
IsMessageReplyTo(const Message & msg,int request_id)70 bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) {
71   if (!msg.is_reply())
72     return false;
73 
74   return GetMessageId(msg) == request_id;
75 }
76 
GetDataIterator(const Message * msg)77 PickleIterator SyncMessage::GetDataIterator(const Message* msg) {
78   PickleIterator iter(*msg);
79   if (!iter.SkipBytes(kSyncMessageHeaderSize))
80     return PickleIterator();
81   else
82     return iter;
83 }
84 
GetMessageId(const Message & msg)85 int SyncMessage::GetMessageId(const Message& msg) {
86   if (!msg.is_sync() && !msg.is_reply())
87     return 0;
88 
89   SyncHeader header;
90   if (!ReadSyncHeader(msg, &header))
91     return 0;
92 
93   return header.message_id;
94 }
95 
GenerateReply(const Message * msg)96 Message* SyncMessage::GenerateReply(const Message* msg) {
97   DCHECK(msg->is_sync());
98 
99   Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID,
100                                msg->priority());
101   reply->set_reply();
102 
103   SyncHeader header;
104 
105   // use the same message id, but this time reply bit is set
106   header.message_id = GetMessageId(*msg);
107   WriteSyncHeader(reply, header);
108 
109   return reply;
110 }
111 
ReadSyncHeader(const Message & msg,SyncHeader * header)112 bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) {
113   DCHECK(msg.is_sync() || msg.is_reply());
114 
115   PickleIterator iter(msg);
116   bool result = msg.ReadInt(&iter, &header->message_id);
117   if (!result) {
118     NOTREACHED();
119     return false;
120   }
121 
122   return true;
123 }
124 
WriteSyncHeader(Message * msg,const SyncHeader & header)125 bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) {
126   DCHECK(msg->is_sync() || msg->is_reply());
127   DCHECK(msg->payload_size() == 0);
128   bool result = msg->WriteInt(header.message_id);
129   if (!result) {
130     NOTREACHED();
131     return false;
132   }
133 
134   // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
135   DCHECK(kSyncMessageHeaderSize == msg->payload_size());
136 
137   return true;
138 }
139 
140 
SerializeOutputParameters(const Message & msg)141 bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) {
142   return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg));
143 }
144 
145 }  // namespace IPC
146