// 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/public/js/connection", [
"mojo/public/js/bindings",
"mojo/public/js/connector",
"mojo/public/js/core",
"mojo/public/js/router",
], function(bindings, connector, core, router) {
var Router = router.Router;
var EmptyProxy = bindings.EmptyProxy;
var EmptyStub = bindings.EmptyStub;
var ProxyBindings = bindings.ProxyBindings;
var StubBindings = bindings.StubBindings;
var TestConnector = connector.TestConnector;
var TestRouter = router.TestRouter;
// TODO(hansmuller): the proxy receiver_ property should be receiver$
function BaseConnection(localStub, remoteProxy, router) {
this.router_ = router;
this.local = localStub;
this.remote = remoteProxy;
this.router_.setIncomingReceiver(localStub);
this.router_.setErrorHandler(function() {
if (StubBindings(this.local) &&
StubBindings(this.local).connectionErrorHandler)
StubBindings(this.local).connectionErrorHandler();
}.bind(this));
if (this.remote)
this.remote.receiver_ = router;
// Validate incoming messages: remote responses and local requests.
var validateRequest = localStub && localStub.validator;
var validateResponse = remoteProxy && remoteProxy.validator;
var payloadValidators = [];
if (validateRequest)
payloadValidators.push(validateRequest);
if (validateResponse)
payloadValidators.push(validateResponse);
this.router_.setPayloadValidators(payloadValidators);
}
BaseConnection.prototype.close = function() {
this.router_.close();
this.router_ = null;
this.local = null;
this.remote = null;
};
BaseConnection.prototype.encounteredError = function() {
return this.router_.encounteredError();
};
function Connection(
handle, localFactory, remoteFactory, routerFactory, connectorFactory) {
var routerClass = routerFactory || Router;
var router = new routerClass(handle, connectorFactory);
var remoteProxy = remoteFactory && new remoteFactory(router);
var localStub = localFactory && new localFactory(remoteProxy);
BaseConnection.call(this, localStub, remoteProxy, router);
}
Connection.prototype = Object.create(BaseConnection.prototype);
// The TestConnection subclass is only intended to be used in unit tests.
function TestConnection(handle, localFactory, remoteFactory) {
Connection.call(this,
handle,
localFactory,
remoteFactory,
TestRouter,
TestConnector);
}
TestConnection.prototype = Object.create(Connection.prototype);
// Return a handle for a message pipe that's connected to a proxy
// for remoteInterface. Used by generated code for outgoing interface&
// (request) parameters: the caller is given the generated proxy via
// |proxyCallback(proxy)| and the generated code sends the handle
// returned by this function.
function bindProxy(proxyCallback, remoteInterface) {
var messagePipe = core.createMessagePipe();
if (messagePipe.result != core.RESULT_OK)
throw new Error("createMessagePipe failed " + messagePipe.result);
var proxy = new remoteInterface.proxyClass;
var router = new Router(messagePipe.handle0);
var connection = new BaseConnection(undefined, proxy, router);
ProxyBindings(proxy).connection = connection;
if (proxyCallback)
proxyCallback(proxy);
return messagePipe.handle1;
}
// Return a handle for a message pipe that's connected to a stub for
// localInterface. Used by generated code for outgoing interface
// parameters: the caller is given the generated stub via
// |stubCallback(stub)| and the generated code sends the handle
// returned by this function. The caller is responsible for managing
// the lifetime of the stub and for setting it's implementation
// delegate with: StubBindings(stub).delegate = myImpl;
function bindImpl(stubCallback, localInterface) {
var messagePipe = core.createMessagePipe();
if (messagePipe.result != core.RESULT_OK)
throw new Error("createMessagePipe failed " + messagePipe.result);
var stub = new localInterface.stubClass;
var router = new Router(messagePipe.handle0);
var connection = new BaseConnection(stub, undefined, router);
StubBindings(stub).connection = connection;
if (stubCallback)
stubCallback(stub);
return messagePipe.handle1;
}
// Return a remoteInterface proxy for handle. Used by generated code
// for converting incoming interface parameters to proxies.
function bindHandleToProxy(handle, remoteInterface) {
if (!core.isHandle(handle))
throw new Error("Not a handle " + handle);
var proxy = new remoteInterface.proxyClass;
var router = new Router(handle);
var connection = new BaseConnection(undefined, proxy, router);
ProxyBindings(proxy).connection = connection;
return proxy;
}
// Return a localInterface stub for handle. Used by generated code
// for converting incoming interface& request parameters to localInterface
// stubs. The caller can specify the stub's implementation of localInterface
// like this: StubBindings(stub).delegate = myStubImpl.
function bindHandleToStub(handle, localInterface) {
if (!core.isHandle(handle))
throw new Error("Not a handle " + handle);
var stub = new localInterface.stubClass;
var router = new Router(handle);
var connection = new BaseConnection(stub, undefined, router);
StubBindings(stub).connection = connection;
return stub;
}
/**
* Creates a messape pipe and links one end of the pipe to the given object.
* @param {!Object} obj The object to create a handle for. Must be a subclass
* of an auto-generated stub class.
* @return {!MojoHandle} The other (not yet connected) end of the message
* pipe.
*/
function bindStubDerivedImpl(obj) {
var pipe = core.createMessagePipe();
var router = new Router(pipe.handle0);
var connection = new BaseConnection(obj, undefined, router);
obj.connection = connection;
return pipe.handle1;
}
var exports = {};
exports.Connection = Connection;
exports.TestConnection = TestConnection;
exports.bindProxy = bindProxy;
exports.bindImpl = bindImpl;
exports.bindHandleToProxy = bindHandleToProxy;
exports.bindHandleToStub = bindHandleToStub;
exports.bindStubDerivedImpl = bindStubDerivedImpl;
return exports;
});