blob: 88fef4ef265c944a3239bcef5b8d7a3b51accaf8 [file] [log] [blame]
// Copyright 2014 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.
define("mojo/services/public/js/service_provider", [
"mojo/public/interfaces/application/service_provider.mojom",
"mojo/public/js/connection",
"mojo/public/js/core",
], function(spInterfaceModule, connectionModule, coreModule) {
// Implementation of the Mojo ServiceProvider interface.
function connectToServiceImpl(serviceName, serviceHandle) {
var provider = this.providers_.get(serviceName);
if (!provider) {
this.pendingRequests_.set(serviceName, serviceHandle);
return;
}
var serviceConnection = new connectionModule.Connection(
serviceHandle,
provider.service.stubClass,
provider.service.client && provider.service.client.proxyClass);
serviceConnection.local.delegate$ =
new provider.factory(serviceConnection.remote);
provider.connections.push(serviceConnection);
}
function checkServiceProvider(sp) {
if (!sp.connections_)
throw new Error("Service was closed");
}
class ServiceProvider {
constructor(service) {
if (!(service instanceof spInterfaceModule.ServiceProvider.proxyClass))
throw new Error("service must be a ServiceProvider proxy");
service.client$ = {
connectToService: connectToServiceImpl.bind(this)
};
this.connections_ = new Map();
this.providers_ = new Map();
this.pendingRequests_ = new Map();
this.connection_ = null;
this.connection_ = service.getConnection$();
}
provideService(service, factory) {
// TODO(hansmuller): if !factory, remove provider and close its
// connections.
checkServiceProvider(this);
var provider = {
service: service, // A JS bindings interface object.
factory: factory, // factory(clientProxy) => interface implemntation.
connections: [],
};
this.providers_.set(service.name, provider);
if (this.pendingRequests_.has(service.name)) {
connectToServiceImpl(service.name, pendingRequests_.get(service.name));
pendingRequests_.delete(service.name);
}
return this;
}
connectToService(service, client) {
checkServiceProvider(this);
if (!service.name)
throw new Error("Invalid service parameter");
var serviceConnection = this.connections_.get(service.name);
if (serviceConnection)
return serviceConnection.remote;
var pipe = coreModule.createMessagePipe();
this.connection_.remote.connectToService(service.name, pipe.handle1);
var clientClass = client && service.client.stubClass;
var serviceConnection = new connectionModule.Connection(
pipe.handle0, clientClass, service.proxyClass);
if (serviceConnection.local)
serviceConnection.local.delegate$ = client;
this.connections_.set(service.name, serviceConnection);
return serviceConnection.remote;
};
close() {
if (!this.connection_)
return;
try {
// Outgoing connections
this.connections_.forEach(function(connection, serviceName) {
connection.close();
});
// Incoming connections
this.providers_.forEach(function(provider, serviceName) {
provider.connections.forEach(function(connection) {
connection.close();
});
});
this.connection_.close();
} finally {
this.connections_ = null;
this.providers_ = null;
this.pendingRequests_ = null;
this.connection_ = null;
this.handle_ = null;
}
}
}
var exports = {};
exports.ServiceProvider = ServiceProvider;
return exports;
});