// 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