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
ValidateControlRequestWithResponse(Message * message)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
ValidateControlRequestWithoutResponse(Message * message)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
IsControlMessage(const Message * message)58 bool ControlMessageHandler::IsControlMessage(const Message* message) {
59 return message->header()->name == interface_control::kRunMessageId ||
60 message->header()->name == interface_control::kRunOrClosePipeMessageId;
61 }
62
ControlMessageHandler(uint32_t interface_version)63 ControlMessageHandler::ControlMessageHandler(uint32_t interface_version)
64 : interface_version_(interface_version) {
65 }
66
~ControlMessageHandler()67 ControlMessageHandler::~ControlMessageHandler() {
68 }
69
Accept(Message * message)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
AcceptWithResponder(Message * message,MessageReceiverWithStatus * responder)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
Run(Message * message,MessageReceiverWithStatus * responder)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
RunOrClosePipe(Message * message)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