summaryrefslogtreecommitdiffstats
path: root/mojo/public/js/connection.js
blob: 3976efd92c76c6c9b0c4de1009d79bd29d757774 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// 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);
    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);

  function createOpenConnection(
      messagePipeHandle, client, localInterface, remoteInterface) {
    var stubClass = (localInterface && localInterface.stubClass) || EmptyStub;
    var proxyClass =
        (remoteInterface && remoteInterface.proxyClass) || EmptyProxy;
    var proxy = new proxyClass;
    var stub = new stubClass;
    var router = new Router(messagePipeHandle);
    var connection = new BaseConnection(stub, proxy, router);

    ProxyBindings(proxy).connection = connection;
    ProxyBindings(proxy).local = connection.local;
    StubBindings(stub).connection = connection;
    StubBindings(proxy).remote = connection.remote;

    var clientImpl = client instanceof Function ? client(proxy) : client;
    if (clientImpl)
      StubBindings(stub).delegate = clientImpl;

    return connection;
  }

  // Return a message pipe handle.
  function bindProxyClient(clientImpl, localInterface, remoteInterface) {
    var messagePipe = core.createMessagePipe();
    if (messagePipe.result != core.RESULT_OK)
      throw new Error("createMessagePipe failed " + messagePipe.result);

    createOpenConnection(
      messagePipe.handle0, clientImpl, localInterface, remoteInterface);
    return messagePipe.handle1;
  }

  // Return a proxy.
  function bindProxyHandle(proxyHandle, localInterface, remoteInterface) {
    if (!core.isHandle(proxyHandle))
      throw new Error("Not a handle " + proxyHandle);

    var connection = createOpenConnection(
        proxyHandle, undefined, localInterface, remoteInterface);
    return connection.remote;
  }

  var exports = {};
  exports.Connection = Connection;
  exports.TestConnection = TestConnection;
  exports.bindProxyHandle = bindProxyHandle;
  exports.bindProxyClient = bindProxyClient;
  return exports;
});