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 #include "flutter/lib/ui/window/platform_message_response_dart.h"
6
7 #include <utility>
8
9 #include "flutter/common/task_runners.h"
10 #include "flutter/fml/make_copyable.h"
11 #include "flutter/lib/ui/window/window.h"
12
13 namespace flutter {
14
15 namespace {
16
17 // Avoid copying the contents of messages beyond a certain size.
18 const int kMessageCopyThreshold = 1000;
19
MessageDataFinalizer(void * isolate_callback_data,Dart_WeakPersistentHandle handle,void * peer)20 void MessageDataFinalizer(void* isolate_callback_data,
21 Dart_WeakPersistentHandle handle,
22 void* peer) {
23 std::vector<uint8_t>* data = reinterpret_cast<std::vector<uint8_t>*>(peer);
24 delete data;
25 }
26
WrapByteData(std::vector<uint8_t> data)27 Dart_Handle WrapByteData(std::vector<uint8_t> data) {
28 if (data.size() < kMessageCopyThreshold) {
29 return ToByteData(data);
30 } else {
31 std::vector<uint8_t>* heap_data = new std::vector<uint8_t>(std::move(data));
32 return Dart_NewExternalTypedDataWithFinalizer(
33 Dart_TypedData_kByteData, heap_data->data(), heap_data->size(),
34 heap_data, heap_data->size(), MessageDataFinalizer);
35 }
36 }
37
WrapByteData(std::unique_ptr<fml::Mapping> mapping)38 Dart_Handle WrapByteData(std::unique_ptr<fml::Mapping> mapping) {
39 std::vector<uint8_t> data(mapping->GetSize());
40 memcpy(data.data(), mapping->GetMapping(), mapping->GetSize());
41 return WrapByteData(std::move(data));
42 }
43
44 } // anonymous namespace
45
PlatformMessageResponseDart(tonic::DartPersistentValue callback,fml::RefPtr<fml::TaskRunner> ui_task_runner)46 PlatformMessageResponseDart::PlatformMessageResponseDart(
47 tonic::DartPersistentValue callback,
48 fml::RefPtr<fml::TaskRunner> ui_task_runner)
49 : callback_(std::move(callback)),
50 ui_task_runner_(std::move(ui_task_runner)) {}
51
~PlatformMessageResponseDart()52 PlatformMessageResponseDart::~PlatformMessageResponseDart() {
53 if (!callback_.is_empty()) {
54 ui_task_runner_->PostTask(fml::MakeCopyable(
55 [callback = std::move(callback_)]() mutable { callback.Clear(); }));
56 }
57 }
58
Complete(std::unique_ptr<fml::Mapping> data)59 void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
60 if (callback_.is_empty())
61 return;
62 FML_DCHECK(!is_complete_);
63 is_complete_ = true;
64 ui_task_runner_->PostTask(fml::MakeCopyable(
65 [callback = std::move(callback_), data = std::move(data)]() mutable {
66 std::shared_ptr<tonic::DartState> dart_state =
67 callback.dart_state().lock();
68 if (!dart_state)
69 return;
70 tonic::DartState::Scope scope(dart_state);
71
72 Dart_Handle byte_buffer = WrapByteData(std::move(data));
73 tonic::DartInvoke(callback.Release(), {byte_buffer});
74 }));
75 }
76
CompleteEmpty()77 void PlatformMessageResponseDart::CompleteEmpty() {
78 if (callback_.is_empty())
79 return;
80 FML_DCHECK(!is_complete_);
81 is_complete_ = true;
82 ui_task_runner_->PostTask(
83 fml::MakeCopyable([callback = std::move(callback_)]() mutable {
84 std::shared_ptr<tonic::DartState> dart_state =
85 callback.dart_state().lock();
86 if (!dart_state)
87 return;
88 tonic::DartState::Scope scope(dart_state);
89 tonic::DartInvoke(callback.Release(), {Dart_Null()});
90 }));
91 }
92
93 } // namespace flutter
94