michael@0: // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "build/build_config.h" michael@0: michael@0: #if defined(OS_WIN) michael@0: #include michael@0: #endif michael@0: #include michael@0: michael@0: #include "base/logging.h" michael@0: #include "base/waitable_event.h" michael@0: #include "chrome/common/ipc_sync_message.h" michael@0: michael@0: namespace IPC { michael@0: michael@0: uint32_t SyncMessage::next_id_ = 0; michael@0: #define kSyncMessageHeaderSize 4 michael@0: michael@0: SyncMessage::SyncMessage( michael@0: int32_t routing_id, michael@0: uint16_t type, michael@0: PriorityValue priority, michael@0: MessageReplyDeserializer* deserializer) michael@0: : Message(routing_id, type, priority), michael@0: deserializer_(deserializer), michael@0: pump_messages_event_(NULL) michael@0: { michael@0: set_sync(); michael@0: set_unblock(true); michael@0: michael@0: // Add synchronous message data before the message payload. michael@0: SyncHeader header; michael@0: header.message_id = ++next_id_; michael@0: WriteSyncHeader(this, header); michael@0: } michael@0: michael@0: MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() { michael@0: MessageReplyDeserializer* rv = deserializer_; michael@0: DCHECK(rv); michael@0: deserializer_ = NULL; michael@0: return rv; michael@0: } michael@0: michael@0: void SyncMessage::EnableMessagePumping() { michael@0: static base::WaitableEvent* dummy_event = new base::WaitableEvent(true, true); michael@0: DCHECK(!pump_messages_event_); michael@0: set_pump_messages_event(dummy_event); michael@0: } michael@0: michael@0: bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) { michael@0: if (!msg.is_reply()) michael@0: return false; michael@0: michael@0: return GetMessageId(msg) == request_id; michael@0: } michael@0: michael@0: void* SyncMessage::GetDataIterator(const Message* msg) { michael@0: void* iter = const_cast(msg->payload()); michael@0: UpdateIter(&iter, kSyncMessageHeaderSize); michael@0: return iter; michael@0: } michael@0: michael@0: int SyncMessage::GetMessageId(const Message& msg) { michael@0: if (!msg.is_sync() && !msg.is_reply()) michael@0: return 0; michael@0: michael@0: SyncHeader header; michael@0: if (!ReadSyncHeader(msg, &header)) michael@0: return 0; michael@0: michael@0: return header.message_id; michael@0: } michael@0: michael@0: Message* SyncMessage::GenerateReply(const Message* msg) { michael@0: DCHECK(msg->is_sync()); michael@0: michael@0: Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID, michael@0: msg->priority()); michael@0: reply->set_reply(); michael@0: michael@0: SyncHeader header; michael@0: michael@0: // use the same message id, but this time reply bit is set michael@0: header.message_id = GetMessageId(*msg); michael@0: WriteSyncHeader(reply, header); michael@0: michael@0: return reply; michael@0: } michael@0: michael@0: bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) { michael@0: DCHECK(msg.is_sync() || msg.is_reply()); michael@0: michael@0: void* iter = NULL; michael@0: bool result = msg.ReadInt(&iter, &header->message_id); michael@0: if (!result) { michael@0: NOTREACHED(); michael@0: return false; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) { michael@0: DCHECK(msg->is_sync() || msg->is_reply()); michael@0: DCHECK(msg->payload_size() == 0); michael@0: bool result = msg->WriteInt(header.message_id); michael@0: if (!result) { michael@0: NOTREACHED(); michael@0: return false; michael@0: } michael@0: michael@0: // Note: if you add anything here, you need to update kSyncMessageHeaderSize. michael@0: DCHECK(kSyncMessageHeaderSize == msg->payload_size()); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: michael@0: bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) { michael@0: return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg)); michael@0: } michael@0: michael@0: } // namespace IPC