|  | 
|  | 1 | +// Copyright 2013 The Flutter 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 | +// This file contains the implementations of any class in the wrapper that | 
|  | 6 | +// - is not fully inline, and | 
|  | 7 | +// - is necessary for all clients of the wrapper (either app or plugin). | 
|  | 8 | +// It exists instead of the usual structure of having some_class_name.cc files | 
|  | 9 | +// so that changes to the set of things that need non-header implementations | 
|  | 10 | +// are not breaking changes for the template. | 
|  | 11 | +// | 
|  | 12 | +// If https://github.com/flutter/flutter/issues/57146 is fixed, this can be | 
|  | 13 | +// removed in favor of the normal structure since templates will no longer | 
|  | 14 | +// manually include files. | 
|  | 15 | + | 
|  | 16 | +#include <assert.h> | 
|  | 17 | + | 
|  | 18 | +#include <iostream> | 
|  | 19 | + | 
|  | 20 | +#include "binary_messenger_impl.h" | 
|  | 21 | +#include "include/flutter/engine_method_result.h" | 
|  | 22 | + | 
|  | 23 | +namespace flutter { | 
|  | 24 | + | 
|  | 25 | +// ========== binary_messenger_impl.h ========== | 
|  | 26 | + | 
|  | 27 | +namespace { | 
|  | 28 | +// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along | 
|  | 29 | +// with a BinaryReply that will send a response on |message|'s response handle. | 
|  | 30 | +// | 
|  | 31 | +// This serves as an adaptor between the function-pointer-based message callback | 
|  | 32 | +// interface provided by the C API and the std::function-based message handler | 
|  | 33 | +// interface of BinaryMessenger. | 
|  | 34 | +void ForwardToHandler(FlutterDesktopMessengerRef messenger, | 
|  | 35 | +                      const FlutterDesktopMessage* message, | 
|  | 36 | +                      void* user_data) { | 
|  | 37 | +  auto* response_handle = message->response_handle; | 
|  | 38 | +  BinaryReply reply_handler = [messenger, response_handle]( | 
|  | 39 | +                                  const uint8_t* reply, | 
|  | 40 | +                                  size_t reply_size) mutable { | 
|  | 41 | +    if (!response_handle) { | 
|  | 42 | +      std::cerr << "Error: Response can be set only once. Ignoring " | 
|  | 43 | +                   "duplicate response." | 
|  | 44 | +                << std::endl; | 
|  | 45 | +      return; | 
|  | 46 | +    } | 
|  | 47 | +    FlutterDesktopMessengerSendResponse(messenger, response_handle, reply, | 
|  | 48 | +                                        reply_size); | 
|  | 49 | +    // The engine frees the response handle once | 
|  | 50 | +    // FlutterDesktopSendMessageResponse is called. | 
|  | 51 | +    response_handle = nullptr; | 
|  | 52 | +  }; | 
|  | 53 | + | 
|  | 54 | +  const BinaryMessageHandler& message_handler = | 
|  | 55 | +      *static_cast<BinaryMessageHandler*>(user_data); | 
|  | 56 | + | 
|  | 57 | +  message_handler(message->message, message->message_size, | 
|  | 58 | +                  std::move(reply_handler)); | 
|  | 59 | +} | 
|  | 60 | +}  // namespace | 
|  | 61 | + | 
|  | 62 | +BinaryMessengerImpl::BinaryMessengerImpl( | 
|  | 63 | +    FlutterDesktopMessengerRef core_messenger) | 
|  | 64 | +    : messenger_(core_messenger) {} | 
|  | 65 | + | 
|  | 66 | +BinaryMessengerImpl::~BinaryMessengerImpl() = default; | 
|  | 67 | + | 
|  | 68 | +void BinaryMessengerImpl::Send(const std::string& channel, | 
|  | 69 | +                               const uint8_t* message, | 
|  | 70 | +                               size_t message_size, | 
|  | 71 | +                               BinaryReply reply) const { | 
|  | 72 | +  if (reply == nullptr) { | 
|  | 73 | +    FlutterDesktopMessengerSend(messenger_, channel.c_str(), message, | 
|  | 74 | +                                message_size); | 
|  | 75 | +    return; | 
|  | 76 | +  } | 
|  | 77 | +  struct Captures { | 
|  | 78 | +    BinaryReply reply; | 
|  | 79 | +  }; | 
|  | 80 | +  auto captures = new Captures(); | 
|  | 81 | +  captures->reply = reply; | 
|  | 82 | + | 
|  | 83 | +  auto message_reply = [](const uint8_t* data, size_t data_size, | 
|  | 84 | +                          void* user_data) { | 
|  | 85 | +    auto captures = reinterpret_cast<Captures*>(user_data); | 
|  | 86 | +    captures->reply(data, data_size); | 
|  | 87 | +    delete captures; | 
|  | 88 | +  }; | 
|  | 89 | +  bool result = FlutterDesktopMessengerSendWithReply( | 
|  | 90 | +      messenger_, channel.c_str(), message, message_size, message_reply, | 
|  | 91 | +      captures); | 
|  | 92 | +  if (!result) { | 
|  | 93 | +    delete captures; | 
|  | 94 | +  } | 
|  | 95 | +} | 
|  | 96 | + | 
|  | 97 | +void BinaryMessengerImpl::SetMessageHandler(const std::string& channel, | 
|  | 98 | +                                            BinaryMessageHandler handler) { | 
|  | 99 | +  if (!handler) { | 
|  | 100 | +    handlers_.erase(channel); | 
|  | 101 | +    FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr, | 
|  | 102 | +                                       nullptr); | 
|  | 103 | +    return; | 
|  | 104 | +  } | 
|  | 105 | +  // Save the handler, to keep it alive. | 
|  | 106 | +  handlers_[channel] = std::move(handler); | 
|  | 107 | +  BinaryMessageHandler* message_handler = &handlers_[channel]; | 
|  | 108 | +  // Set an adaptor callback that will invoke the handler. | 
|  | 109 | +  FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), | 
|  | 110 | +                                     ForwardToHandler, message_handler); | 
|  | 111 | +} | 
|  | 112 | + | 
|  | 113 | +// ========== engine_method_result.h ========== | 
|  | 114 | + | 
|  | 115 | +namespace internal { | 
|  | 116 | + | 
|  | 117 | +ReplyManager::ReplyManager(BinaryReply reply_handler) | 
|  | 118 | +    : reply_handler_(std::move(reply_handler)) { | 
|  | 119 | +  assert(reply_handler_); | 
|  | 120 | +} | 
|  | 121 | + | 
|  | 122 | +ReplyManager::~ReplyManager() { | 
|  | 123 | +  if (reply_handler_) { | 
|  | 124 | +    // Warn, rather than send a not-implemented response, since the engine may | 
|  | 125 | +    // no longer be valid at this point. | 
|  | 126 | +    std::cerr | 
|  | 127 | +        << "Warning: Failed to respond to a message. This is a memory leak." | 
|  | 128 | +        << std::endl; | 
|  | 129 | +  } | 
|  | 130 | +} | 
|  | 131 | + | 
|  | 132 | +void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) { | 
|  | 133 | +  if (!reply_handler_) { | 
|  | 134 | +    std::cerr | 
|  | 135 | +        << "Error: Only one of Success, Error, or NotImplemented can be " | 
|  | 136 | +           "called," | 
|  | 137 | +        << " and it can be called exactly once. Ignoring duplicate result." | 
|  | 138 | +        << std::endl; | 
|  | 139 | +    return; | 
|  | 140 | +  } | 
|  | 141 | + | 
|  | 142 | +  const uint8_t* message = data && !data->empty() ? data->data() : nullptr; | 
|  | 143 | +  size_t message_size = data ? data->size() : 0; | 
|  | 144 | +  reply_handler_(message, message_size); | 
|  | 145 | +  reply_handler_ = nullptr; | 
|  | 146 | +} | 
|  | 147 | + | 
|  | 148 | +}  // namespace internal | 
|  | 149 | + | 
|  | 150 | +}  // namespace flutter | 
0 commit comments