Adam Barth fbc0950da4 Factor MojoShell into shell.dart
Putting this code in a separate library let's services that depend only on the
shell be clearer about their dependencies.
2016-03-04 13:48:28 -08:00

100 lines
4.4 KiB
Dart

// Copyright 2015 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.
/// Manages connections with embedder-provided services.
library shell;
import 'dart:ui' as ui;
import 'package:mojo/application.dart';
import 'package:mojo/bindings.dart' as bindings;
import 'package:mojo/core.dart' as core;
import 'package:mojo/mojo/service_provider.mojom.dart' as mojom;
import 'package:mojo/mojo/shell.mojom.dart' as mojom;
/// A replacement for shell.connectToService. Implementations should return true
/// if they handled the request, or false if the request should fall through
/// to the default requestService.
typedef bool OverrideConnectToService(String url, Object proxy);
/// Manages connections with embedder-provided services.
class MojoShell {
MojoShell() {
assert(_instance == null);
_instance = this;
}
/// The unique instance of this class.
static MojoShell get instance => _instance;
static MojoShell _instance;
static mojom.ShellProxy _initShellProxy() {
core.MojoHandle shellHandle = new core.MojoHandle(ui.takeShellProxyHandle());
if (!shellHandle.isValid)
return null;
return new mojom.ShellProxy.fromHandle(shellHandle);
}
final mojom.Shell _shell = _initShellProxy()?.ptr;
static ApplicationConnection _initEmbedderConnection() {
core.MojoHandle servicesHandle = new core.MojoHandle(ui.takeServicesProvidedByEmbedder());
core.MojoHandle exposedServicesHandle = new core.MojoHandle(ui.takeServicesProvidedToEmbedder());
if (!servicesHandle.isValid || !exposedServicesHandle.isValid)
return null;
mojom.ServiceProviderProxy services = new mojom.ServiceProviderProxy.fromHandle(servicesHandle);
mojom.ServiceProviderStub exposedServices = new mojom.ServiceProviderStub.fromHandle(exposedServicesHandle);
return new ApplicationConnection(exposedServices, services);
}
final ApplicationConnection _embedderConnection = _initEmbedderConnection();
/// Attempts to connect to an application via the Mojo shell.
ApplicationConnection connectToApplication(String url) {
if (_shell == null)
return null;
mojom.ServiceProviderProxy services = new mojom.ServiceProviderProxy.unbound();
mojom.ServiceProviderStub exposedServices = new mojom.ServiceProviderStub.unbound();
_shell.connectToApplication(url, services, exposedServices);
return new ApplicationConnection(exposedServices, services);
}
/// Set this to intercept calls to [connectToService()] and supply an
/// alternative implementation of a service (for example, a mock for testing).
OverrideConnectToService overrideConnectToService;
/// Attempts to connect to a service implementing the interface for the given proxy.
/// If an application URL is specified, the service will be requested from that application.
/// Otherwise, it will be requested from the embedder (the Flutter engine).
void connectToService(String url, bindings.ProxyBase proxy) {
if (overrideConnectToService != null && overrideConnectToService(url, proxy))
return;
if (url == null || _shell == null) {
// If the application URL is null, it means the service to connect
// to is one provided by the embedder.
// If the applircation URL isn't null but there's no shell, then
// ask the embedder in case it provides it. (For example, if you're
// running on Android without the Mojo shell, then you can obtain
// the media service from the embedder directly, instead of having
// to ask the media application for it.)
// This makes it easier to write an application that works both
// with and without a Mojo environment.
_embedderConnection?.requestService(proxy);
return;
}
mojom.ServiceProviderProxy services = new mojom.ServiceProviderProxy.unbound();
_shell.connectToApplication(url, services, null);
core.MojoMessagePipe pipe = new core.MojoMessagePipe();
proxy.impl.bind(pipe.endpoints[0]);
services.ptr.connectToService(proxy.serviceName, pipe.endpoints[1]);
services.close();
}
/// Registers a service to expose to the embedder.
void provideService(String interfaceName, ServiceFactory factory) {
_embedderConnection?.provideService(interfaceName, factory);
}
}
/// The singleton object that manages connections with embedder-provided services.
MojoShell get shell => MojoShell.instance;