Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,8 @@ FILE: ../../../flutter/shell/platform/embedder/embedder_engine.h
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_external_texture_gl.h
FILE: ../../../flutter/shell/platform/embedder/embedder_include.c
FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_platform_message_response.h
FILE: ../../../flutter/shell/platform/embedder/embedder_safe_access.h
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc
FILE: ../../../flutter/shell/platform/embedder/embedder_surface.h
Expand Down
3 changes: 3 additions & 0 deletions shell/platform/embedder/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ source_set("embedder") {
"embedder_external_texture_gl.cc",
"embedder_external_texture_gl.h",
"embedder_include.c",
"embedder_platform_message_response.cc",
"embedder_platform_message_response.h",
"embedder_safe_access.h",
"embedder_surface.cc",
"embedder_surface.h",
Expand All @@ -46,6 +48,7 @@ source_set("embedder") {
"$flutter_root/common",
"$flutter_root/flow",
"$flutter_root/fml",
"$flutter_root/lib/ui",
"$flutter_root/runtime:libdart",
"$flutter_root/shell/common",
"//third_party/dart/runtime/bin:dart_io_api",
Expand Down
52 changes: 51 additions & 1 deletion shell/platform/embedder/embedder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern const intptr_t kPlatformStrongDillSize;
#include "flutter/shell/common/switches.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/embedder/embedder_engine.h"
#include "flutter/shell/platform/embedder/embedder_platform_message_response.h"
#include "flutter/shell/platform/embedder/embedder_safe_access.h"
#include "flutter/shell/platform/embedder/embedder_task_runner.h"
#include "flutter/shell/platform/embedder/embedder_thread_host.h"
Expand Down Expand Up @@ -818,19 +819,68 @@ FlutterEngineResult FlutterEngineSendPlatformMessage(
return LOG_EMBEDDER_ERROR(kInvalidArguments);
}

const FlutterPlatformMessageResponseHandle* response_handle =
SAFE_ACCESS(flutter_message, response_handle, nullptr);

fml::RefPtr<flutter::PlatformMessageResponse> response;
if (response_handle->message) {
response = response_handle->message->response();
}

auto message = fml::MakeRefCounted<flutter::PlatformMessage>(
flutter_message->channel,
std::vector<uint8_t>(
flutter_message->message,
flutter_message->message + flutter_message->message_size),
nullptr);
response);

return reinterpret_cast<flutter::EmbedderEngine*>(engine)
->SendPlatformMessage(std::move(message))
? kSuccess
: LOG_EMBEDDER_ERROR(kInvalidArguments);
}

FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(
FlutterEngine engine,
FlutterDataCallback data_callback,
void* user_data,
FlutterPlatformMessageResponseHandle** response_out) {
if (engine == nullptr || data_callback == nullptr ||
response_out == nullptr) {
return LOG_EMBEDDER_ERROR(kInvalidArguments);
}

flutter::EmbedderPlatformMessageResponse::Callback response_callback =
[user_data, data_callback](const uint8_t* data, size_t size) {
data_callback(data, size, user_data);
};

auto platform_task_runner = reinterpret_cast<flutter::EmbedderEngine*>(engine)
->GetTaskRunners()
.GetPlatformTaskRunner();

auto handle = new FlutterPlatformMessageResponseHandle();

handle->message = fml::MakeRefCounted<flutter::PlatformMessage>(
"", // The channel is empty and unused as the response handle is going to
// referenced directly in the |FlutterEngineSendPlatformMessage| with
// the container message discarded.
fml::MakeRefCounted<flutter::EmbedderPlatformMessageResponse>(
std::move(platform_task_runner), response_callback));
*response_out = handle;
return kSuccess;
}

FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(
FlutterEngine engine,
FlutterPlatformMessageResponseHandle* response) {
if (engine == nullptr || response == nullptr) {
return LOG_EMBEDDER_ERROR(kInvalidArguments);
}
delete response;
return kSuccess;
}

FlutterEngineResult FlutterEngineSendPlatformMessageResponse(
FlutterEngine engine,
const FlutterPlatformMessageResponseHandle* handle,
Expand Down
40 changes: 35 additions & 5 deletions shell/platform/embedder/embedder.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,11 @@ typedef struct {
size_t struct_size;
const char* channel;
const uint8_t* message;
const size_t message_size;
size_t message_size;
// The response handle on which to invoke
// |FlutterEngineSendPlatformMessageResponse| when the response is ready. This
// field is ignored for messages being sent from the embedder to the
// framework. |FlutterEngineSendPlatformMessageResponse| must be called for
// all messages received by the embedder. Failure to call
// |FlutterEngineSendPlatformMessageResponse| when the response is ready.
// |FlutterEngineSendPlatformMessageResponse| must be called for all messages
// received by the embedder. Failure to call
// |FlutterEngineSendPlatformMessageResponse| will cause a memory leak. It is
// not safe to send multiple responses on a single response object.
const FlutterPlatformMessageResponseHandle* response_handle;
Expand All @@ -388,6 +387,10 @@ typedef void (*FlutterPlatformMessageCallback)(
const FlutterPlatformMessage* /* message*/,
void* /* user data */);

typedef void (*FlutterDataCallback)(const uint8_t* /* data */,
size_t /* size */,
void* /* user data */);

typedef struct {
double left;
double top;
Expand Down Expand Up @@ -707,6 +710,33 @@ FlutterEngineResult FlutterEngineSendPlatformMessage(
FlutterEngine engine,
const FlutterPlatformMessage* message);

// Creates a platform message response handle that allows the embedder to set a
// native callback for a response to a message. This handle may be set on the
// |response_handle| field of any |FlutterPlatformMessage| sent to the engine.
//
// The handle must be collected via a call to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: consider adding a blank line above this, and another before the "The user data baton [...]" to break this long comment up into different conceptual sections (overview, memory management, argument details).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. At some point, we should move over to using doxygen style header docs too.

// |FlutterPlatformMessageReleaseResponseHandle|. This may be done immediately
// after a call to |FlutterEngineSendPlatformMessage| with a platform message
// whose response handle contains the handle created using this call. In case a
// handle is created but never sent in a message, the release call must still be
// made. Not calling release on the handle results in a small memory leak.
//
// The user data baton passed to the data callback is the one specified in this
// call as the third argument.
FLUTTER_EXPORT
FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(
FlutterEngine engine,
FlutterDataCallback data_callback,
void* user_data,
FlutterPlatformMessageResponseHandle** response_out);

// Collects the handle created using
// |FlutterPlatformMessageCreateResponseHandle|.
FLUTTER_EXPORT
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(
FlutterEngine engine,
FlutterPlatformMessageResponseHandle* response);

FLUTTER_EXPORT
FlutterEngineResult FlutterEngineSendPlatformMessageResponse(
FlutterEngine engine,
Expand Down
7 changes: 6 additions & 1 deletion shell/platform/embedder/embedder_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ EmbedderEngine::EmbedderEngine(
EmbedderExternalTextureGL::ExternalTextureCallback
external_texture_callback)
: thread_host_(std::move(thread_host)),
shell_(Shell::Create(std::move(task_runners),
task_runners_(task_runners),
shell_(Shell::Create(task_runners_,
std::move(settings),
on_create_platform_view,
on_create_rasterizer)),
Expand All @@ -36,6 +37,10 @@ bool EmbedderEngine::IsValid() const {
return is_valid_;
}

const TaskRunners& EmbedderEngine::GetTaskRunners() const {
return task_runners_;
}

bool EmbedderEngine::NotifyCreated() {
if (!IsValid()) {
return false;
Expand Down
3 changes: 3 additions & 0 deletions shell/platform/embedder/embedder_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class EmbedderEngine {

~EmbedderEngine();

const TaskRunners& GetTaskRunners() const;

bool NotifyCreated();

bool NotifyDestroyed();
Expand Down Expand Up @@ -71,6 +73,7 @@ class EmbedderEngine {

private:
const std::unique_ptr<EmbedderThreadHost> thread_host_;
TaskRunners task_runners_;
std::unique_ptr<Shell> shell_;
const EmbedderExternalTextureGL::ExternalTextureCallback
external_texture_callback_;
Expand Down
37 changes: 37 additions & 0 deletions shell/platform/embedder/embedder_platform_message_response.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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/shell/platform/embedder/embedder_platform_message_response.h"

#include "flutter/fml/make_copyable.h"

namespace flutter {

EmbedderPlatformMessageResponse::EmbedderPlatformMessageResponse(
fml::RefPtr<fml::TaskRunner> runner,
Callback callback)
: runner_(std::move(runner)), callback_(callback) {}

EmbedderPlatformMessageResponse::~EmbedderPlatformMessageResponse() = default;

// |PlatformMessageResponse|
void EmbedderPlatformMessageResponse::Complete(
std::unique_ptr<fml::Mapping> data) {
if (!data) {
CompleteEmpty();
return;
}

runner_->PostTask(
fml::MakeCopyable([data = std::move(data), callback = callback_]() {
callback(data->GetMapping(), data->GetSize());
}));
}

// |PlatformMessageResponse|
void EmbedderPlatformMessageResponse::CompleteEmpty() {
Complete(std::make_unique<fml::NonOwnedMapping>(nullptr, 0u));
}

} // namespace flutter
53 changes: 53 additions & 0 deletions shell/platform/embedder/embedder_platform_message_response.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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_EMBEDDER_EMBEDDER_PLATFORM_MESSAGE_RESPONSE_H_
#define FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_PLATFORM_MESSAGE_RESPONSE_H_

#include "flutter/fml/macros.h"
#include "flutter/fml/task_runner.h"
#include "flutter/lib/ui/window/platform_message_response.h"

namespace flutter {

//------------------------------------------------------------------------------
/// @brief The platform message response subclass for responses to messages
/// from the embedder to the framework. Message responses are
/// fulfilled by the framework.
class EmbedderPlatformMessageResponse : public PlatformMessageResponse {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add class definition documentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

public:
using Callback = std::function<void(const uint8_t* data, size_t size)>;

//----------------------------------------------------------------------------
/// @param[in] runner The task runner on which to execute the callback.
/// The response will be initiated by the framework on
/// the UI thread.
/// @param[in] callback The callback that communicates to the embedder the
/// contents of the response sent by the framework back
/// to the emebder.
EmbedderPlatformMessageResponse(fml::RefPtr<fml::TaskRunner> runner,
Callback callback);

//----------------------------------------------------------------------------
/// @brief Destroys the message response. Can be called on any thread.
/// Does not execute unfulfilled callbacks.
///
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove blank comment line.

~EmbedderPlatformMessageResponse() override;

private:
fml::RefPtr<fml::TaskRunner> runner_;
Callback callback_;

// |PlatformMessageResponse|
void Complete(std::unique_ptr<fml::Mapping> data) override;

// |PlatformMessageResponse|
void CompleteEmpty() override;

FML_DISALLOW_COPY_AND_ASSIGN(EmbedderPlatformMessageResponse);
};

} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_EMBEDDER_EMBEDDER_PLATFORM_MESSAGE_RESPONSE_H_
9 changes: 9 additions & 0 deletions shell/platform/embedder/fixtures/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,12 @@ void a11y_main() async { // ignore: non_constant_identifier_names
await semanticsChanged;
notifySemanticsEnabled(window.semanticsEnabled);
}


@pragma('vm:entry-point')
void platform_messages_response() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these messages have documentation relating to the tests using them?

window.onPlatformMessage = (String name, ByteData data, PlatformMessageResponseCallback callback) {
callback(data);
};
signalNativeTest();
}
3 changes: 2 additions & 1 deletion shell/platform/embedder/tests/embedder_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ EmbedderContext& EmbedderTest::GetEmbedderContext() {

// |testing::Test|
void EmbedderTest::SetUp() {
// Nothing to do here since we will lazily setup the context when asked.
ThreadTest::SetUp();
}

// |testing::Test|
void EmbedderTest::TearDown() {
embedder_context_.reset();
ThreadTest::TearDown();
}

} // namespace testing
Expand Down
3 changes: 2 additions & 1 deletion shell/platform/embedder/tests/embedder_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@
#include "flutter/fml/macros.h"
#include "flutter/shell/platform/embedder/tests/embedder_context.h"
#include "flutter/testing/testing.h"
#include "flutter/testing/thread_test.h"

namespace flutter {
namespace testing {

class EmbedderTest : public ::testing::Test {
class EmbedderTest : public ThreadTest {
public:
EmbedderTest();

Expand Down
Loading