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 "ppapi/proxy/resource_message_test_sink.h" 6 7 #include "ppapi/proxy/ppapi_messages.h" 8 #include "ppapi/proxy/resource_message_params.h" 9 #include "ppapi/proxy/serialized_handle.h" 10 11 namespace ppapi { 12 namespace proxy { 13 14 namespace { 15 16 // Backend for GetAllResource[Calls|Replies]Matching. 17 template<class WrapperMessage, class Params> 18 std::vector<std::pair<Params, IPC::Message> > 19 GetAllResourceMessagesMatching(const ResourceMessageTestSink& sink, 20 uint32 id) { 21 std::vector<std::pair<Params, IPC::Message> > result; 22 for (size_t i = 0; i < sink.message_count(); i++) { 23 const IPC::Message* msg = sink.GetMessageAt(i); 24 if (msg->type() == WrapperMessage::ID) { 25 typename WrapperMessage::Param params; 26 WrapperMessage::Read(msg, ¶ms); 27 Params cur_params = params.a; 28 IPC::Message cur_msg = params.b; 29 if (cur_msg.type() == id) { 30 result.push_back(std::make_pair(cur_params, cur_msg)); 31 } 32 } 33 } 34 return result; 35 } 36 37 } // namespace 38 39 ResourceMessageTestSink::ResourceMessageTestSink() { 40 } 41 42 ResourceMessageTestSink::~ResourceMessageTestSink() { 43 } 44 45 bool ResourceMessageTestSink::Send(IPC::Message* msg) { 46 int message_id = 0; 47 scoped_ptr<IPC::MessageReplyDeserializer> reply_deserializer; 48 if (msg->is_sync()) { 49 reply_deserializer.reset( 50 static_cast<IPC::SyncMessage*>(msg)->GetReplyDeserializer()); 51 message_id = IPC::SyncMessage::GetMessageId(*msg); 52 } 53 bool result = IPC::TestSink::Send(msg); // Deletes |msg|. 54 if (sync_reply_msg_.get()) { 55 // |sync_reply_msg_| should always be a reply to the pending sync message. 56 DCHECK(IPC::SyncMessage::IsMessageReplyTo(*sync_reply_msg_.get(), 57 message_id)); 58 reply_deserializer->SerializeOutputParameters(*sync_reply_msg_.get()); 59 sync_reply_msg_.reset(NULL); 60 } 61 return result; 62 } 63 64 void ResourceMessageTestSink::SetSyncReplyMessage(IPC::Message* reply_msg) { 65 DCHECK(!sync_reply_msg_.get()); 66 sync_reply_msg_.reset(reply_msg); 67 } 68 69 bool ResourceMessageTestSink::GetFirstResourceCallMatching( 70 uint32 id, 71 ResourceMessageCallParams* params, 72 IPC::Message* nested_msg) const { 73 ResourceCallVector matching_messages = 74 GetAllResourceMessagesMatching<PpapiHostMsg_ResourceCall, 75 ResourceMessageCallParams>(*this, id); 76 if (matching_messages.empty()) 77 return false; 78 79 *params = matching_messages[0].first; 80 *nested_msg = matching_messages[0].second; 81 return true; 82 } 83 84 bool ResourceMessageTestSink::GetFirstResourceReplyMatching( 85 uint32 id, 86 ResourceMessageReplyParams* params, 87 IPC::Message* nested_msg) { 88 ResourceReplyVector matching_messages = 89 GetAllResourceMessagesMatching<PpapiPluginMsg_ResourceReply, 90 ResourceMessageReplyParams>(*this, id); 91 if (matching_messages.empty()) 92 return false; 93 94 *params = matching_messages[0].first; 95 *nested_msg = matching_messages[0].second; 96 return true; 97 } 98 99 ResourceMessageTestSink::ResourceCallVector 100 ResourceMessageTestSink::GetAllResourceCallsMatching(uint32 id) { 101 return GetAllResourceMessagesMatching<PpapiHostMsg_ResourceCall, 102 ResourceMessageCallParams>(*this, id); 103 } 104 105 ResourceMessageTestSink::ResourceReplyVector 106 ResourceMessageTestSink::GetAllResourceRepliesMatching(uint32 id) { 107 return GetAllResourceMessagesMatching<PpapiPluginMsg_ResourceReply, 108 ResourceMessageReplyParams>(*this, id); 109 } 110 111 ResourceSyncCallHandler::ResourceSyncCallHandler( 112 ResourceMessageTestSink* test_sink, 113 uint32 incoming_type, 114 int32_t result, 115 const IPC::Message& reply_msg) 116 : test_sink_(test_sink), 117 incoming_type_(incoming_type), 118 result_(result), 119 serialized_handle_(NULL), 120 reply_msg_(reply_msg) { 121 } 122 123 ResourceSyncCallHandler::~ResourceSyncCallHandler() { 124 } 125 126 bool ResourceSyncCallHandler::OnMessageReceived(const IPC::Message& msg) { 127 if (msg.type() != PpapiHostMsg_ResourceSyncCall::ID) 128 return false; 129 PpapiHostMsg_ResourceSyncCall::Schema::SendParam send_params; 130 bool success = PpapiHostMsg_ResourceSyncCall::ReadSendParam( 131 &msg, &send_params); 132 DCHECK(success); 133 ResourceMessageCallParams call_params = send_params.a; 134 IPC::Message call_msg = send_params.b; 135 if (call_msg.type() != incoming_type_) 136 return false; 137 IPC::Message* wrapper_reply_msg = IPC::SyncMessage::GenerateReply(&msg); 138 ResourceMessageReplyParams reply_params(call_params.pp_resource(), 139 call_params.sequence()); 140 reply_params.set_result(result_); 141 if (serialized_handle_) 142 reply_params.AppendHandle(*serialized_handle_); 143 PpapiHostMsg_ResourceSyncCall::WriteReplyParams( 144 wrapper_reply_msg, reply_params, reply_msg_); 145 test_sink_->SetSyncReplyMessage(wrapper_reply_msg); 146 147 // Stash a copy of the message for inspection later. 148 last_handled_msg_ = call_msg; 149 return true; 150 } 151 152 } // namespace proxy 153 } // namespace ppapi 154