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_handler.h" 6 7 #include <stddef.h> 8 #include <stdint.h> 9 #include <utility> 10 11 #include "base/logging.h" 12 #include "mojo/public/cpp/bindings/lib/message_builder.h" 13 #include "mojo/public/cpp/bindings/lib/serialization.h" 14 #include "mojo/public/cpp/bindings/lib/validation_util.h" 15 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" 16 17 namespace mojo { 18 namespace internal { 19 namespace { 20 21 bool ValidateControlRequestWithResponse(Message* message) { 22 ValidationContext validation_context(message->payload(), 23 message->payload_num_bytes(), 0, 0, 24 message, "ControlRequestValidator"); 25 if (!ValidateMessageIsRequestExpectingResponse(message, &validation_context)) 26 return false; 27 28 switch (message->header()->name) { 29 case interface_control::kRunMessageId: 30 return ValidateMessagePayload< 31 interface_control::internal::RunMessageParams_Data>( 32 message, &validation_context); 33 } 34 return false; 35 } 36 37 bool ValidateControlRequestWithoutResponse(Message* message) { 38 ValidationContext validation_context(message->payload(), 39 message->payload_num_bytes(), 0, 0, 40 message, "ControlRequestValidator"); 41 if (!ValidateMessageIsRequestWithoutResponse(message, &validation_context)) 42 return false; 43 44 switch (message->header()->name) { 45 case interface_control::kRunOrClosePipeMessageId: 46 return ValidateMessageIsRequestWithoutResponse(message, 47 &validation_context) && 48 ValidateMessagePayload< 49 interface_control::internal::RunOrClosePipeMessageParams_Data>( 50 message, &validation_context); 51 } 52 return false; 53 } 54 55 } // namespace 56 57 // static 58 bool ControlMessageHandler::IsControlMessage(const Message* message) { 59 return message->header()->name == interface_control::kRunMessageId || 60 message->header()->name == interface_control::kRunOrClosePipeMessageId; 61 } 62 63 ControlMessageHandler::ControlMessageHandler(uint32_t interface_version) 64 : interface_version_(interface_version) { 65 } 66 67 ControlMessageHandler::~ControlMessageHandler() { 68 } 69 70 bool ControlMessageHandler::Accept(Message* message) { 71 if (!ValidateControlRequestWithoutResponse(message)) 72 return false; 73 74 if (message->header()->name == interface_control::kRunOrClosePipeMessageId) 75 return RunOrClosePipe(message); 76 77 NOTREACHED(); 78 return false; 79 } 80 81 bool ControlMessageHandler::AcceptWithResponder( 82 Message* message, 83 MessageReceiverWithStatus* responder) { 84 if (!ValidateControlRequestWithResponse(message)) 85 return false; 86 87 if (message->header()->name == interface_control::kRunMessageId) 88 return Run(message, responder); 89 90 NOTREACHED(); 91 return false; 92 } 93 94 bool ControlMessageHandler::Run(Message* message, 95 MessageReceiverWithStatus* responder) { 96 interface_control::internal::RunMessageParams_Data* params = 97 reinterpret_cast<interface_control::internal::RunMessageParams_Data*>( 98 message->mutable_payload()); 99 interface_control::RunMessageParamsPtr params_ptr; 100 Deserialize<interface_control::RunMessageParamsDataView>(params, ¶ms_ptr, 101 &context_); 102 auto& input = *params_ptr->input; 103 interface_control::RunOutputPtr output = interface_control::RunOutput::New(); 104 if (input.is_query_version()) { 105 output->set_query_version_result( 106 interface_control::QueryVersionResult::New()); 107 output->get_query_version_result()->version = interface_version_; 108 } else if (input.is_flush_for_testing()) { 109 output.reset(); 110 } else { 111 output.reset(); 112 } 113 114 auto response_params_ptr = interface_control::RunResponseMessageParams::New(); 115 response_params_ptr->output = std::move(output); 116 size_t size = 117 PrepareToSerialize<interface_control::RunResponseMessageParamsDataView>( 118 response_params_ptr, &context_); 119 MessageBuilder builder(interface_control::kRunMessageId, 120 Message::kFlagIsResponse, size, 0); 121 builder.message()->set_request_id(message->request_id()); 122 123 interface_control::internal::RunResponseMessageParams_Data* response_params = 124 nullptr; 125 Serialize<interface_control::RunResponseMessageParamsDataView>( 126 response_params_ptr, builder.buffer(), &response_params, &context_); 127 bool ok = responder->Accept(builder.message()); 128 ALLOW_UNUSED_LOCAL(ok); 129 delete responder; 130 131 return true; 132 } 133 134 bool ControlMessageHandler::RunOrClosePipe(Message* message) { 135 interface_control::internal::RunOrClosePipeMessageParams_Data* params = 136 reinterpret_cast< 137 interface_control::internal::RunOrClosePipeMessageParams_Data*>( 138 message->mutable_payload()); 139 interface_control::RunOrClosePipeMessageParamsPtr params_ptr; 140 Deserialize<interface_control::RunOrClosePipeMessageParamsDataView>( 141 params, ¶ms_ptr, &context_); 142 auto& input = *params_ptr->input; 143 if (input.is_require_version()) 144 return interface_version_ >= input.get_require_version()->version; 145 146 return false; 147 } 148 149 } // namespace internal 150 } // namespace mojo 151