summaryrefslogtreecommitdiff
path: root/mojo/public/cpp/bindings/lib/control_message_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'mojo/public/cpp/bindings/lib/control_message_handler.cc')
-rw-r--r--mojo/public/cpp/bindings/lib/control_message_handler.cc150
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, &params_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, &params_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