mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
The Android embedder had been using a JNI call to get the observatory URI from DartServiceIsolate. This call was not thread safe and was redundant with the server status callback mechanism used on iOS.
204 lines
6.1 KiB
C++
204 lines
6.1 KiB
C++
// 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/runtime/dart_service_isolate.h"
|
|
|
|
#include <string.h>
|
|
#include <algorithm>
|
|
|
|
#include "flutter/fml/logging.h"
|
|
#include "flutter/runtime/embedder_resources.h"
|
|
#include "third_party/dart/runtime/include/dart_api.h"
|
|
#include "third_party/tonic/converter/dart_converter.h"
|
|
#include "third_party/tonic/dart_library_natives.h"
|
|
#include "third_party/tonic/logging/dart_error.h"
|
|
|
|
#define RETURN_ERROR_HANDLE(handle) \
|
|
if (Dart_IsError(handle)) { \
|
|
return handle; \
|
|
}
|
|
|
|
#define SHUTDOWN_ON_ERROR(handle) \
|
|
if (Dart_IsError(handle)) { \
|
|
*error = strdup(Dart_GetError(handle)); \
|
|
Dart_ExitScope(); \
|
|
Dart_ShutdownIsolate(); \
|
|
return false; \
|
|
}
|
|
|
|
namespace flutter {
|
|
namespace {
|
|
|
|
static Dart_LibraryTagHandler g_embedder_tag_handler;
|
|
static tonic::DartLibraryNatives* g_natives;
|
|
static std::string g_observatory_uri;
|
|
|
|
Dart_NativeFunction GetNativeFunction(Dart_Handle name,
|
|
int argument_count,
|
|
bool* auto_setup_scope) {
|
|
FML_CHECK(g_natives);
|
|
return g_natives->GetNativeFunction(name, argument_count, auto_setup_scope);
|
|
}
|
|
|
|
const uint8_t* GetSymbol(Dart_NativeFunction native_function) {
|
|
FML_CHECK(g_natives);
|
|
return g_natives->GetSymbol(native_function);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
std::mutex DartServiceIsolate::callbacks_mutex_;
|
|
|
|
FML_GUARDED_BY(DartServiceIsolate::callbacks_mutex_)
|
|
std::set<std::unique_ptr<DartServiceIsolate::ObservatoryServerStateCallback>>
|
|
DartServiceIsolate::callbacks_;
|
|
|
|
void DartServiceIsolate::NotifyServerState(Dart_NativeArguments args) {
|
|
Dart_Handle exception = nullptr;
|
|
std::string uri =
|
|
tonic::DartConverter<std::string>::FromArguments(args, 0, exception);
|
|
|
|
if (exception) {
|
|
return;
|
|
}
|
|
|
|
g_observatory_uri = uri;
|
|
|
|
// Collect callbacks to fire in a separate collection and invoke them outside
|
|
// the lock.
|
|
std::vector<DartServiceIsolate::ObservatoryServerStateCallback>
|
|
callbacks_to_fire;
|
|
{
|
|
std::scoped_lock lock(callbacks_mutex_);
|
|
for (auto& callback : callbacks_) {
|
|
callbacks_to_fire.push_back(*callback.get());
|
|
}
|
|
}
|
|
|
|
for (auto callback_to_fire : callbacks_to_fire) {
|
|
callback_to_fire(uri);
|
|
}
|
|
}
|
|
|
|
DartServiceIsolate::CallbackHandle DartServiceIsolate::AddServerStatusCallback(
|
|
DartServiceIsolate::ObservatoryServerStateCallback callback) {
|
|
if (!callback) {
|
|
return 0;
|
|
}
|
|
|
|
auto callback_pointer =
|
|
std::make_unique<DartServiceIsolate::ObservatoryServerStateCallback>(
|
|
callback);
|
|
|
|
auto handle = reinterpret_cast<CallbackHandle>(callback_pointer.get());
|
|
|
|
{
|
|
std::scoped_lock lock(callbacks_mutex_);
|
|
callbacks_.insert(std::move(callback_pointer));
|
|
}
|
|
|
|
if (!g_observatory_uri.empty()) {
|
|
callback(g_observatory_uri);
|
|
}
|
|
|
|
return handle;
|
|
}
|
|
|
|
bool DartServiceIsolate::RemoveServerStatusCallback(
|
|
CallbackHandle callback_handle) {
|
|
std::scoped_lock lock(callbacks_mutex_);
|
|
auto found = std::find_if(
|
|
callbacks_.begin(), callbacks_.end(),
|
|
[callback_handle](const auto& item) {
|
|
return reinterpret_cast<CallbackHandle>(item.get()) == callback_handle;
|
|
});
|
|
|
|
if (found == callbacks_.end()) {
|
|
return false;
|
|
}
|
|
|
|
callbacks_.erase(found);
|
|
return true;
|
|
}
|
|
|
|
void DartServiceIsolate::Shutdown(Dart_NativeArguments args) {
|
|
// NO-OP.
|
|
}
|
|
|
|
bool DartServiceIsolate::Startup(std::string server_ip,
|
|
intptr_t server_port,
|
|
Dart_LibraryTagHandler embedder_tag_handler,
|
|
bool disable_origin_check,
|
|
bool disable_service_auth_codes,
|
|
char** error) {
|
|
Dart_Isolate isolate = Dart_CurrentIsolate();
|
|
FML_CHECK(isolate);
|
|
|
|
// Remember the embedder's library tag handler.
|
|
g_embedder_tag_handler = embedder_tag_handler;
|
|
FML_CHECK(g_embedder_tag_handler);
|
|
|
|
// Setup native entries.
|
|
if (!g_natives) {
|
|
g_natives = new tonic::DartLibraryNatives();
|
|
g_natives->Register({
|
|
{"VMServiceIO_NotifyServerState", NotifyServerState, 1, true},
|
|
{"VMServiceIO_Shutdown", Shutdown, 0, true},
|
|
});
|
|
}
|
|
|
|
Dart_Handle uri = Dart_NewStringFromCString("dart:vmservice_io");
|
|
Dart_Handle library = Dart_LookupLibrary(uri);
|
|
SHUTDOWN_ON_ERROR(library);
|
|
Dart_Handle result = Dart_SetRootLibrary(library);
|
|
SHUTDOWN_ON_ERROR(result);
|
|
result = Dart_SetNativeResolver(library, GetNativeFunction, GetSymbol);
|
|
SHUTDOWN_ON_ERROR(result);
|
|
|
|
// Make runnable.
|
|
Dart_ExitScope();
|
|
Dart_ExitIsolate();
|
|
*error = Dart_IsolateMakeRunnable(isolate);
|
|
if (*error) {
|
|
Dart_EnterIsolate(isolate);
|
|
Dart_ShutdownIsolate();
|
|
return false;
|
|
}
|
|
Dart_EnterIsolate(isolate);
|
|
Dart_EnterScope();
|
|
|
|
library = Dart_RootLibrary();
|
|
SHUTDOWN_ON_ERROR(library);
|
|
|
|
// Set the HTTP server's ip.
|
|
result = Dart_SetField(library, Dart_NewStringFromCString("_ip"),
|
|
Dart_NewStringFromCString(server_ip.c_str()));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
// If we have a port specified, start the server immediately.
|
|
bool auto_start = server_port >= 0;
|
|
if (server_port < 0) {
|
|
// Adjust server_port to port 0 which will result in the first available
|
|
// port when the HTTP server is started.
|
|
server_port = 0;
|
|
}
|
|
// Set the HTTP's servers port.
|
|
result = Dart_SetField(library, Dart_NewStringFromCString("_port"),
|
|
Dart_NewInteger(server_port));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
result = Dart_SetField(library, Dart_NewStringFromCString("_autoStart"),
|
|
Dart_NewBoolean(auto_start));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
result =
|
|
Dart_SetField(library, Dart_NewStringFromCString("_originCheckDisabled"),
|
|
Dart_NewBoolean(disable_origin_check));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
result =
|
|
Dart_SetField(library, Dart_NewStringFromCString("_authCodesDisabled"),
|
|
Dart_NewBoolean(disable_service_auth_codes));
|
|
SHUTDOWN_ON_ERROR(result);
|
|
return true;
|
|
}
|
|
|
|
} // namespace flutter
|