// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "mojo/public/cpp/bindings/lib/control_message_handler.h" #include <stddef.h> #include <stdint.h> #include <utility> #include "base/logging.h" #include "base/macros.h" #include "mojo/public/cpp/bindings/lib/serialization.h" #include "mojo/public/cpp/bindings/lib/validation_util.h" #include "mojo/public/cpp/bindings/message.h" #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" namespace mojo { namespace internal { namespace { bool ValidateControlRequestWithResponse(Message* message) { ValidationContext validation_context(message->payload(), message->payload_num_bytes(), 0, 0, message, "ControlRequestValidator"); if (!ValidateMessageIsRequestExpectingResponse(message, &validation_context)) return false; switch (message->header()->name) { case interface_control::kRunMessageId: return ValidateMessagePayload< interface_control::internal::RunMessageParams_Data>( message, &validation_context); } return false; } bool ValidateControlRequestWithoutResponse(Message* message) { ValidationContext validation_context(message->payload(), message->payload_num_bytes(), 0, 0, message, "ControlRequestValidator"); if (!ValidateMessageIsRequestWithoutResponse(message, &validation_context)) return false; switch (message->header()->name) { case interface_control::kRunOrClosePipeMessageId: return ValidateMessageIsRequestWithoutResponse(message, &validation_context) && ValidateMessagePayload< interface_control::internal::RunOrClosePipeMessageParams_Data>( message, &validation_context); } return false; } } // namespace // static bool ControlMessageHandler::IsControlMessage(const Message* message) { return message->header()->name == interface_control::kRunMessageId || message->header()->name == interface_control::kRunOrClosePipeMessageId; } ControlMessageHandler::ControlMessageHandler(uint32_t interface_version) : interface_version_(interface_version) { } ControlMessageHandler::~ControlMessageHandler() { } bool ControlMessageHandler::Accept(Message* message) { if (!ValidateControlRequestWithoutResponse(message)) return false; if (message->header()->name == interface_control::kRunOrClosePipeMessageId) return RunOrClosePipe(message); NOTREACHED(); return false; } bool ControlMessageHandler::AcceptWithResponder( Message* message, std::unique_ptr<MessageReceiverWithStatus> responder) { if (!ValidateControlRequestWithResponse(message)) return false; if (message->header()->name == interface_control::kRunMessageId) return Run(message, std::move(responder)); NOTREACHED(); return false; } bool ControlMessageHandler::Run( Message* message, std::unique_ptr<MessageReceiverWithStatus> responder) { interface_control::internal::RunMessageParams_Data* params = reinterpret_cast<interface_control::internal::RunMessageParams_Data*>( message->mutable_payload()); interface_control::RunMessageParamsPtr params_ptr; Deserialize<interface_control::RunMessageParamsDataView>(params, ¶ms_ptr, &context_); auto& input = *params_ptr->input; interface_control::RunOutputPtr output = interface_control::RunOutput::New(); if (input.is_query_version()) { output->set_query_version_result( interface_control::QueryVersionResult::New()); output->get_query_version_result()->version = interface_version_; } else if (input.is_flush_for_testing()) { output.reset(); } else { output.reset(); } auto response_params_ptr = interface_control::RunResponseMessageParams::New(); response_params_ptr->output = std::move(output); Message response_message(interface_control::kRunMessageId, Message::kFlagIsResponse, 0, 0, nullptr); response_message.set_request_id(message->request_id()); interface_control::internal::RunResponseMessageParams_Data::BufferWriter response_params; Serialize<interface_control::RunResponseMessageParamsDataView>( response_params_ptr, response_message.payload_buffer(), &response_params, &context_); ignore_result(responder->Accept(&response_message)); return true; } bool ControlMessageHandler::RunOrClosePipe(Message* message) { interface_control::internal::RunOrClosePipeMessageParams_Data* params = reinterpret_cast< interface_control::internal::RunOrClosePipeMessageParams_Data*>( message->mutable_payload()); interface_control::RunOrClosePipeMessageParamsPtr params_ptr; Deserialize<interface_control::RunOrClosePipeMessageParamsDataView>( params, ¶ms_ptr, &context_); auto& input = *params_ptr->input; if (input.is_require_version()) return interface_version_ >= input.get_require_version()->version; return false; } } // namespace internal } // namespace mojo