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