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> >
GetAllResourceMessagesMatching(const ResourceMessageTestSink & sink,uint32 id)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
ResourceMessageTestSink()39 ResourceMessageTestSink::ResourceMessageTestSink() {
40 }
41
~ResourceMessageTestSink()42 ResourceMessageTestSink::~ResourceMessageTestSink() {
43 }
44
Send(IPC::Message * msg)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
SetSyncReplyMessage(IPC::Message * reply_msg)64 void ResourceMessageTestSink::SetSyncReplyMessage(IPC::Message* reply_msg) {
65 DCHECK(!sync_reply_msg_.get());
66 sync_reply_msg_.reset(reply_msg);
67 }
68
GetFirstResourceCallMatching(uint32 id,ResourceMessageCallParams * params,IPC::Message * nested_msg) const69 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
GetFirstResourceReplyMatching(uint32 id,ResourceMessageReplyParams * params,IPC::Message * nested_msg)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
GetAllResourceCallsMatching(uint32 id)100 ResourceMessageTestSink::GetAllResourceCallsMatching(uint32 id) {
101 return GetAllResourceMessagesMatching<PpapiHostMsg_ResourceCall,
102 ResourceMessageCallParams>(*this, id);
103 }
104
105 ResourceMessageTestSink::ResourceReplyVector
GetAllResourceRepliesMatching(uint32 id)106 ResourceMessageTestSink::GetAllResourceRepliesMatching(uint32 id) {
107 return GetAllResourceMessagesMatching<PpapiPluginMsg_ResourceReply,
108 ResourceMessageReplyParams>(*this, id);
109 }
110
ResourceSyncCallHandler(ResourceMessageTestSink * test_sink,uint32 incoming_type,int32_t result,const IPC::Message & reply_msg)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
~ResourceSyncCallHandler()123 ResourceSyncCallHandler::~ResourceSyncCallHandler() {
124 }
125
OnMessageReceived(const IPC::Message & msg)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