1 // Copyright 2015 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 "mojo/public/cpp/bindings/lib/control_message_proxy.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/macros.h"
14 #include "base/run_loop.h"
15 #include "mojo/public/cpp/bindings/lib/message_builder.h"
16 #include "mojo/public/cpp/bindings/lib/serialization.h"
17 #include "mojo/public/cpp/bindings/lib/validation_util.h"
18 #include "mojo/public/cpp/bindings/message.h"
19 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
20
21 namespace mojo {
22 namespace internal {
23
24 namespace {
25
ValidateControlResponse(Message * message)26 bool ValidateControlResponse(Message* message) {
27 ValidationContext validation_context(message->payload(),
28 message->payload_num_bytes(), 0, 0,
29 message, "ControlResponseValidator");
30 if (!ValidateMessageIsResponse(message, &validation_context))
31 return false;
32
33 switch (message->header()->name) {
34 case interface_control::kRunMessageId:
35 return ValidateMessagePayload<
36 interface_control::internal::RunResponseMessageParams_Data>(
37 message, &validation_context);
38 }
39 return false;
40 }
41
42 using RunCallback =
43 base::Callback<void(interface_control::RunResponseMessageParamsPtr)>;
44
45 class RunResponseForwardToCallback : public MessageReceiver {
46 public:
RunResponseForwardToCallback(const RunCallback & callback)47 explicit RunResponseForwardToCallback(const RunCallback& callback)
48 : callback_(callback) {}
49 bool Accept(Message* message) override;
50
51 private:
52 RunCallback callback_;
53 DISALLOW_COPY_AND_ASSIGN(RunResponseForwardToCallback);
54 };
55
Accept(Message * message)56 bool RunResponseForwardToCallback::Accept(Message* message) {
57 if (!ValidateControlResponse(message))
58 return false;
59
60 interface_control::internal::RunResponseMessageParams_Data* params =
61 reinterpret_cast<
62 interface_control::internal::RunResponseMessageParams_Data*>(
63 message->mutable_payload());
64 interface_control::RunResponseMessageParamsPtr params_ptr;
65 SerializationContext context;
66 Deserialize<interface_control::RunResponseMessageParamsDataView>(
67 params, ¶ms_ptr, &context);
68
69 callback_.Run(std::move(params_ptr));
70 return true;
71 }
72
SendRunMessage(MessageReceiverWithResponder * receiver,interface_control::RunInputPtr input_ptr,const RunCallback & callback)73 void SendRunMessage(MessageReceiverWithResponder* receiver,
74 interface_control::RunInputPtr input_ptr,
75 const RunCallback& callback) {
76 SerializationContext context;
77
78 auto params_ptr = interface_control::RunMessageParams::New();
79 params_ptr->input = std::move(input_ptr);
80 size_t size = PrepareToSerialize<interface_control::RunMessageParamsDataView>(
81 params_ptr, &context);
82 MessageBuilder builder(interface_control::kRunMessageId,
83 Message::kFlagExpectsResponse, size, 0);
84
85 interface_control::internal::RunMessageParams_Data* params = nullptr;
86 Serialize<interface_control::RunMessageParamsDataView>(
87 params_ptr, builder.buffer(), ¶ms, &context);
88 MessageReceiver* responder = new RunResponseForwardToCallback(callback);
89 if (!receiver->AcceptWithResponder(builder.message(), responder))
90 delete responder;
91 }
92
ConstructRunOrClosePipeMessage(interface_control::RunOrClosePipeInputPtr input_ptr)93 Message ConstructRunOrClosePipeMessage(
94 interface_control::RunOrClosePipeInputPtr input_ptr) {
95 SerializationContext context;
96
97 auto params_ptr = interface_control::RunOrClosePipeMessageParams::New();
98 params_ptr->input = std::move(input_ptr);
99
100 size_t size = PrepareToSerialize<
101 interface_control::RunOrClosePipeMessageParamsDataView>(params_ptr,
102 &context);
103 MessageBuilder builder(interface_control::kRunOrClosePipeMessageId, 0, size,
104 0);
105
106 interface_control::internal::RunOrClosePipeMessageParams_Data* params =
107 nullptr;
108 Serialize<interface_control::RunOrClosePipeMessageParamsDataView>(
109 params_ptr, builder.buffer(), ¶ms, &context);
110 return std::move(*builder.message());
111 }
112
SendRunOrClosePipeMessage(MessageReceiverWithResponder * receiver,interface_control::RunOrClosePipeInputPtr input_ptr)113 void SendRunOrClosePipeMessage(
114 MessageReceiverWithResponder* receiver,
115 interface_control::RunOrClosePipeInputPtr input_ptr) {
116 Message message(ConstructRunOrClosePipeMessage(std::move(input_ptr)));
117
118 bool ok = receiver->Accept(&message);
119 ALLOW_UNUSED_LOCAL(ok);
120 }
121
RunVersionCallback(const base::Callback<void (uint32_t)> & callback,interface_control::RunResponseMessageParamsPtr run_response)122 void RunVersionCallback(
123 const base::Callback<void(uint32_t)>& callback,
124 interface_control::RunResponseMessageParamsPtr run_response) {
125 uint32_t version = 0u;
126 if (run_response->output && run_response->output->is_query_version_result())
127 version = run_response->output->get_query_version_result()->version;
128 callback.Run(version);
129 }
130
RunClosure(const base::Closure & callback,interface_control::RunResponseMessageParamsPtr run_response)131 void RunClosure(const base::Closure& callback,
132 interface_control::RunResponseMessageParamsPtr run_response) {
133 callback.Run();
134 }
135
136 } // namespace
137
ControlMessageProxy(MessageReceiverWithResponder * receiver)138 ControlMessageProxy::ControlMessageProxy(MessageReceiverWithResponder* receiver)
139 : receiver_(receiver) {
140 }
141
142 ControlMessageProxy::~ControlMessageProxy() = default;
143
QueryVersion(const base::Callback<void (uint32_t)> & callback)144 void ControlMessageProxy::QueryVersion(
145 const base::Callback<void(uint32_t)>& callback) {
146 auto input_ptr = interface_control::RunInput::New();
147 input_ptr->set_query_version(interface_control::QueryVersion::New());
148 SendRunMessage(receiver_, std::move(input_ptr),
149 base::Bind(&RunVersionCallback, callback));
150 }
151
RequireVersion(uint32_t version)152 void ControlMessageProxy::RequireVersion(uint32_t version) {
153 auto require_version = interface_control::RequireVersion::New();
154 require_version->version = version;
155 auto input_ptr = interface_control::RunOrClosePipeInput::New();
156 input_ptr->set_require_version(std::move(require_version));
157 SendRunOrClosePipeMessage(receiver_, std::move(input_ptr));
158 }
159
FlushForTesting()160 void ControlMessageProxy::FlushForTesting() {
161 if (encountered_error_)
162 return;
163
164 auto input_ptr = interface_control::RunInput::New();
165 input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New());
166 base::RunLoop run_loop;
167 run_loop_quit_closure_ = run_loop.QuitClosure();
168 SendRunMessage(
169 receiver_, std::move(input_ptr),
170 base::Bind(&RunClosure,
171 base::Bind(&ControlMessageProxy::RunFlushForTestingClosure,
172 base::Unretained(this))));
173 run_loop.Run();
174 }
175
RunFlushForTestingClosure()176 void ControlMessageProxy::RunFlushForTestingClosure() {
177 DCHECK(!run_loop_quit_closure_.is_null());
178 base::ResetAndReturn(&run_loop_quit_closure_).Run();
179 }
180
OnConnectionError()181 void ControlMessageProxy::OnConnectionError() {
182 encountered_error_ = true;
183 if (!run_loop_quit_closure_.is_null())
184 RunFlushForTestingClosure();
185 }
186
187 } // namespace internal
188 } // namespace mojo
189