Skip to content

Commit

Permalink
[engine] Sync Flutter 3.7 source code (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
swift-kim authored Feb 3, 2023
1 parent 124f613 commit e6ecb94
Show file tree
Hide file tree
Showing 14 changed files with 459 additions and 101 deletions.
1 change: 1 addition & 0 deletions flutter/shell/platform/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ config("desktop_library_implementation") {

_public_headers = [
"public/flutter_export.h",
"public/flutter_macros.h",
"public/flutter_messenger.h",
"public/flutter_plugin_registrar.h",
"public/flutter_texture_registrar.h",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ namespace flutter {
// ========== binary_messenger_impl.h ==========

namespace {

using FlutterDesktopMessengerScopedLock =
std::unique_ptr<FlutterDesktopMessenger,
decltype(&FlutterDesktopMessengerUnlock)>;

// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
// with a BinaryReply that will send a response on |message|'s response handle.
//
Expand All @@ -36,17 +41,28 @@ void ForwardToHandler(FlutterDesktopMessengerRef messenger,
const FlutterDesktopMessage* message,
void* user_data) {
auto* response_handle = message->response_handle;
BinaryReply reply_handler = [messenger, response_handle](
auto messenger_ptr = std::shared_ptr<FlutterDesktopMessenger>(
FlutterDesktopMessengerAddRef(messenger),
&FlutterDesktopMessengerRelease);
BinaryReply reply_handler = [messenger_ptr, response_handle](
const uint8_t* reply,
size_t reply_size) mutable {
// Note: This lambda can be called on any thread.
auto lock = FlutterDesktopMessengerScopedLock(
FlutterDesktopMessengerLock(messenger_ptr.get()),
&FlutterDesktopMessengerUnlock);
if (!FlutterDesktopMessengerIsAvailable(messenger_ptr.get())) {
// Drop reply if it comes in after the engine is destroyed.
return;
}
if (!response_handle) {
std::cerr << "Error: Response can be set only once. Ignoring "
"duplicate response."
<< std::endl;
return;
}
FlutterDesktopMessengerSendResponse(messenger, response_handle, reply,
reply_size);
FlutterDesktopMessengerSendResponse(messenger_ptr.get(), response_handle,
reply, reply_size);
// The engine frees the response handle once
// FlutterDesktopSendMessageResponse is called.
response_handle = nullptr;
Expand Down Expand Up @@ -195,9 +211,32 @@ bool TextureRegistrarImpl::MarkTextureFrameAvailable(int64_t texture_id) {
texture_registrar_ref_, texture_id);
}

void TextureRegistrarImpl::UnregisterTexture(int64_t texture_id,
std::function<void()> callback) {
if (callback == nullptr) {
FlutterDesktopTextureRegistrarUnregisterExternalTexture(
texture_registrar_ref_, texture_id, nullptr, nullptr);
return;
}

struct Captures {
std::function<void()> callback;
};
auto captures = new Captures();
captures->callback = std::move(callback);
FlutterDesktopTextureRegistrarUnregisterExternalTexture(
texture_registrar_ref_, texture_id,
[](void* opaque) {
auto captures = reinterpret_cast<Captures*>(opaque);
captures->callback();
delete captures;
},
captures);
}

bool TextureRegistrarImpl::UnregisterTexture(int64_t texture_id) {
return FlutterDesktopTextureRegistrarUnregisterExternalTexture(
texture_registrar_ref_, texture_id);
UnregisterTexture(texture_id, nullptr);
return true;
}

} // namespace flutter
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,13 @@ class EventChannel {
// Registers a stream handler on this channel.
// If no handler has been registered, any incoming stream setup requests will
// be handled silently by providing an empty stream.
//
// Note that the EventChannel does not own the handler and will not
// unregister it on destruction. The caller is responsible for unregistering
// the handler if it should no longer be called.
void SetStreamHandler(std::unique_ptr<StreamHandler<T>> handler) {
if (!handler) {
messenger_->SetMessageHandler(name_, nullptr);
is_listening_ = false;
return;
}

Expand All @@ -61,69 +64,75 @@ class EventChannel {
const MethodCodec<T>* codec = codec_;
const std::string channel_name = name_;
const BinaryMessenger* messenger = messenger_;
BinaryMessageHandler binary_handler = [shared_handler, codec, channel_name,
messenger,
this](const uint8_t* message,
const size_t message_size,
BinaryReply reply) {
constexpr char kOnListenMethod[] = "listen";
constexpr char kOnCancelMethod[] = "cancel";

std::unique_ptr<MethodCall<T>> method_call =
codec->DecodeMethodCall(message, message_size);
if (!method_call) {
std::cerr << "Unable to construct method call from message on channel: "
<< channel_name << std::endl;
reply(nullptr, 0);
return;
}

const std::string& method = method_call->method_name();
if (method.compare(kOnListenMethod) == 0) {
if (is_listening_) {
std::unique_ptr<StreamHandlerError<T>> error =
shared_handler->OnCancel(nullptr);
if (error) {
std::cerr << "Failed to cancel existing stream: "
<< (error->error_code) << ", " << (error->error_message)
<< ", " << (error->error_details);
BinaryMessageHandler binary_handler =
[shared_handler, codec, channel_name, messenger,
// Mutable state to track the handler's listening status.
is_listening = bool(false)](const uint8_t* message,
const size_t message_size,
BinaryReply reply) mutable {
constexpr char kOnListenMethod[] = "listen";
constexpr char kOnCancelMethod[] = "cancel";

std::unique_ptr<MethodCall<T>> method_call =
codec->DecodeMethodCall(message, message_size);
if (!method_call) {
std::cerr
<< "Unable to construct method call from message on channel: "
<< channel_name << std::endl;
reply(nullptr, 0);
return;
}
}
is_listening_ = true;

std::unique_ptr<std::vector<uint8_t>> result;
auto sink = std::make_unique<EventSinkImplementation>(
messenger, channel_name, codec);
std::unique_ptr<StreamHandlerError<T>> error =
shared_handler->OnListen(method_call->arguments(), std::move(sink));
if (error) {
result = codec->EncodeErrorEnvelope(
error->error_code, error->error_message, error->error_details);
} else {
result = codec->EncodeSuccessEnvelope();
}
reply(result->data(), result->size());
} else if (method.compare(kOnCancelMethod) == 0) {
std::unique_ptr<std::vector<uint8_t>> result;
if (is_listening_) {
std::unique_ptr<StreamHandlerError<T>> error =
shared_handler->OnCancel(method_call->arguments());
if (error) {
result = codec->EncodeErrorEnvelope(
error->error_code, error->error_message, error->error_details);

const std::string& method = method_call->method_name();
if (method.compare(kOnListenMethod) == 0) {
if (is_listening) {
std::unique_ptr<StreamHandlerError<T>> error =
shared_handler->OnCancel(nullptr);
if (error) {
std::cerr << "Failed to cancel existing stream: "
<< (error->error_code) << ", "
<< (error->error_message) << ", "
<< (error->error_details);
}
}
is_listening = true;

std::unique_ptr<std::vector<uint8_t>> result;
auto sink = std::make_unique<EventSinkImplementation>(
messenger, channel_name, codec);
std::unique_ptr<StreamHandlerError<T>> error =
shared_handler->OnListen(method_call->arguments(),
std::move(sink));
if (error) {
result = codec->EncodeErrorEnvelope(error->error_code,
error->error_message,
error->error_details);
} else {
result = codec->EncodeSuccessEnvelope();
}
reply(result->data(), result->size());
} else if (method.compare(kOnCancelMethod) == 0) {
std::unique_ptr<std::vector<uint8_t>> result;
if (is_listening) {
std::unique_ptr<StreamHandlerError<T>> error =
shared_handler->OnCancel(method_call->arguments());
if (error) {
result = codec->EncodeErrorEnvelope(error->error_code,
error->error_message,
error->error_details);
} else {
result = codec->EncodeSuccessEnvelope();
}
is_listening = false;
} else {
result = codec->EncodeErrorEnvelope(
"error", "No active stream to cancel", nullptr);
}
reply(result->data(), result->size());
} else {
result = codec->EncodeSuccessEnvelope();
reply(nullptr, 0);
}
is_listening_ = false;
} else {
result = codec->EncodeErrorEnvelope(
"error", "No active stream to cancel", nullptr);
}
reply(result->data(), result->size());
} else {
reply(nullptr, 0);
}
};
};
messenger_->SetMessageHandler(name_, std::move(binary_handler));
}

Expand Down Expand Up @@ -165,7 +174,6 @@ class EventChannel {
BinaryMessenger* messenger_;
const std::string name_;
const MethodCodec<T>* codec_;
bool is_listening_ = false;
};

} // namespace flutter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,13 @@ class TextureRegistrar {
// the callback that was provided upon creating the texture.
virtual bool MarkTextureFrameAvailable(int64_t texture_id) = 0;

// Unregisters an existing Texture object.
// Textures must not be unregistered while they're in use.
// Asynchronously unregisters an existing texture object.
// Upon completion, the optional |callback| gets invoked.
virtual void UnregisterTexture(int64_t texture_id,
std::function<void()> callback) = 0;

// Unregisters an existing texture object.
// DEPRECATED: Use UnregisterTexture(texture_id, optional_callback) instead.
virtual bool UnregisterTexture(int64_t texture_id) = 0;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class TextureRegistrarImpl : public TextureRegistrar {
// |flutter::TextureRegistrar|
bool MarkTextureFrameAvailable(int64_t texture_id) override;

// |flutter::TextureRegistrar|
void UnregisterTexture(int64_t texture_id,
std::function<void()> callback) override;

// |flutter::TextureRegistrar|
bool UnregisterTexture(int64_t texture_id) override;

Expand Down
7 changes: 4 additions & 3 deletions flutter/shell/platform/common/incoming_message_dispatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ void IncomingMessageDispatcher::HandleMessage(
const std::function<void(void)>& input_unblock_cb) {
std::string channel(message.channel);

auto callback_iterator = callbacks_.find(channel);
// Find the handler for the channel; if there isn't one, report the failure.
if (callbacks_.find(channel) == callbacks_.end()) {
if (callback_iterator == callbacks_.end()) {
FlutterDesktopMessengerSendResponse(messenger_, message.response_handle,
nullptr, 0);
return;
}
auto& callback_info = callbacks_[channel];
FlutterDesktopMessageCallback message_callback = callback_info.first;
auto& callback_info = callback_iterator->second;
const FlutterDesktopMessageCallback& message_callback = callback_info.first;

// Process the call, handling input blocking if requested.
bool block_input = input_blocking_channels_.count(channel) > 0;
Expand Down
2 changes: 1 addition & 1 deletion flutter/shell/platform/common/public/flutter_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#define FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_EXPORT_H_

#ifdef FLUTTER_DESKTOP_LIBRARY
// Add visibility/export annotations when building the library.

// Add visibility/export annotations when building the library.
#ifdef _WIN32
#define FLUTTER_EXPORT __declspec(dllexport)
#else
Expand Down
24 changes: 24 additions & 0 deletions flutter/shell/platform/common/public/flutter_macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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.

#ifndef FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_MACROS_H_
#define FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_MACROS_H_

#ifdef FLUTTER_DESKTOP_LIBRARY

// Do not add deprecation annotations when building the library.
#define FLUTTER_DEPRECATED(message)

#else // FLUTTER_DESKTOP_LIBRARY

// Add deprecation warning for users of the library.
#ifdef _WIN32
#define FLUTTER_DEPRECATED(message) __declspec(deprecated(message))
#else
#define FLUTTER_DEPRECATED(message) __attribute__((deprecated(message)))
#endif

#endif // FLUTTER_DESKTOP_LIBRARY

#endif // FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_MACROS_H_
48 changes: 48 additions & 0 deletions flutter/shell/platform/common/public/flutter_messenger.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_MESSENGER_H_
#define FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_MESSENGER_H_

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

Expand Down Expand Up @@ -87,6 +88,53 @@ FLUTTER_EXPORT void FlutterDesktopMessengerSetCallback(
FlutterDesktopMessageCallback callback,
void* user_data);

// Increments the reference count for the |messenger|.
//
// Operation is thread-safe.
//
// See also: |FlutterDesktopMessengerRelease|
FLUTTER_EXPORT FlutterDesktopMessengerRef
FlutterDesktopMessengerAddRef(FlutterDesktopMessengerRef messenger);

// Decrements the reference count for the |messenger|.
//
// Operation is thread-safe.
//
// See also: |FlutterDesktopMessengerAddRef|
FLUTTER_EXPORT void FlutterDesktopMessengerRelease(
FlutterDesktopMessengerRef messenger);

// Returns `true` if the |FlutterDesktopMessengerRef| still references a running
// engine.
//
// This check should be made inside of a |FlutterDesktopMessengerLock| and
// before any other calls are made to the FlutterDesktopMessengerRef when using
// it from a thread other than the platform thread.
FLUTTER_EXPORT bool FlutterDesktopMessengerIsAvailable(
FlutterDesktopMessengerRef messenger);

// Locks the `FlutterDesktopMessengerRef` ensuring that
// |FlutterDesktopMessengerIsAvailable| does not change while locked.
//
// All calls to the FlutterDesktopMessengerRef from threads other than the
// platform thread should happen inside of a lock.
//
// Operation is thread-safe.
//
// Returns the |messenger| value.
//
// See also: |FlutterDesktopMessengerUnlock|
FLUTTER_EXPORT FlutterDesktopMessengerRef
FlutterDesktopMessengerLock(FlutterDesktopMessengerRef messenger);

// Unlocks the `FlutterDesktopMessengerRef`.
//
// Operation is thread-safe.
//
// See also: |FlutterDesktopMessengerLock|
FLUTTER_EXPORT void FlutterDesktopMessengerUnlock(
FlutterDesktopMessengerRef messenger);

#if defined(__cplusplus)
} // extern "C"
#endif
Expand Down
Loading

0 comments on commit e6ecb94

Please sign in to comment.