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 "base/macros.h"
13 #include "mojo/public/cpp/bindings/lib/serialization.h"
14 #include "mojo/public/cpp/bindings/lib/validation_util.h"
15 #include "mojo/public/cpp/bindings/message.h"
16 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
17
18 namespace mojo {
19 namespace internal {
20 namespace {
21
ValidateControlRequestWithResponse(Message * message)22 bool ValidateControlRequestWithResponse(Message* message) {
23 ValidationContext validation_context(message->payload(),
24 message->payload_num_bytes(), 0, 0,
25 message, "ControlRequestValidator");
26 if (!ValidateMessageIsRequestExpectingResponse(message, &validation_context))
27 return false;
28
29 switch (message->header()->name) {
30 case interface_control::kRunMessageId:
31 return ValidateMessagePayload<
32 interface_control::internal::RunMessageParams_Data>(
33 message, &validation_context);
34 }
35 return false;
36 }
37
ValidateControlRequestWithoutResponse(Message * message)38 bool ValidateControlRequestWithoutResponse(Message* message) {
39 ValidationContext validation_context(message->payload(),
40 message->payload_num_bytes(), 0, 0,
41 message, "ControlRequestValidator");
42 if (!ValidateMessageIsRequestWithoutResponse(message, &validation_context))
43 return false;
44
45 switch (message->header()->name) {
46 case interface_control::kRunOrClosePipeMessageId:
47 return ValidateMessageIsRequestWithoutResponse(message,
48 &validation_context) &&
49 ValidateMessagePayload<
50 interface_control::internal::RunOrClosePipeMessageParams_Data>(
51 message, &validation_context);
52 }
53 return false;
54 }
55
56 } // namespace
57
58 // static
IsControlMessage(const Message * message)59 bool ControlMessageHandler::IsControlMessage(const Message* message) {
60 return message->header()->name == interface_control::kRunMessageId ||
61 message->header()->name == interface_control::kRunOrClosePipeMessageId;
62 }
63
ControlMessageHandler(uint32_t interface_version)64 ControlMessageHandler::ControlMessageHandler(uint32_t interface_version)
65 : interface_version_(interface_version) {
66 }
67
~ControlMessageHandler()68 ControlMessageHandler::~ControlMessageHandler() {
69 }
70
Accept(Message * message)71 bool ControlMessageHandler::Accept(Message* message) {
72 if (!ValidateControlRequestWithoutResponse(message))
73 return false;
74
75 if (message->header()->name == interface_control::kRunOrClosePipeMessageId)
76 return RunOrClosePipe(message);
77
78 NOTREACHED();
79 return false;
80 }
81
AcceptWithResponder(Message * message,std::unique_ptr<MessageReceiverWithStatus> responder)82 bool ControlMessageHandler::AcceptWithResponder(
83 Message* message,
84 std::unique_ptr<MessageReceiverWithStatus> responder) {
85 if (!ValidateControlRequestWithResponse(message))
86 return false;
87
88 if (message->header()->name == interface_control::kRunMessageId)
89 return Run(message, std::move(responder));
90
91 NOTREACHED();
92 return false;
93 }
94
Run(Message * message,std::unique_ptr<MessageReceiverWithStatus> responder)95 bool ControlMessageHandler::Run(
96 Message* message,
97 std::unique_ptr<MessageReceiverWithStatus> responder) {
98 interface_control::internal::RunMessageParams_Data* params =
99 reinterpret_cast<interface_control::internal::RunMessageParams_Data*>(
100 message->mutable_payload());
101 interface_control::RunMessageParamsPtr params_ptr;
102 Deserialize<interface_control::RunMessageParamsDataView>(params, ¶ms_ptr,
103 &context_);
104 auto& input = *params_ptr->input;
105 interface_control::RunOutputPtr output = interface_control::RunOutput::New();
106 if (input.is_query_version()) {
107 output->set_query_version_result(
108 interface_control::QueryVersionResult::New());
109 output->get_query_version_result()->version = interface_version_;
110 } else if (input.is_flush_for_testing()) {
111 output.reset();
112 } else {
113 output.reset();
114 }
115
116 auto response_params_ptr = interface_control::RunResponseMessageParams::New();
117 response_params_ptr->output = std::move(output);
118 Message response_message(interface_control::kRunMessageId,
119 Message::kFlagIsResponse, 0, 0, nullptr);
120 response_message.set_request_id(message->request_id());
121 interface_control::internal::RunResponseMessageParams_Data::BufferWriter
122 response_params;
123 Serialize<interface_control::RunResponseMessageParamsDataView>(
124 response_params_ptr, response_message.payload_buffer(), &response_params,
125 &context_);
126 ignore_result(responder->Accept(&response_message));
127 return true;
128 }
129
RunOrClosePipe(Message * message)130 bool ControlMessageHandler::RunOrClosePipe(Message* message) {
131 interface_control::internal::RunOrClosePipeMessageParams_Data* params =
132 reinterpret_cast<
133 interface_control::internal::RunOrClosePipeMessageParams_Data*>(
134 message->mutable_payload());
135 interface_control::RunOrClosePipeMessageParamsPtr params_ptr;
136 Deserialize<interface_control::RunOrClosePipeMessageParamsDataView>(
137 params, ¶ms_ptr, &context_);
138 auto& input = *params_ptr->input;
139 if (input.is_require_version())
140 return interface_version_ >= input.get_require_version()->version;
141
142 return false;
143 }
144
145 } // namespace internal
146 } // namespace mojo
147