Remove support for dynamic Mojo services (#3089)

Instead, clients should use host messaging.
This commit is contained in:
Adam Barth 2016-10-03 21:02:52 -07:00 committed by GitHub
parent 862d9e9f6b
commit 2601064d47
21 changed files with 6 additions and 857 deletions

View File

@ -20,12 +20,6 @@ group("flutter") {
"//flutter/sky",
]
}
if (is_ios) {
deps += [
"//flutter/services/dynamic:sdk_lib_archive",
]
}
}
if (!is_fuchsia) {

View File

@ -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
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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;
}

View File

@ -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_

View File

@ -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";

View File

@ -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_

View File

@ -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_

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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",

View File

@ -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_

View File

@ -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

View File

@ -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,

View File

@ -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();