mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Remove support for dynamic Mojo services (#3089)
Instead, clients should use host messaging.
This commit is contained in:
parent
862d9e9f6b
commit
2601064d47
6
BUILD.gn
6
BUILD.gn
@ -20,12 +20,6 @@ group("flutter") {
|
||||
"//flutter/sky",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ios) {
|
||||
deps += [
|
||||
"//flutter/services/dynamic:sdk_lib_archive",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_fuchsia) {
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
# Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
source_set("embedder") {
|
||||
sources = [
|
||||
"dynamic_service.c",
|
||||
"dynamic_service.h",
|
||||
"dynamic_service_definition.cc",
|
||||
"dynamic_service_definition.h",
|
||||
"dynamic_service_embedder.c",
|
||||
"dynamic_service_embedder.h",
|
||||
"dynamic_service_macros.h",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//mojo/public/c/environment",
|
||||
"//mojo/public/c/system",
|
||||
]
|
||||
|
||||
# In order for the embedder to access the routine that prepares the
|
||||
# the thunk for dylib, It needs access to system_thunks.h. This is included
|
||||
# in a target that includes mojo symbols already present on the embedder.
|
||||
# This works around header checks just for these files.
|
||||
check_includes = false
|
||||
|
||||
defines = [
|
||||
"DYNAMIC_SERVICE_EMBEDDER",
|
||||
]
|
||||
}
|
||||
|
||||
lib_sources = [
|
||||
"dynamic_service.c",
|
||||
"dynamic_service.h",
|
||||
"dynamic_service_dylib.cc",
|
||||
"dynamic_service_dylib.h",
|
||||
"dynamic_service_macros.h",
|
||||
]
|
||||
|
||||
lib_deps = [
|
||||
"//mojo/public/c/system",
|
||||
"//mojo/public/cpp/bindings",
|
||||
"//mojo/public/cpp/environment:standalone",
|
||||
"//mojo/public/platform/native:system",
|
||||
]
|
||||
|
||||
static_library("sdk_lib_archive") {
|
||||
complete_static_lib = true
|
||||
output_name = "FlutterService"
|
||||
sources = lib_sources
|
||||
deps = lib_deps
|
||||
}
|
||||
|
||||
source_set("sdk_lib") {
|
||||
sources = lib_sources
|
||||
deps = lib_deps
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
Flutter Dynamic Services Loader
|
||||
===============================
|
||||
|
||||
Third party service implementations are packaged as dylibs. Each dylib implementation needs to import just one file (`dynamic_service_dylib.h`) and implement `FlutterServicePerform` to provide the service implementation. In order to build the dylib, the build step needs the `//flutter/services/dynamic:sdk_lib` GN rule.
|
||||
@ -1,32 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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/services/dynamic/dynamic_service.h"
|
||||
|
||||
const struct FlutterServiceVersion* FlutterServiceGetVersion() {
|
||||
static const struct FlutterServiceVersion version = {
|
||||
.major = 1, // updated on breaking changes
|
||||
.minor = 0, // updated on augments
|
||||
.patch = 0, // informational, embedder does not care
|
||||
};
|
||||
return &version;
|
||||
}
|
||||
|
||||
bool FlutterServiceVersionsCompatible(
|
||||
const struct FlutterServiceVersion* embedder_version,
|
||||
const struct FlutterServiceVersion* service_version) {
|
||||
if (embedder_version == NULL || service_version == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (embedder_version->major != service_version->major) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (embedder_version->minor < service_version->minor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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_SERVICES_DYNAMIC_DYNAMIC_SERVICE_H_
|
||||
#define FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "mojo/public/c/environment/async_waiter.h"
|
||||
#include "mojo/public/c/environment/logger.h"
|
||||
#include "mojo/public/c/system/handle.h"
|
||||
#include "flutter/services/dynamic/dynamic_service_macros.h"
|
||||
|
||||
FLUTTER_C_API_START
|
||||
|
||||
/// ============================================================================
|
||||
/// The definitions in this file (and this file alone) form the stable Flutter
|
||||
/// dynamic services ABI.
|
||||
/// ============================================================================
|
||||
|
||||
#pragma pack(push, 8)
|
||||
/// The dynamic Flutter service version is responsible for deciding if services
|
||||
/// built with older or newer versions of Flutter will work with the current
|
||||
/// embedder. This struct is stable and will never change. The version check
|
||||
/// is the first thing performed by the embedder, and, in case of breaking
|
||||
/// changes (as decribed below), no other service calls are made.
|
||||
struct FlutterServiceVersion {
|
||||
/// If major versions of the embedder and the service differ, it indicates
|
||||
/// a completely breaking change. The embedder will refuse to load a service
|
||||
/// with any mismatch.
|
||||
uint32_t major;
|
||||
/// If minor versions of the embedder and the service differ, it indicates
|
||||
/// that parts of the ABI were augmented but the exisiting components have
|
||||
/// remained stable. The embedder will only attempt to load the service if
|
||||
/// its minor version is greater than or equal to that of the service.
|
||||
uint32_t minor;
|
||||
/// The patch version is used to indicate trivial non-ABI breaking updates.
|
||||
/// The embedder does not use this to accept or reject services being loaded.
|
||||
/// This field may be used to check if certain bug fixes are present in either
|
||||
/// the embedder or service runtimes.
|
||||
uint32_t patch;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/// Gets the version of the Flutter dynamic services. This is basically the
|
||||
/// only method guaranteed to be stable across major, minor and patch revisions.
|
||||
FLUTTER_EXPORT const struct FlutterServiceVersion* FlutterServiceGetVersion(
|
||||
void);
|
||||
|
||||
bool FlutterServiceVersionsCompatible(
|
||||
const struct FlutterServiceVersion* embedder_version,
|
||||
const struct FlutterServiceVersion* service_version);
|
||||
|
||||
FLUTTER_EXPORT
|
||||
void FlutterServiceOnLoad(const struct MojoAsyncWaiter* waiter,
|
||||
const struct MojoLogger* logger);
|
||||
|
||||
FLUTTER_EXPORT void FlutterServiceInvoke(MojoHandle client_handle,
|
||||
const char* service_name);
|
||||
|
||||
FLUTTER_EXPORT void FlutterServiceOnUnload(void);
|
||||
|
||||
FLUTTER_C_API_END
|
||||
|
||||
#endif // FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_H_
|
||||
@ -1,214 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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/services/dynamic/dynamic_service_definition.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "lib/ftl/logging.h"
|
||||
|
||||
namespace sky {
|
||||
namespace services {
|
||||
|
||||
std::unique_ptr<DynamicServiceDefinition> DynamicServiceDefinition::Initialize(
|
||||
const mojo::String& dylib_path) {
|
||||
auto definition = std::unique_ptr<DynamicServiceDefinition>(
|
||||
new DynamicServiceDefinition(dylib_path));
|
||||
|
||||
if (definition->IsReady()) {
|
||||
return definition;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DynamicServiceDefinition::DynamicServiceDefinition(
|
||||
const mojo::String& dylib_path)
|
||||
: service_procs_(), is_ready_(false) {
|
||||
Setup(dylib_path);
|
||||
}
|
||||
|
||||
DynamicServiceDefinition::~DynamicServiceDefinition() {
|
||||
Teardown();
|
||||
}
|
||||
|
||||
void DynamicServiceDefinition::Setup(const mojo::String& dylib_path) {
|
||||
std::lock_guard<std::mutex> lock(lifecycle_mtx_);
|
||||
|
||||
if (!OpenDylib(dylib_path)) {
|
||||
FTL_LOG(ERROR) << "Could not open the service dylib.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Remember, the service version proc is the only absolutely stable part
|
||||
// of the runtime. All other proc acquisition and setup tasks must be
|
||||
// performed *after* the version check is complete.
|
||||
|
||||
if (!AcquireServiceVersionProc()) {
|
||||
FTL_LOG(ERROR) << "Could not acquire proc for service version check.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckServiceVersion()) {
|
||||
FTL_LOG(ERROR) << "Service and embedder versions mismatch.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AcquireServiceProcs()) {
|
||||
FTL_LOG(ERROR) << "Could not acquire procs for loading the service.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!InstallSystemThunks()) {
|
||||
FTL_LOG(ERROR) << "Could not install system thunks to process the service.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!InvokeLibraryOnLoad()) {
|
||||
FTL_LOG(ERROR) << "Could not invoke library OnLoad.";
|
||||
return;
|
||||
}
|
||||
|
||||
is_ready_ = true;
|
||||
}
|
||||
|
||||
void DynamicServiceDefinition::Teardown() {
|
||||
std::lock_guard<std::mutex> lock(lifecycle_mtx_);
|
||||
|
||||
is_ready_ = false;
|
||||
|
||||
InvokeLibraryOnUnload();
|
||||
|
||||
CloseDylib();
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::IsReady() const {
|
||||
return is_ready_;
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::OpenDylib(const mojo::String& dylib_path) {
|
||||
dlerror();
|
||||
dylib_handle_ = dlopen(dylib_path.data(), RTLD_NOW);
|
||||
|
||||
if (dylib_handle_ == nullptr || dlerror() != nullptr) {
|
||||
dylib_handle_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::CloseDylib() {
|
||||
if (dylib_handle_ == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
dlerror();
|
||||
dlclose(dylib_handle_);
|
||||
return dlerror() == nullptr;
|
||||
}
|
||||
|
||||
static bool AcquireProc(void* handle, const char* name, void** dest) {
|
||||
dlerror();
|
||||
void* sym = dlsym(handle, name);
|
||||
if (sym != nullptr && dlerror() == nullptr) {
|
||||
*dest = sym;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::AcquireServiceVersionProc() {
|
||||
return AcquireProc(dylib_handle_, kFlutterServiceGetVersionProcName,
|
||||
reinterpret_cast<void**>(&service_procs_.version));
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::AcquireServiceProcs() {
|
||||
if (!AcquireProc(dylib_handle_, kFlutterServiceOnLoadProcName,
|
||||
reinterpret_cast<void**>(&service_procs_.load))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AcquireProc(dylib_handle_, kFlutterServiceInvokeProcName,
|
||||
reinterpret_cast<void**>(&service_procs_.invoke))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AcquireProc(dylib_handle_, kFlutterServiceOnUnloadProcName,
|
||||
reinterpret_cast<void**>(&service_procs_.unload))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AcquireProc(dylib_handle_, "MojoSetSystemThunks",
|
||||
reinterpret_cast<void**>(&service_procs_.set_thunks))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::CheckServiceVersion() {
|
||||
if (service_procs_.version == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const FlutterServiceVersion* embedder_version = FlutterServiceGetVersion();
|
||||
const FlutterServiceVersion* service_version = service_procs_.version();
|
||||
|
||||
return FlutterServiceVersionsCompatible(embedder_version, service_version);
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::InstallSystemThunks() {
|
||||
if (service_procs_.set_thunks == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MojoSystemThunks embedder_thunks = MojoMakeSystemThunks();
|
||||
|
||||
size_t result = service_procs_.set_thunks(&embedder_thunks);
|
||||
|
||||
if (result > sizeof(MojoSystemThunks)) {
|
||||
// The dylib expects to use a system thunks table that is larger than what
|
||||
// is currently supported by the embedder. This indicates that the embedder
|
||||
// is older than the dylib.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::InvokeLibraryOnLoad() {
|
||||
if (service_procs_.load == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
service_procs_.load(mojo::Environment::GetDefaultAsyncWaiter(),
|
||||
mojo::Environment::GetDefaultLogger());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DynamicServiceDefinition::InvokeLibraryOnUnload() {
|
||||
if (service_procs_.unload == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
service_procs_.unload();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynamicServiceDefinition::InvokeServiceHandler(
|
||||
mojo::ScopedMessagePipeHandle handle,
|
||||
const mojo::String& service_name) const {
|
||||
if (!is_ready_ || service_procs_.invoke == nullptr) {
|
||||
// Handle goes out of scope and is collected
|
||||
return;
|
||||
}
|
||||
|
||||
mojo::MessagePipeHandle rawMessageHandle = handle.release();
|
||||
// The service assumes ownership of the handle
|
||||
service_procs_.invoke(rawMessageHandle.value(), service_name.data());
|
||||
}
|
||||
|
||||
} // namespace services
|
||||
} // namespace sky
|
||||
@ -1,65 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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_SERVICES_DYNAMIC_DYNAMIC_SERVICE_DEFINITION_H_
|
||||
#define FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_DEFINITION_H_
|
||||
|
||||
#include "mojo/public/cpp/system/macros.h"
|
||||
#include "mojo/public/cpp/bindings/string.h"
|
||||
#include "mojo/public/platform/native/system_thunks.h"
|
||||
#include "flutter/services/dynamic/dynamic_service_embedder.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace sky {
|
||||
namespace services {
|
||||
|
||||
class DynamicServiceDefinition {
|
||||
public:
|
||||
static std::unique_ptr<DynamicServiceDefinition> Initialize(
|
||||
const mojo::String& dylib_path);
|
||||
|
||||
void InvokeServiceHandler(mojo::ScopedMessagePipeHandle handle,
|
||||
const mojo::String& service_name) const;
|
||||
|
||||
~DynamicServiceDefinition();
|
||||
|
||||
private:
|
||||
struct ServiceProcs {
|
||||
FlutterServiceGetVersionProc version;
|
||||
FlutterServiceOnLoadProc load;
|
||||
FlutterServiceInvokeProc invoke;
|
||||
FlutterServiceOnUnloadProc unload;
|
||||
MojoSetSystemThunksFn set_thunks;
|
||||
};
|
||||
|
||||
explicit DynamicServiceDefinition(const mojo::String& dylib_path);
|
||||
|
||||
bool IsReady() const;
|
||||
|
||||
std::mutex lifecycle_mtx_;
|
||||
|
||||
void* dylib_handle_;
|
||||
ServiceProcs service_procs_;
|
||||
bool is_ready_;
|
||||
|
||||
void Setup(const mojo::String& dylib_path);
|
||||
void Teardown();
|
||||
|
||||
bool OpenDylib(const mojo::String& dylib_path);
|
||||
bool CloseDylib();
|
||||
bool AcquireServiceVersionProc();
|
||||
bool AcquireServiceProcs();
|
||||
bool CheckServiceVersion();
|
||||
bool InstallSystemThunks();
|
||||
bool InvokeLibraryOnLoad();
|
||||
bool InvokeLibraryOnUnload();
|
||||
|
||||
MOJO_DISALLOW_COPY_AND_ASSIGN(DynamicServiceDefinition);
|
||||
};
|
||||
|
||||
} // namespace services
|
||||
} // namespace sky
|
||||
|
||||
#endif // FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_DEFINITION_H_
|
||||
@ -1,42 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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/services/dynamic/dynamic_service.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "flutter/services/dynamic/dynamic_service_dylib.h"
|
||||
#include "mojo/public/cpp/environment/environment.h"
|
||||
|
||||
static bool g_did_initialize_environment = false;
|
||||
|
||||
void FlutterServiceOnLoad(const MojoAsyncWaiter* waiter,
|
||||
const MojoLogger* logger) {
|
||||
// Assert that the dylib environment is not already initialized somehow.
|
||||
assert(!g_did_initialize_environment);
|
||||
g_did_initialize_environment = true;
|
||||
mojo::Environment::SetDefaultAsyncWaiter(waiter);
|
||||
mojo::Environment::SetDefaultLogger(logger);
|
||||
}
|
||||
|
||||
void FlutterServiceInvoke(MojoHandle client_handle, const char* service_name) {
|
||||
assert(g_did_initialize_environment);
|
||||
|
||||
// The service is always responsible for releasing the client handle. Create
|
||||
// a scoped handle immediately.
|
||||
mojo::MessagePipeHandle message_pipe_handle(client_handle);
|
||||
mojo::ScopedMessagePipeHandle scoped_handle(message_pipe_handle);
|
||||
|
||||
mojo::String name(service_name);
|
||||
|
||||
// Call the user callback
|
||||
FlutterServicePerform(scoped_handle.Pass(), name);
|
||||
}
|
||||
|
||||
void FlutterServiceOnUnload() {
|
||||
// Make sure the library is not being unloaded without the OnLoad callback
|
||||
// being called already.
|
||||
assert(g_did_initialize_environment);
|
||||
g_did_initialize_environment = false;
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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_SERVICES_DYNAMIC_DYNAMIC_SERVICE_DYLIB_H_
|
||||
#define FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_DYLIB_H_
|
||||
|
||||
#include "mojo/public/cpp/system/message_pipe.h"
|
||||
#include "mojo/public/cpp/bindings/string.h"
|
||||
|
||||
void FlutterServicePerform(mojo::ScopedMessagePipeHandle client_handle,
|
||||
const mojo::String& service_name);
|
||||
|
||||
#endif // FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_DYLIB_H_
|
||||
@ -1,11 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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/services/dynamic/dynamic_service_embedder.h"
|
||||
|
||||
const char* const kFlutterServiceGetVersionProcName =
|
||||
"FlutterServiceGetVersion";
|
||||
const char* const kFlutterServiceOnLoadProcName = "FlutterServiceOnLoad";
|
||||
const char* const kFlutterServiceInvokeProcName = "FlutterServiceInvoke";
|
||||
const char* const kFlutterServiceOnUnloadProcName = "FlutterServiceOnUnload";
|
||||
@ -1,26 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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_SERVICES_DYNAMIC_DYNAMIC_SERVICE_EMBEDDER_H_
|
||||
#define FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_EMBEDDER_H_
|
||||
|
||||
#include "flutter/services/dynamic/dynamic_service.h"
|
||||
|
||||
typedef const struct FlutterServiceVersion* (*FlutterServiceGetVersionProc)(
|
||||
void);
|
||||
typedef void (*FlutterServiceOnLoadProc)(const struct MojoAsyncWaiter*,
|
||||
const struct MojoLogger*);
|
||||
typedef void (*FlutterServiceInvokeProc)(MojoHandle, const char*);
|
||||
typedef void (*FlutterServiceOnUnloadProc)();
|
||||
|
||||
FLUTTER_C_API_START
|
||||
|
||||
extern const char* const kFlutterServiceGetVersionProcName;
|
||||
extern const char* const kFlutterServiceOnLoadProcName;
|
||||
extern const char* const kFlutterServiceInvokeProcName;
|
||||
extern const char* const kFlutterServiceOnUnloadProcName;
|
||||
|
||||
FLUTTER_C_API_END
|
||||
|
||||
#endif // FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_EMBEDDER_H_
|
||||
@ -1,31 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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_SERVICES_DYNAMIC_DYNAMIC_SERVICE_MACROS_H_
|
||||
#define FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_MACROS_H_
|
||||
|
||||
#if defined(DYNAMIC_SERVICE_EMBEDDER)
|
||||
|
||||
// Embedder does not export any symbols
|
||||
#define FLUTTER_EXPORT
|
||||
|
||||
#else // defined(DYNAMIC_SERVICE_EMBEDDER)
|
||||
|
||||
#define FLUTTER_EXPORT __attribute__((visibility("default")))
|
||||
|
||||
#endif // defined(DYNAMIC_SERVICE_EMBEDDER)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#define FLUTTER_C_API_START extern "C" {
|
||||
#define FLUTTER_C_API_END }
|
||||
|
||||
#else // __cplusplus
|
||||
|
||||
#define FLUTTER_C_API_START
|
||||
#define FLUTTER_C_API_END
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // FLUTTER_SERVICES_DYNAMIC_DYNAMIC_SERVICE_MACROS_H_
|
||||
@ -90,7 +90,6 @@ public class FlutterMain {
|
||||
private static final String DEFAULT_FLX = "app.flx";
|
||||
|
||||
private static final String MANIFEST = "flutter.yaml";
|
||||
private static final String SERVICES = "services.json";
|
||||
private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "sky_shell";
|
||||
|
||||
private static final Set<String> SKY_RESOURCES = ImmutableSetBuilder.<String>newInstance()
|
||||
@ -199,8 +198,6 @@ public class FlutterMain {
|
||||
private static native void nativeRecordStartTimestamp(long initTimeMillis);
|
||||
|
||||
private static void onServiceRegistryAvailable(final Context applicationContext, ServiceRegistry registry) {
|
||||
parseServicesConfig(applicationContext, registry);
|
||||
|
||||
registry.register(Activity.MANAGER.getName(), new ServiceFactory() {
|
||||
@Override
|
||||
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
|
||||
@ -274,56 +271,6 @@ public class FlutterMain {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the auto-generated services.json file, which contains additional services to register.
|
||||
*/
|
||||
private static void parseServicesConfig(Context applicationContext, ServiceRegistry registry) {
|
||||
final AssetManager manager = applicationContext.getResources().getAssets();
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(manager.open(SERVICES)))) {
|
||||
StringBuffer json = new StringBuffer();
|
||||
while (true) {
|
||||
String line = reader.readLine();
|
||||
if (line == null)
|
||||
break;
|
||||
json.append(line);
|
||||
}
|
||||
|
||||
JSONObject object = (JSONObject) new JSONTokener(json.toString()).nextValue();
|
||||
JSONArray services = object.getJSONArray("services");
|
||||
for (int i = 0; i < services.length(); ++i) {
|
||||
JSONObject service = services.getJSONObject(i);
|
||||
String serviceName = service.getString("name");
|
||||
String className = service.getString("class");
|
||||
registerService(registry, serviceName, className);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
// Not all apps will have a services.json file.
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failure parsing service configuration file", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a third-party service.
|
||||
*/
|
||||
private static void registerService(ServiceRegistry registry, final String serviceName, final String className) {
|
||||
registry.register(serviceName, new ServiceFactory() {
|
||||
@Override
|
||||
public Binding connectToService(FlutterView view, Core core, MessagePipeHandle pipe) {
|
||||
try {
|
||||
return (Binding) Class.forName(className)
|
||||
.getMethod("connectToService", FlutterView.class, Core.class, MessagePipeHandle.class)
|
||||
.invoke(null, view, core, pipe);
|
||||
} catch(Exception e) {
|
||||
Log.e(TAG, "Failed to register service '" + serviceName + "'", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize our Flutter config values by obtaining them from the
|
||||
* manifest XML file, falling back to default values.
|
||||
|
||||
@ -22,9 +22,8 @@
|
||||
namespace shell {
|
||||
|
||||
PlatformServiceProvider::PlatformServiceProvider(
|
||||
mojo::InterfaceRequest<mojo::ServiceProvider> request,
|
||||
DynamicServiceProviderCallback callback)
|
||||
: dynamic_service_provider_(callback), binding_(this, request.Pass()) {}
|
||||
mojo::InterfaceRequest<mojo::ServiceProvider> request)
|
||||
: binding_(this, request.Pass()) {}
|
||||
|
||||
PlatformServiceProvider::~PlatformServiceProvider() {}
|
||||
|
||||
@ -94,8 +93,6 @@ void PlatformServiceProvider::ConnectToService(
|
||||
return;
|
||||
}
|
||||
#endif // TARGET_OS_IPHONE
|
||||
|
||||
dynamic_service_provider_.Run(service_name, client_handle.Pass());
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
|
||||
@ -14,12 +14,7 @@ namespace shell {
|
||||
|
||||
class PlatformServiceProvider : public mojo::ServiceProvider {
|
||||
public:
|
||||
using DynamicServiceProviderCallback =
|
||||
base::Callback<void(const mojo::String& service_name,
|
||||
mojo::ScopedMessagePipeHandle)>;
|
||||
|
||||
PlatformServiceProvider(mojo::InterfaceRequest<mojo::ServiceProvider> request,
|
||||
DynamicServiceProviderCallback callback);
|
||||
PlatformServiceProvider(mojo::InterfaceRequest<mojo::ServiceProvider> request);
|
||||
|
||||
~PlatformServiceProvider() override;
|
||||
|
||||
@ -27,7 +22,6 @@ class PlatformServiceProvider : public mojo::ServiceProvider {
|
||||
mojo::ScopedMessagePipeHandle client_handle) override;
|
||||
|
||||
private:
|
||||
DynamicServiceProviderCallback dynamic_service_provider_;
|
||||
mojo::StrongBinding<mojo::ServiceProvider> binding_;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(PlatformServiceProvider);
|
||||
|
||||
@ -33,11 +33,6 @@ PlatformViewMac::PlatformViewMac(NSOpenGLView* gl_view)
|
||||
|
||||
PlatformViewMac::~PlatformViewMac() = default;
|
||||
|
||||
static void DynamicServiceResolve(const mojo::String& service_name,
|
||||
mojo::ScopedMessagePipeHandle handle) {
|
||||
// This platform does not support dynamic service loading.
|
||||
}
|
||||
|
||||
static void IgnoreRequest(
|
||||
mojo::InterfaceRequest<flutter::platform::ApplicationMessages>) {}
|
||||
|
||||
@ -45,8 +40,7 @@ void PlatformViewMac::ConnectToEngineAndSetupServices() {
|
||||
ConnectToEngine(mojo::GetProxy(&sky_engine_));
|
||||
|
||||
mojo::ServiceProviderPtr service_provider;
|
||||
new PlatformServiceProvider(mojo::GetProxy(&service_provider),
|
||||
base::Bind(DynamicServiceResolve));
|
||||
new PlatformServiceProvider(mojo::GetProxy(&service_provider));
|
||||
|
||||
mojo::ServiceProviderPtr view_service_provider;
|
||||
new ViewServiceProvider(IgnoreRequest,
|
||||
|
||||
@ -33,21 +33,18 @@ shared_library("flutter_framework_dylib") {
|
||||
"framework/Source/FlutterDartProject_Internal.h",
|
||||
"framework/Source/FlutterDartSource.h",
|
||||
"framework/Source/FlutterDartSource.mm",
|
||||
"framework/Source/FlutterDynamicServiceLoader.h",
|
||||
"framework/Source/FlutterDynamicServiceLoader.mm",
|
||||
"framework/Source/FlutterView.h",
|
||||
"framework/Source/FlutterView.mm",
|
||||
"framework/Source/FlutterViewController.mm",
|
||||
"platform_view_ios.h",
|
||||
"platform_view_ios.mm",
|
||||
]
|
||||
|
||||
|
||||
|
||||
deps = [
|
||||
"//base:base",
|
||||
"//dart/runtime:libdart",
|
||||
"//flutter/services/activity",
|
||||
"//flutter/services/dynamic:embedder",
|
||||
"//flutter/services/editing",
|
||||
"//flutter/services/engine:interfaces",
|
||||
"//flutter/services/media",
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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 SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_DYNAMIC_SERVICE_LOADER_H_
|
||||
#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_DYNAMIC_SERVICE_LOADER_H_
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include "flutter/shell/platform/darwin/common/platform_service_provider.h"
|
||||
|
||||
@interface FlutterDynamicServiceLoader : NSObject
|
||||
|
||||
- (void)resolveService:(NSString*)name
|
||||
handle:(mojo::ScopedMessagePipeHandle)handle;
|
||||
|
||||
@end
|
||||
|
||||
#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_DYNAMIC_SERVICE_LOADER_H_
|
||||
@ -1,178 +0,0 @@
|
||||
// Copyright 2016 The Chromium 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/darwin/ios/framework/Source/FlutterDynamicServiceLoader.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "flutter/services/dynamic/dynamic_service_embedder.h"
|
||||
#include "flutter/services/dynamic/dynamic_service_definition.h"
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
@interface FlutterServiceDefinition : NSObject
|
||||
|
||||
@property(nonatomic, readonly) NSString* serviceName;
|
||||
|
||||
@property(nonatomic, readonly) NSString* containerFramework;
|
||||
|
||||
- (instancetype)initWithName:(NSString*)name framework:(NSString*)framework;
|
||||
|
||||
- (void)invokeService:(NSString*)serviceName
|
||||
handle:(mojo::ScopedMessagePipeHandle)handle;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FlutterServiceDefinition {
|
||||
std::unique_ptr<sky::services::DynamicServiceDefinition> _definition;
|
||||
BOOL _initializationAttempted;
|
||||
}
|
||||
|
||||
- (instancetype)initWithName:(NSString*)name framework:(NSString*)framework {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
if (name.length == 0 || framework.length == 0) {
|
||||
[self release];
|
||||
return nil;
|
||||
}
|
||||
|
||||
_serviceName = [name copy];
|
||||
_containerFramework = [framework copy];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)openIfNecessary {
|
||||
if (_definition || _initializationAttempted) {
|
||||
return;
|
||||
}
|
||||
|
||||
mojo::String dylib_path([[NSBundle mainBundle]
|
||||
pathForResource:_containerFramework
|
||||
ofType:@"dylib"
|
||||
inDirectory:@"Frameworks"]
|
||||
.UTF8String);
|
||||
|
||||
_definition = sky::services::DynamicServiceDefinition::Initialize(dylib_path);
|
||||
|
||||
if (!_definition) {
|
||||
LOG(ERROR) << "Could not load dynamic service for '"
|
||||
<< _serviceName.UTF8String << "'";
|
||||
}
|
||||
|
||||
// All known services are in the application bundle. If the service cannot
|
||||
// be initialized once, dont attempt any more loads.
|
||||
_initializationAttempted = YES;
|
||||
}
|
||||
|
||||
- (void)invokeService:(NSString*)serviceName
|
||||
handle:(mojo::ScopedMessagePipeHandle)handle {
|
||||
[self openIfNecessary];
|
||||
if (_definition) {
|
||||
_definition->InvokeServiceHandler(handle.Pass(), serviceName.UTF8String);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)closeIfNecessary {
|
||||
_definition = nullptr;
|
||||
_initializationAttempted = NO;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self closeIfNecessary];
|
||||
|
||||
[_serviceName release];
|
||||
[_containerFramework release];
|
||||
|
||||
[super dealloc];
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
@implementation FlutterDynamicServiceLoader {
|
||||
NSMutableDictionary* _services;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_services = [[NSMutableDictionary alloc] init];
|
||||
|
||||
[self populateServiceDefinitions];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)resolveService:(NSString*)serviceName
|
||||
handle:(mojo::ScopedMessagePipeHandle)handle {
|
||||
if (serviceName.length == 0) {
|
||||
LOG(INFO) << "Invalid service name";
|
||||
return;
|
||||
}
|
||||
|
||||
[_services[serviceName] invokeService:serviceName handle:handle.Pass()];
|
||||
}
|
||||
|
||||
- (void)populateServiceDefinitions {
|
||||
NSString* definitionsPath =
|
||||
[[NSBundle mainBundle] pathForResource:@"ServiceDefinitions"
|
||||
ofType:@"json"];
|
||||
|
||||
if (definitionsPath.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSData* data = [NSData dataWithContentsOfFile:definitionsPath];
|
||||
|
||||
if (data.length == 0) {
|
||||
LOG(INFO) << "The service definitions manifest could not be read. No "
|
||||
"custom services will be available.";
|
||||
return;
|
||||
}
|
||||
|
||||
NSError* error = nil;
|
||||
NSDictionary* servicesData =
|
||||
[NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
|
||||
|
||||
if (error != nil || ![servicesData isKindOfClass:[NSDictionary class]]) {
|
||||
LOG(INFO) << "Corrupt service definitions manifest. No custom services "
|
||||
"will be available";
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray* services = servicesData[@"services"];
|
||||
|
||||
if (![services isKindOfClass:[NSArray class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSDictionary* service in services) {
|
||||
if (![service isKindOfClass:[NSDictionary class]]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString* serviceName = service[@"name"];
|
||||
|
||||
FlutterServiceDefinition* definition =
|
||||
[[FlutterServiceDefinition alloc] initWithName:serviceName
|
||||
framework:service[@"framework"]];
|
||||
|
||||
if (definition != nil) {
|
||||
_services[serviceName] = definition;
|
||||
}
|
||||
|
||||
[definition release];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_services release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
@ -13,7 +13,6 @@
|
||||
#include "flutter/services/platform/app_messages.mojom.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/application_messages_impl.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDynamicServiceLoader.h"
|
||||
#include "flutter/shell/common/platform_view.h"
|
||||
|
||||
@class CAEAGLLayer;
|
||||
@ -60,7 +59,6 @@ class PlatformViewIOS : public PlatformView {
|
||||
flutter::platform::ApplicationMessagesPtr app_message_sender_;
|
||||
ApplicationMessagesImpl app_message_receiver_;
|
||||
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
|
||||
base::scoped_nsprotocol<FlutterDynamicServiceLoader*> dynamic_service_loader_;
|
||||
ftl::WeakPtrFactory<PlatformViewIOS> weak_factory_;
|
||||
|
||||
void SetupAndLoadFromSource(const std::string& main,
|
||||
|
||||
@ -273,7 +273,6 @@ class IOSGLContext {
|
||||
|
||||
PlatformViewIOS::PlatformViewIOS(CAEAGLLayer* layer)
|
||||
: context_(WTF::MakeUnique<IOSGLContext>(surface_config_, layer)),
|
||||
dynamic_service_loader_([[FlutterDynamicServiceLoader alloc] init]),
|
||||
weak_factory_(this) {
|
||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
|
||||
NSUserDomainMask, YES);
|
||||
@ -306,14 +305,6 @@ void PlatformViewIOS::ToggleAccessibility(UIView* view, bool enable) {
|
||||
}
|
||||
}
|
||||
|
||||
static void DynamicServiceResolve(void* baton,
|
||||
const mojo::String& service_name,
|
||||
mojo::ScopedMessagePipeHandle handle) {
|
||||
base::mac::ScopedNSAutoreleasePool pool;
|
||||
auto loader = reinterpret_cast<FlutterDynamicServiceLoader*>(baton);
|
||||
[loader resolveService:@(service_name.data()) handle:handle.Pass()];
|
||||
}
|
||||
|
||||
void PlatformViewIOS::ConnectToEngineAndSetupServices() {
|
||||
ConnectToEngine(mojo::GetProxy(&engine_));
|
||||
|
||||
@ -321,12 +312,7 @@ void PlatformViewIOS::ConnectToEngineAndSetupServices() {
|
||||
|
||||
auto service_provider_proxy = mojo::GetProxy(&service_provider);
|
||||
|
||||
auto service_resolution_callback = base::Bind(
|
||||
&DynamicServiceResolve,
|
||||
base::Unretained(reinterpret_cast<void*>(dynamic_service_loader_.get())));
|
||||
|
||||
new PlatformServiceProvider(service_provider_proxy.Pass(),
|
||||
service_resolution_callback);
|
||||
new PlatformServiceProvider(service_provider_proxy.Pass());
|
||||
|
||||
ftl::WeakPtr<ApplicationMessagesImpl> appplication_messages_impl =
|
||||
app_message_receiver_.GetWeakPtr();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user