blob: dca1ab74f9d5804ede9de941e4b7866aa08cb090 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/lib/ui/window/platform_message_response_dart.h"
#include <utility>
#include "flutter/common/task_runners.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/lib/ui/window/window.h"
#include "third_party/tonic/dart_state.h"
#include "third_party/tonic/logging/dart_invoke.h"
namespace flutter {
namespace {
// Avoid copying the contents of messages beyond a certain size.
const int kMessageCopyThreshold = 1000;
void MessageDataFinalizer(void* isolate_callback_data,
Dart_WeakPersistentHandle handle,
void* peer) {
std::vector<uint8_t>* data = reinterpret_cast<std::vector<uint8_t>*>(peer);
delete data;
}
Dart_Handle WrapByteData(std::vector<uint8_t> data) {
if (data.size() < kMessageCopyThreshold) {
return ToByteData(data);
} else {
std::vector<uint8_t>* heap_data = new std::vector<uint8_t>(std::move(data));
return Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kByteData, heap_data->data(), heap_data->size(),
heap_data, heap_data->size(), MessageDataFinalizer);
}
}
Dart_Handle WrapByteData(std::unique_ptr<fml::Mapping> mapping) {
std::vector<uint8_t> data(mapping->GetSize());
memcpy(data.data(), mapping->GetMapping(), mapping->GetSize());
return WrapByteData(std::move(data));
}
} // anonymous namespace
PlatformMessageResponseDart::PlatformMessageResponseDart(
tonic::DartPersistentValue callback,
fml::RefPtr<fml::TaskRunner> ui_task_runner)
: callback_(std::move(callback)),
ui_task_runner_(std::move(ui_task_runner)) {}
PlatformMessageResponseDart::~PlatformMessageResponseDart() {
if (!callback_.is_empty()) {
ui_task_runner_->PostTask(fml::MakeCopyable(
[callback = std::move(callback_)]() mutable { callback.Clear(); }));
}
}
void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
if (callback_.is_empty())
return;
FML_DCHECK(!is_complete_);
is_complete_ = true;
ui_task_runner_->PostTask(fml::MakeCopyable(
[callback = std::move(callback_), data = std::move(data)]() mutable {
std::shared_ptr<tonic::DartState> dart_state =
callback.dart_state().lock();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle byte_buffer = WrapByteData(std::move(data));
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}
void PlatformMessageResponseDart::CompleteEmpty() {
if (callback_.is_empty())
return;
FML_DCHECK(!is_complete_);
is_complete_ = true;
ui_task_runner_->PostTask(
fml::MakeCopyable([callback = std::move(callback_)]() mutable {
std::shared_ptr<tonic::DartState> dart_state =
callback.dart_state().lock();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
tonic::DartInvoke(callback.Release(), {Dart_Null()});
}));
}
} // namespace flutter