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