| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 define("mojo/services/public/js/service_provider", [ | 5 define("mojo/services/public/js/service_provider", [ |
| 6 "mojo/public/interfaces/application/service_provider.mojom", | 6 "mojo/public/interfaces/application/service_provider.mojom", |
| 7 "mojo/public/js/connection", | 7 "mojo/public/js/connection", |
| 8 "mojo/public/js/core", | 8 ], function(serviceProviderMojom, connection) { |
| 9 ], function(spInterfaceModule, connectionModule, coreModule) { | |
| 10 | 9 |
| 11 // Implementation of the Mojo ServiceProvider interface. | 10 const ServiceProviderInterface = serviceProviderMojom.ServiceProvider; |
| 12 function connectToServiceImpl(serviceName, serviceHandle) { | |
| 13 var provider = this.providers_.get(serviceName); | |
| 14 if (!provider) { | |
| 15 this.pendingRequests_.set(serviceName, serviceHandle); | |
| 16 return; | |
| 17 } | |
| 18 | |
| 19 var serviceConnection = new connectionModule.Connection( | |
| 20 serviceHandle, | |
| 21 provider.service.stubClass, | |
| 22 provider.service.client && provider.service.client.proxyClass); | |
| 23 | |
| 24 serviceConnection.local.delegate$ = | |
| 25 new provider.factory(serviceConnection.remote); | |
| 26 | |
| 27 provider.connections.push(serviceConnection); | |
| 28 } | |
| 29 | 11 |
| 30 function checkServiceProvider(sp) { | 12 function checkServiceProvider(sp) { |
| 31 if (!sp.connections_) | 13 if (!sp.providers_) |
| 32 throw new Error("Service was closed"); | 14 throw new Error("Service was closed"); |
| 33 } | 15 } |
| 34 | 16 |
| 35 class ServiceProvider { | 17 class ServiceProvider { |
| 36 constructor(service) { | 18 constructor(service) { |
| 37 if (!(service instanceof spInterfaceModule.ServiceProvider.proxyClass)) | 19 if (!(service instanceof ServiceProviderInterface.proxyClass)) |
| 38 throw new Error("service must be a ServiceProvider proxy"); | 20 throw new Error("service must be a ServiceProvider proxy"); |
| 21 service.local$ = this; // Implicitly sets this.remote$ to service. |
| 22 this.providers_ = new Map(); // serviceName => see provideService() below |
| 23 this.pendingRequests_ = new Map(); // serviceName => serviceHandle |
| 24 } |
| 39 | 25 |
| 40 service.client$ = { | 26 // Incoming requests |
| 41 connectToService: connectToServiceImpl.bind(this) | 27 connectToService(serviceName, serviceHandle) { |
| 42 }; | 28 if (!this.providers_) // We're closed. |
| 29 return; |
| 43 | 30 |
| 44 this.connections_ = new Map(); | 31 var provider = this.providers_.get(serviceName); |
| 45 this.providers_ = new Map(); | 32 if (!provider) { |
| 46 this.pendingRequests_ = new Map(); | 33 this.pendingRequests_.set(serviceName, serviceHandle); |
| 47 this.connection_ = null; | 34 return; |
| 48 this.connection_ = service.getConnection$(); | 35 } |
| 36 var proxy = connection.bindProxyHandle( |
| 37 serviceHandle, provider.service, provider.service.client); |
| 38 proxy.local$ = new provider.factory(proxy); |
| 39 provider.connections.push(proxy.connection$); |
| 49 } | 40 } |
| 50 | 41 |
| 51 provideService(service, factory) { | 42 provideService(service, factory) { |
| 52 // TODO(hansmuller): if !factory, remove provider and close its | |
| 53 // connections. | |
| 54 checkServiceProvider(this); | 43 checkServiceProvider(this); |
| 55 | 44 |
| 56 var provider = { | 45 var provider = { |
| 57 service: service, // A JS bindings interface object. | 46 service: service, // A JS bindings interface object. |
| 58 factory: factory, // factory(clientProxy) => interface implemntation. | 47 factory: factory, // factory(clientProxy) => interface implemntation |
| 59 connections: [], | 48 connections: [], |
| 60 }; | 49 }; |
| 61 this.providers_.set(service.name, provider); | 50 this.providers_.set(service.name, provider); |
| 62 | 51 |
| 63 if (this.pendingRequests_.has(service.name)) { | 52 if (this.pendingRequests_.has(service.name)) { |
| 64 connectToServiceImpl(service.name, pendingRequests_.get(service.name)); | 53 this.connectToService(service.name, pendingRequests_.get(service.name)); |
| 65 pendingRequests_.delete(service.name); | 54 pendingRequests_.delete(service.name); |
| 66 } | 55 } |
| 67 | |
| 68 return this; | 56 return this; |
| 69 } | 57 } |
| 70 | 58 |
| 71 connectToService(service, client) { | 59 // Outgoing requests |
| 60 requestService(interfaceObject, clientImpl) { |
| 72 checkServiceProvider(this); | 61 checkServiceProvider(this); |
| 73 if (!service.name) | 62 if (!interfaceObject.name) |
| 74 throw new Error("Invalid service parameter"); | 63 throw new Error("Invalid service parameter"); |
| 64 if (!clientImpl && interfaceObject.client) |
| 65 throw new Error("Client implementation must be provided"); |
| 75 | 66 |
| 76 var serviceConnection = this.connections_.get(service.name); | 67 if (!clientImpl) |
| 77 if (serviceConnection) | 68 clientImpl = {}; |
| 78 return serviceConnection.remote; | 69 var messagePipeHandle = connection.bindProxyClient( |
| 79 | 70 clientImpl, interfaceObject.client, interfaceObject); |
| 80 var pipe = coreModule.createMessagePipe(); | 71 this.remote$.connectToService(interfaceObject.name, messagePipeHandle); |
| 81 this.connection_.remote.connectToService(service.name, pipe.handle1); | 72 return clientImpl.remote$; |
| 82 var clientClass = client && service.client.stubClass; | |
| 83 var serviceConnection = new connectionModule.Connection( | |
| 84 pipe.handle0, clientClass, service.proxyClass); | |
| 85 if (serviceConnection.local) | |
| 86 serviceConnection.local.delegate$ = client; | |
| 87 | |
| 88 this.connections_.set(service.name, serviceConnection); | |
| 89 return serviceConnection.remote; | |
| 90 }; | 73 }; |
| 91 | 74 |
| 92 close() { | 75 close() { |
| 93 if (!this.connection_) | 76 this.providers_ = null; |
| 94 return; | 77 this.pendingRequests_ = null; |
| 95 | |
| 96 try { | |
| 97 // Outgoing connections | |
| 98 this.connections_.forEach(function(connection, serviceName) { | |
| 99 connection.close(); | |
| 100 }); | |
| 101 // Incoming connections | |
| 102 this.providers_.forEach(function(provider, serviceName) { | |
| 103 provider.connections.forEach(function(connection) { | |
| 104 connection.close(); | |
| 105 }); | |
| 106 }); | |
| 107 this.connection_.close(); | |
| 108 } finally { | |
| 109 this.connections_ = null; | |
| 110 this.providers_ = null; | |
| 111 this.pendingRequests_ = null; | |
| 112 this.connection_ = null; | |
| 113 this.handle_ = null; | |
| 114 } | |
| 115 } | 78 } |
| 116 } | 79 } |
| 117 | 80 |
| 118 var exports = {}; | 81 var exports = {}; |
| 119 exports.ServiceProvider = ServiceProvider; | 82 exports.ServiceProvider = ServiceProvider; |
| 120 return exports; | 83 return exports; |
| 121 }); | 84 }); |
| OLD | NEW |