diff options
Diffstat (limited to 'mojo/public/cpp/bindings/lib/control_message_handler.cc')
-rw-r--r-- | mojo/public/cpp/bindings/lib/control_message_handler.cc | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/mojo/public/cpp/bindings/lib/control_message_handler.cc b/mojo/public/cpp/bindings/lib/control_message_handler.cc new file mode 100644 index 0000000000..1b7bb78e5f --- /dev/null +++ b/mojo/public/cpp/bindings/lib/control_message_handler.cc @@ -0,0 +1,150 @@ +// 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/message_builder.h" +#include "mojo/public/cpp/bindings/lib/serialization.h" +#include "mojo/public/cpp/bindings/lib/validation_util.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); + size_t size = + PrepareToSerialize<interface_control::RunResponseMessageParamsDataView>( + response_params_ptr, &context_); + MessageBuilder builder(interface_control::kRunMessageId, + Message::kFlagIsResponse, size, 0); + builder.message()->set_request_id(message->request_id()); + + interface_control::internal::RunResponseMessageParams_Data* response_params = + nullptr; + Serialize<interface_control::RunResponseMessageParamsDataView>( + response_params_ptr, builder.buffer(), &response_params, &context_); + ignore_result(responder->Accept(builder.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 |