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 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: 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 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 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 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 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 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 131 void RunClosure(const base::Closure& callback, 132 interface_control::RunResponseMessageParamsPtr run_response) { 133 callback.Run(); 134 } 135 136 } // namespace 137 138 ControlMessageProxy::ControlMessageProxy(MessageReceiverWithResponder* receiver) 139 : receiver_(receiver) { 140 } 141 142 ControlMessageProxy::~ControlMessageProxy() = default; 143 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 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 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 176 void ControlMessageProxy::RunFlushForTestingClosure() { 177 DCHECK(!run_loop_quit_closure_.is_null()); 178 base::ResetAndReturn(&run_loop_quit_closure_).Run(); 179 } 180 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