• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3// found in the LICENSE file.
4
5define("mojo/public/js/connection", [
6  "mojo/public/js/bindings",
7  "mojo/public/js/connector",
8  "mojo/public/js/core",
9  "mojo/public/js/router",
10], function(bindings, connector, core, router) {
11
12  var Router = router.Router;
13  var EmptyProxy = bindings.EmptyProxy;
14  var EmptyStub = bindings.EmptyStub;
15  var ProxyBindings = bindings.ProxyBindings;
16  var StubBindings = bindings.StubBindings;
17  var TestConnector = connector.TestConnector;
18  var TestRouter = router.TestRouter;
19
20  // TODO(hansmuller): the proxy receiver_ property should be receiver$
21
22  function BaseConnection(localStub, remoteProxy, router) {
23    this.router_ = router;
24    this.local = localStub;
25    this.remote = remoteProxy;
26
27    this.router_.setIncomingReceiver(localStub);
28    this.router_.setErrorHandler(function() {
29      if (StubBindings(this.local) &&
30          StubBindings(this.local).connectionErrorHandler)
31        StubBindings(this.local).connectionErrorHandler();
32    }.bind(this));
33    if (this.remote)
34      this.remote.receiver_ = router;
35
36    // Validate incoming messages: remote responses and local requests.
37    var validateRequest = localStub && localStub.validator;
38    var validateResponse = remoteProxy && remoteProxy.validator;
39    var payloadValidators = [];
40    if (validateRequest)
41      payloadValidators.push(validateRequest);
42    if (validateResponse)
43      payloadValidators.push(validateResponse);
44    this.router_.setPayloadValidators(payloadValidators);
45  }
46
47  BaseConnection.prototype.close = function() {
48    this.router_.close();
49    this.router_ = null;
50    this.local = null;
51    this.remote = null;
52  };
53
54  BaseConnection.prototype.encounteredError = function() {
55    return this.router_.encounteredError();
56  };
57
58  function Connection(
59      handle, localFactory, remoteFactory, routerFactory, connectorFactory) {
60    var routerClass = routerFactory || Router;
61    var router = new routerClass(handle, connectorFactory);
62    var remoteProxy = remoteFactory && new remoteFactory(router);
63    var localStub = localFactory && new localFactory(remoteProxy);
64    BaseConnection.call(this, localStub, remoteProxy, router);
65  }
66
67  Connection.prototype = Object.create(BaseConnection.prototype);
68
69  // The TestConnection subclass is only intended to be used in unit tests.
70  function TestConnection(handle, localFactory, remoteFactory) {
71    Connection.call(this,
72                    handle,
73                    localFactory,
74                    remoteFactory,
75                    TestRouter,
76                    TestConnector);
77  }
78
79  TestConnection.prototype = Object.create(Connection.prototype);
80
81  // Return a handle for a message pipe that's connected to a proxy
82  // for remoteInterface. Used by generated code for outgoing interface&
83  // (request) parameters: the caller is given the generated proxy via
84  // |proxyCallback(proxy)| and the generated code sends the handle
85  // returned by this function.
86  function bindProxy(proxyCallback, remoteInterface) {
87    var messagePipe = core.createMessagePipe();
88    if (messagePipe.result != core.RESULT_OK)
89      throw new Error("createMessagePipe failed " + messagePipe.result);
90
91    var proxy = new remoteInterface.proxyClass;
92    var router = new Router(messagePipe.handle0);
93    var connection = new BaseConnection(undefined, proxy, router);
94    ProxyBindings(proxy).connection = connection;
95    if (proxyCallback)
96      proxyCallback(proxy);
97
98    return messagePipe.handle1;
99  }
100
101  // Return a handle for a message pipe that's connected to a stub for
102  // localInterface. Used by generated code for outgoing interface
103  // parameters: the caller  is given the generated stub via
104  // |stubCallback(stub)| and the generated code sends the handle
105  // returned by this function. The caller is responsible for managing
106  // the lifetime of the stub and for setting it's implementation
107  // delegate with: StubBindings(stub).delegate = myImpl;
108  function bindImpl(stubCallback, localInterface) {
109    var messagePipe = core.createMessagePipe();
110    if (messagePipe.result != core.RESULT_OK)
111      throw new Error("createMessagePipe failed " + messagePipe.result);
112
113    var stub = new localInterface.stubClass;
114    var router = new Router(messagePipe.handle0);
115    var connection = new BaseConnection(stub, undefined, router);
116    StubBindings(stub).connection = connection;
117    if (stubCallback)
118      stubCallback(stub);
119
120    return messagePipe.handle1;
121  }
122
123  // Return a remoteInterface proxy for handle. Used by generated code
124  // for converting incoming interface parameters to proxies.
125  function bindHandleToProxy(handle, remoteInterface) {
126    if (!core.isHandle(handle))
127      throw new Error("Not a handle " + handle);
128
129    var proxy = new remoteInterface.proxyClass;
130    var router = new Router(handle);
131    var connection = new BaseConnection(undefined, proxy, router);
132    ProxyBindings(proxy).connection = connection;
133    return proxy;
134  }
135
136  // Return a localInterface stub for handle. Used by generated code
137  // for converting incoming interface& request parameters to localInterface
138  // stubs. The caller can specify the stub's implementation of localInterface
139  // like this: StubBindings(stub).delegate = myStubImpl.
140  function bindHandleToStub(handle, localInterface) {
141    if (!core.isHandle(handle))
142      throw new Error("Not a handle " + handle);
143
144    var stub = new localInterface.stubClass;
145    var router = new Router(handle);
146    var connection = new BaseConnection(stub, undefined, router);
147    StubBindings(stub).connection = connection;
148    return stub;
149  }
150
151  /**
152   * Creates a messape pipe and links one end of the pipe to the given object.
153   * @param {!Object} obj The object to create a handle for. Must be a subclass
154   *     of an auto-generated stub class.
155   * @return {!MojoHandle} The other (not yet connected) end of the message
156   *     pipe.
157   */
158  function bindStubDerivedImpl(obj) {
159    var pipe = core.createMessagePipe();
160    var router = new Router(pipe.handle0);
161    var connection = new BaseConnection(obj, undefined, router);
162    obj.connection = connection;
163    return pipe.handle1;
164  }
165
166  var exports = {};
167  exports.Connection = Connection;
168  exports.TestConnection = TestConnection;
169
170  exports.bindProxy = bindProxy;
171  exports.bindImpl = bindImpl;
172  exports.bindHandleToProxy = bindHandleToProxy;
173  exports.bindHandleToStub = bindHandleToStub;
174  exports.bindStubDerivedImpl = bindStubDerivedImpl;
175  return exports;
176});
177