Home | History | Annotate | Download | only in lib
      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_proxy.h"
      6 
      7 #include <stddef.h>
      8 #include <stdint.h>
      9 #include <utility>
     10 
     11 #include "base/bind.h"
     12 #include "base/callback_helpers.h"
     13 #include "base/macros.h"
     14 #include "base/run_loop.h"
     15 #include "mojo/public/cpp/bindings/lib/serialization.h"
     16 #include "mojo/public/cpp/bindings/lib/validation_util.h"
     17 #include "mojo/public/cpp/bindings/message.h"
     18 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h"
     19 
     20 namespace mojo {
     21 namespace internal {
     22 
     23 namespace {
     24 
     25 bool ValidateControlResponse(Message* message) {
     26   ValidationContext validation_context(message->payload(),
     27                                        message->payload_num_bytes(), 0, 0,
     28                                        message, "ControlResponseValidator");
     29   if (!ValidateMessageIsResponse(message, &validation_context))
     30     return false;
     31 
     32   switch (message->header()->name) {
     33     case interface_control::kRunMessageId:
     34       return ValidateMessagePayload<
     35           interface_control::internal::RunResponseMessageParams_Data>(
     36           message, &validation_context);
     37   }
     38   return false;
     39 }
     40 
     41 using RunCallback =
     42     base::Callback<void(interface_control::RunResponseMessageParamsPtr)>;
     43 
     44 class RunResponseForwardToCallback : public MessageReceiver {
     45  public:
     46   explicit RunResponseForwardToCallback(const RunCallback& callback)
     47       : callback_(callback) {}
     48   bool Accept(Message* message) override;
     49 
     50  private:
     51   RunCallback callback_;
     52   DISALLOW_COPY_AND_ASSIGN(RunResponseForwardToCallback);
     53 };
     54 
     55 bool RunResponseForwardToCallback::Accept(Message* message) {
     56   if (!ValidateControlResponse(message))
     57     return false;
     58 
     59   interface_control::internal::RunResponseMessageParams_Data* params =
     60       reinterpret_cast<
     61           interface_control::internal::RunResponseMessageParams_Data*>(
     62           message->mutable_payload());
     63   interface_control::RunResponseMessageParamsPtr params_ptr;
     64   SerializationContext context;
     65   Deserialize<interface_control::RunResponseMessageParamsDataView>(
     66       params, &params_ptr, &context);
     67 
     68   callback_.Run(std::move(params_ptr));
     69   return true;
     70 }
     71 
     72 void SendRunMessage(MessageReceiverWithResponder* receiver,
     73                     interface_control::RunInputPtr input_ptr,
     74                     const RunCallback& callback) {
     75   auto params_ptr = interface_control::RunMessageParams::New();
     76   params_ptr->input = std::move(input_ptr);
     77   Message message(interface_control::kRunMessageId,
     78                   Message::kFlagExpectsResponse, 0, 0, nullptr);
     79   SerializationContext context;
     80   interface_control::internal::RunMessageParams_Data::BufferWriter params;
     81   Serialize<interface_control::RunMessageParamsDataView>(
     82       params_ptr, message.payload_buffer(), &params, &context);
     83   std::unique_ptr<MessageReceiver> responder =
     84       std::make_unique<RunResponseForwardToCallback>(callback);
     85   ignore_result(receiver->AcceptWithResponder(&message, std::move(responder)));
     86 }
     87 
     88 Message ConstructRunOrClosePipeMessage(
     89     interface_control::RunOrClosePipeInputPtr input_ptr) {
     90   auto params_ptr = interface_control::RunOrClosePipeMessageParams::New();
     91   params_ptr->input = std::move(input_ptr);
     92   Message message(interface_control::kRunOrClosePipeMessageId, 0, 0, 0,
     93                   nullptr);
     94   SerializationContext context;
     95   interface_control::internal::RunOrClosePipeMessageParams_Data::BufferWriter
     96       params;
     97   Serialize<interface_control::RunOrClosePipeMessageParamsDataView>(
     98       params_ptr, message.payload_buffer(), &params, &context);
     99   return message;
    100 }
    101 
    102 void SendRunOrClosePipeMessage(
    103     MessageReceiverWithResponder* receiver,
    104     interface_control::RunOrClosePipeInputPtr input_ptr) {
    105   Message message(ConstructRunOrClosePipeMessage(std::move(input_ptr)));
    106   ignore_result(receiver->Accept(&message));
    107 }
    108 
    109 void RunVersionCallback(
    110     const base::Callback<void(uint32_t)>& callback,
    111     interface_control::RunResponseMessageParamsPtr run_response) {
    112   uint32_t version = 0u;
    113   if (run_response->output && run_response->output->is_query_version_result())
    114     version = run_response->output->get_query_version_result()->version;
    115   callback.Run(version);
    116 }
    117 
    118 void RunClosure(const base::Closure& callback,
    119                 interface_control::RunResponseMessageParamsPtr run_response) {
    120   callback.Run();
    121 }
    122 
    123 }  // namespace
    124 
    125 ControlMessageProxy::ControlMessageProxy(MessageReceiverWithResponder* receiver)
    126     : receiver_(receiver) {
    127 }
    128 
    129 ControlMessageProxy::~ControlMessageProxy() = default;
    130 
    131 void ControlMessageProxy::QueryVersion(
    132     const base::Callback<void(uint32_t)>& callback) {
    133   auto input_ptr = interface_control::RunInput::New();
    134   input_ptr->set_query_version(interface_control::QueryVersion::New());
    135   SendRunMessage(receiver_, std::move(input_ptr),
    136                  base::Bind(&RunVersionCallback, callback));
    137 }
    138 
    139 void ControlMessageProxy::RequireVersion(uint32_t version) {
    140   auto require_version = interface_control::RequireVersion::New();
    141   require_version->version = version;
    142   auto input_ptr = interface_control::RunOrClosePipeInput::New();
    143   input_ptr->set_require_version(std::move(require_version));
    144   SendRunOrClosePipeMessage(receiver_, std::move(input_ptr));
    145 }
    146 
    147 void ControlMessageProxy::FlushForTesting() {
    148   if (encountered_error_)
    149     return;
    150 
    151   auto input_ptr = interface_control::RunInput::New();
    152   input_ptr->set_flush_for_testing(interface_control::FlushForTesting::New());
    153   base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
    154   run_loop_quit_closure_ = run_loop.QuitClosure();
    155   SendRunMessage(
    156       receiver_, std::move(input_ptr),
    157       base::Bind(&RunClosure,
    158                  base::Bind(&ControlMessageProxy::RunFlushForTestingClosure,
    159                             base::Unretained(this))));
    160   run_loop.Run();
    161 }
    162 
    163 void ControlMessageProxy::RunFlushForTestingClosure() {
    164   DCHECK(!run_loop_quit_closure_.is_null());
    165   base::ResetAndReturn(&run_loop_quit_closure_).Run();
    166 }
    167 
    168 void ControlMessageProxy::OnConnectionError() {
    169   encountered_error_ = true;
    170   if (!run_loop_quit_closure_.is_null())
    171     RunFlushForTestingClosure();
    172 }
    173 
    174 }  // namespace internal
    175 }  // namespace mojo
    176