xref: /aosp_15_r20/external/libchrome/mojo/public/js/lib/router.js (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker// Copyright 2014 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker// found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker(function() {
6*635a8641SAndroid Build Coastguard Worker  var internal = mojo.internal;
7*635a8641SAndroid Build Coastguard Worker
8*635a8641SAndroid Build Coastguard Worker  /**
9*635a8641SAndroid Build Coastguard Worker   * The state of |endpoint|. If both the endpoint and its peer have been
10*635a8641SAndroid Build Coastguard Worker   * closed, removes it from |endpoints_|.
11*635a8641SAndroid Build Coastguard Worker   * @enum {string}
12*635a8641SAndroid Build Coastguard Worker   */
13*635a8641SAndroid Build Coastguard Worker  var EndpointStateUpdateType = {
14*635a8641SAndroid Build Coastguard Worker    ENDPOINT_CLOSED: 'endpoint_closed',
15*635a8641SAndroid Build Coastguard Worker    PEER_ENDPOINT_CLOSED: 'peer_endpoint_closed'
16*635a8641SAndroid Build Coastguard Worker  };
17*635a8641SAndroid Build Coastguard Worker
18*635a8641SAndroid Build Coastguard Worker  function check(condition, output) {
19*635a8641SAndroid Build Coastguard Worker    if (!condition) {
20*635a8641SAndroid Build Coastguard Worker      // testharness.js does not rethrow errors so the error stack needs to be
21*635a8641SAndroid Build Coastguard Worker      // included as a string in the error we throw for debugging layout tests.
22*635a8641SAndroid Build Coastguard Worker      throw new Error((new Error()).stack);
23*635a8641SAndroid Build Coastguard Worker    }
24*635a8641SAndroid Build Coastguard Worker  }
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker  function InterfaceEndpoint(router, interfaceId) {
27*635a8641SAndroid Build Coastguard Worker    this.router_ = router;
28*635a8641SAndroid Build Coastguard Worker    this.id = interfaceId;
29*635a8641SAndroid Build Coastguard Worker    this.closed = false;
30*635a8641SAndroid Build Coastguard Worker    this.peerClosed = false;
31*635a8641SAndroid Build Coastguard Worker    this.handleCreated = false;
32*635a8641SAndroid Build Coastguard Worker    this.disconnectReason = null;
33*635a8641SAndroid Build Coastguard Worker    this.client = null;
34*635a8641SAndroid Build Coastguard Worker  }
35*635a8641SAndroid Build Coastguard Worker
36*635a8641SAndroid Build Coastguard Worker  InterfaceEndpoint.prototype.sendMessage = function(message) {
37*635a8641SAndroid Build Coastguard Worker    message.setInterfaceId(this.id);
38*635a8641SAndroid Build Coastguard Worker    return this.router_.connector_.accept(message);
39*635a8641SAndroid Build Coastguard Worker  };
40*635a8641SAndroid Build Coastguard Worker
41*635a8641SAndroid Build Coastguard Worker  function Router(handle, setInterfaceIdNamespaceBit) {
42*635a8641SAndroid Build Coastguard Worker    if (!(handle instanceof MojoHandle)) {
43*635a8641SAndroid Build Coastguard Worker      throw new Error("Router constructor: Not a handle");
44*635a8641SAndroid Build Coastguard Worker    }
45*635a8641SAndroid Build Coastguard Worker    if (setInterfaceIdNamespaceBit === undefined) {
46*635a8641SAndroid Build Coastguard Worker      setInterfaceIdNamespaceBit = false;
47*635a8641SAndroid Build Coastguard Worker    }
48*635a8641SAndroid Build Coastguard Worker
49*635a8641SAndroid Build Coastguard Worker    this.connector_ = new internal.Connector(handle);
50*635a8641SAndroid Build Coastguard Worker
51*635a8641SAndroid Build Coastguard Worker    this.connector_.setIncomingReceiver({
52*635a8641SAndroid Build Coastguard Worker        accept: this.accept.bind(this),
53*635a8641SAndroid Build Coastguard Worker    });
54*635a8641SAndroid Build Coastguard Worker    this.connector_.setErrorHandler({
55*635a8641SAndroid Build Coastguard Worker        onError: this.onPipeConnectionError.bind(this),
56*635a8641SAndroid Build Coastguard Worker    });
57*635a8641SAndroid Build Coastguard Worker
58*635a8641SAndroid Build Coastguard Worker    this.setInterfaceIdNamespaceBit_ = setInterfaceIdNamespaceBit;
59*635a8641SAndroid Build Coastguard Worker    // |cachedMessageData| caches infomation about a message, so it can be
60*635a8641SAndroid Build Coastguard Worker    // processed later if a client is not yet attached to the target endpoint.
61*635a8641SAndroid Build Coastguard Worker    this.cachedMessageData = null;
62*635a8641SAndroid Build Coastguard Worker    this.controlMessageHandler_ = new internal.PipeControlMessageHandler(this);
63*635a8641SAndroid Build Coastguard Worker    this.controlMessageProxy_ =
64*635a8641SAndroid Build Coastguard Worker        new internal.PipeControlMessageProxy(this.connector_);
65*635a8641SAndroid Build Coastguard Worker    this.nextInterfaceIdValue_ = 1;
66*635a8641SAndroid Build Coastguard Worker    this.encounteredError_ = false;
67*635a8641SAndroid Build Coastguard Worker    this.endpoints_ = new Map();
68*635a8641SAndroid Build Coastguard Worker  }
69*635a8641SAndroid Build Coastguard Worker
70*635a8641SAndroid Build Coastguard Worker  Router.prototype.associateInterface = function(handleToSend) {
71*635a8641SAndroid Build Coastguard Worker    if (!handleToSend.pendingAssociation()) {
72*635a8641SAndroid Build Coastguard Worker      return internal.kInvalidInterfaceId;
73*635a8641SAndroid Build Coastguard Worker    }
74*635a8641SAndroid Build Coastguard Worker
75*635a8641SAndroid Build Coastguard Worker    var id = 0;
76*635a8641SAndroid Build Coastguard Worker    do {
77*635a8641SAndroid Build Coastguard Worker      if (this.nextInterfaceIdValue_ >= internal.kInterfaceIdNamespaceMask) {
78*635a8641SAndroid Build Coastguard Worker        this.nextInterfaceIdValue_ = 1;
79*635a8641SAndroid Build Coastguard Worker      }
80*635a8641SAndroid Build Coastguard Worker      id = this.nextInterfaceIdValue_++;
81*635a8641SAndroid Build Coastguard Worker      if (this.setInterfaceIdNamespaceBit_) {
82*635a8641SAndroid Build Coastguard Worker        id += internal.kInterfaceIdNamespaceMask;
83*635a8641SAndroid Build Coastguard Worker      }
84*635a8641SAndroid Build Coastguard Worker    } while (this.endpoints_.has(id));
85*635a8641SAndroid Build Coastguard Worker
86*635a8641SAndroid Build Coastguard Worker    var endpoint = new InterfaceEndpoint(this, id);
87*635a8641SAndroid Build Coastguard Worker    this.endpoints_.set(id, endpoint);
88*635a8641SAndroid Build Coastguard Worker    if (this.encounteredError_) {
89*635a8641SAndroid Build Coastguard Worker      this.updateEndpointStateMayRemove(endpoint,
90*635a8641SAndroid Build Coastguard Worker          EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
91*635a8641SAndroid Build Coastguard Worker    }
92*635a8641SAndroid Build Coastguard Worker    endpoint.handleCreated = true;
93*635a8641SAndroid Build Coastguard Worker
94*635a8641SAndroid Build Coastguard Worker    if (!handleToSend.notifyAssociation(id, this)) {
95*635a8641SAndroid Build Coastguard Worker      // The peer handle of |handleToSend|, which is supposed to join this
96*635a8641SAndroid Build Coastguard Worker      // associated group, has been closed.
97*635a8641SAndroid Build Coastguard Worker      this.updateEndpointStateMayRemove(endpoint,
98*635a8641SAndroid Build Coastguard Worker          EndpointStateUpdateType.ENDPOINT_CLOSED);
99*635a8641SAndroid Build Coastguard Worker
100*635a8641SAndroid Build Coastguard Worker      pipeControlMessageproxy.notifyPeerEndpointClosed(id,
101*635a8641SAndroid Build Coastguard Worker          handleToSend.disconnectReason());
102*635a8641SAndroid Build Coastguard Worker    }
103*635a8641SAndroid Build Coastguard Worker
104*635a8641SAndroid Build Coastguard Worker    return id;
105*635a8641SAndroid Build Coastguard Worker  };
106*635a8641SAndroid Build Coastguard Worker
107*635a8641SAndroid Build Coastguard Worker  Router.prototype.attachEndpointClient = function(
108*635a8641SAndroid Build Coastguard Worker      interfaceEndpointHandle, interfaceEndpointClient) {
109*635a8641SAndroid Build Coastguard Worker    check(internal.isValidInterfaceId(interfaceEndpointHandle.id()));
110*635a8641SAndroid Build Coastguard Worker    check(interfaceEndpointClient);
111*635a8641SAndroid Build Coastguard Worker
112*635a8641SAndroid Build Coastguard Worker    var endpoint = this.endpoints_.get(interfaceEndpointHandle.id());
113*635a8641SAndroid Build Coastguard Worker    check(endpoint);
114*635a8641SAndroid Build Coastguard Worker    check(!endpoint.client);
115*635a8641SAndroid Build Coastguard Worker    check(!endpoint.closed);
116*635a8641SAndroid Build Coastguard Worker    endpoint.client = interfaceEndpointClient;
117*635a8641SAndroid Build Coastguard Worker
118*635a8641SAndroid Build Coastguard Worker    if (endpoint.peerClosed) {
119*635a8641SAndroid Build Coastguard Worker      setTimeout(endpoint.client.notifyError.bind(endpoint.client), 0);
120*635a8641SAndroid Build Coastguard Worker    }
121*635a8641SAndroid Build Coastguard Worker
122*635a8641SAndroid Build Coastguard Worker    if (this.cachedMessageData && interfaceEndpointHandle.id() ===
123*635a8641SAndroid Build Coastguard Worker        this.cachedMessageData.message.getInterfaceId()) {
124*635a8641SAndroid Build Coastguard Worker      setTimeout((function() {
125*635a8641SAndroid Build Coastguard Worker        if (!this.cachedMessageData) {
126*635a8641SAndroid Build Coastguard Worker          return;
127*635a8641SAndroid Build Coastguard Worker        }
128*635a8641SAndroid Build Coastguard Worker
129*635a8641SAndroid Build Coastguard Worker        var targetEndpoint = this.endpoints_.get(
130*635a8641SAndroid Build Coastguard Worker            this.cachedMessageData.message.getInterfaceId());
131*635a8641SAndroid Build Coastguard Worker        // Check that the target endpoint's client still exists.
132*635a8641SAndroid Build Coastguard Worker        if (targetEndpoint && targetEndpoint.client) {
133*635a8641SAndroid Build Coastguard Worker          var message = this.cachedMessageData.message;
134*635a8641SAndroid Build Coastguard Worker          var messageValidator = this.cachedMessageData.messageValidator;
135*635a8641SAndroid Build Coastguard Worker          this.cachedMessageData = null;
136*635a8641SAndroid Build Coastguard Worker          this.connector_.resumeIncomingMethodCallProcessing();
137*635a8641SAndroid Build Coastguard Worker          var ok = endpoint.client.handleIncomingMessage(message,
138*635a8641SAndroid Build Coastguard Worker              messageValidator);
139*635a8641SAndroid Build Coastguard Worker
140*635a8641SAndroid Build Coastguard Worker          // Handle invalid cached incoming message.
141*635a8641SAndroid Build Coastguard Worker          if (!internal.isTestingMode() && !ok) {
142*635a8641SAndroid Build Coastguard Worker            this.connector_.handleError(true, true);
143*635a8641SAndroid Build Coastguard Worker          }
144*635a8641SAndroid Build Coastguard Worker        }
145*635a8641SAndroid Build Coastguard Worker      }).bind(this), 0);
146*635a8641SAndroid Build Coastguard Worker    }
147*635a8641SAndroid Build Coastguard Worker
148*635a8641SAndroid Build Coastguard Worker    return endpoint;
149*635a8641SAndroid Build Coastguard Worker  };
150*635a8641SAndroid Build Coastguard Worker
151*635a8641SAndroid Build Coastguard Worker  Router.prototype.detachEndpointClient = function(
152*635a8641SAndroid Build Coastguard Worker      interfaceEndpointHandle) {
153*635a8641SAndroid Build Coastguard Worker    check(internal.isValidInterfaceId(interfaceEndpointHandle.id()));
154*635a8641SAndroid Build Coastguard Worker    var endpoint = this.endpoints_.get(interfaceEndpointHandle.id());
155*635a8641SAndroid Build Coastguard Worker    check(endpoint);
156*635a8641SAndroid Build Coastguard Worker    check(endpoint.client);
157*635a8641SAndroid Build Coastguard Worker    check(!endpoint.closed);
158*635a8641SAndroid Build Coastguard Worker
159*635a8641SAndroid Build Coastguard Worker    endpoint.client = null;
160*635a8641SAndroid Build Coastguard Worker  };
161*635a8641SAndroid Build Coastguard Worker
162*635a8641SAndroid Build Coastguard Worker  Router.prototype.createLocalEndpointHandle = function(
163*635a8641SAndroid Build Coastguard Worker      interfaceId) {
164*635a8641SAndroid Build Coastguard Worker    if (!internal.isValidInterfaceId(interfaceId)) {
165*635a8641SAndroid Build Coastguard Worker      return new internal.InterfaceEndpointHandle();
166*635a8641SAndroid Build Coastguard Worker    }
167*635a8641SAndroid Build Coastguard Worker
168*635a8641SAndroid Build Coastguard Worker    // Unless it is the master ID, |interfaceId| is from the remote side and
169*635a8641SAndroid Build Coastguard Worker    // therefore its namespace bit is supposed to be different than the value
170*635a8641SAndroid Build Coastguard Worker    // that this router would use.
171*635a8641SAndroid Build Coastguard Worker    if (!internal.isMasterInterfaceId(interfaceId) &&
172*635a8641SAndroid Build Coastguard Worker        this.setInterfaceIdNamespaceBit_ ===
173*635a8641SAndroid Build Coastguard Worker            internal.hasInterfaceIdNamespaceBitSet(interfaceId)) {
174*635a8641SAndroid Build Coastguard Worker      return new internal.InterfaceEndpointHandle();
175*635a8641SAndroid Build Coastguard Worker    }
176*635a8641SAndroid Build Coastguard Worker
177*635a8641SAndroid Build Coastguard Worker    var endpoint = this.endpoints_.get(interfaceId);
178*635a8641SAndroid Build Coastguard Worker
179*635a8641SAndroid Build Coastguard Worker    if (!endpoint) {
180*635a8641SAndroid Build Coastguard Worker      endpoint = new InterfaceEndpoint(this, interfaceId);
181*635a8641SAndroid Build Coastguard Worker      this.endpoints_.set(interfaceId, endpoint);
182*635a8641SAndroid Build Coastguard Worker
183*635a8641SAndroid Build Coastguard Worker      check(!endpoint.handleCreated);
184*635a8641SAndroid Build Coastguard Worker
185*635a8641SAndroid Build Coastguard Worker      if (this.encounteredError_) {
186*635a8641SAndroid Build Coastguard Worker        this.updateEndpointStateMayRemove(endpoint,
187*635a8641SAndroid Build Coastguard Worker            EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
188*635a8641SAndroid Build Coastguard Worker      }
189*635a8641SAndroid Build Coastguard Worker    } else {
190*635a8641SAndroid Build Coastguard Worker      // If the endpoint already exist, it is because we have received a
191*635a8641SAndroid Build Coastguard Worker      // notification that the peer endpoint has closed.
192*635a8641SAndroid Build Coastguard Worker      check(!endpoint.closed);
193*635a8641SAndroid Build Coastguard Worker      check(endpoint.peerClosed);
194*635a8641SAndroid Build Coastguard Worker
195*635a8641SAndroid Build Coastguard Worker      if (endpoint.handleCreated) {
196*635a8641SAndroid Build Coastguard Worker        return new internal.InterfaceEndpointHandle();
197*635a8641SAndroid Build Coastguard Worker      }
198*635a8641SAndroid Build Coastguard Worker    }
199*635a8641SAndroid Build Coastguard Worker
200*635a8641SAndroid Build Coastguard Worker    endpoint.handleCreated = true;
201*635a8641SAndroid Build Coastguard Worker    return new internal.InterfaceEndpointHandle(interfaceId, this);
202*635a8641SAndroid Build Coastguard Worker  };
203*635a8641SAndroid Build Coastguard Worker
204*635a8641SAndroid Build Coastguard Worker  Router.prototype.accept = function(message) {
205*635a8641SAndroid Build Coastguard Worker    var messageValidator = new internal.Validator(message);
206*635a8641SAndroid Build Coastguard Worker    var err = messageValidator.validateMessageHeader();
207*635a8641SAndroid Build Coastguard Worker
208*635a8641SAndroid Build Coastguard Worker    var ok = false;
209*635a8641SAndroid Build Coastguard Worker    if (err !== internal.validationError.NONE) {
210*635a8641SAndroid Build Coastguard Worker      internal.reportValidationError(err);
211*635a8641SAndroid Build Coastguard Worker    } else if (message.deserializeAssociatedEndpointHandles(this)) {
212*635a8641SAndroid Build Coastguard Worker      if (internal.isPipeControlMessage(message)) {
213*635a8641SAndroid Build Coastguard Worker        ok = this.controlMessageHandler_.accept(message);
214*635a8641SAndroid Build Coastguard Worker      } else {
215*635a8641SAndroid Build Coastguard Worker        var interfaceId = message.getInterfaceId();
216*635a8641SAndroid Build Coastguard Worker        var endpoint = this.endpoints_.get(interfaceId);
217*635a8641SAndroid Build Coastguard Worker        if (!endpoint || endpoint.closed) {
218*635a8641SAndroid Build Coastguard Worker          return true;
219*635a8641SAndroid Build Coastguard Worker        }
220*635a8641SAndroid Build Coastguard Worker
221*635a8641SAndroid Build Coastguard Worker        if (!endpoint.client) {
222*635a8641SAndroid Build Coastguard Worker          // We need to wait until a client is attached in order to dispatch
223*635a8641SAndroid Build Coastguard Worker          // further messages.
224*635a8641SAndroid Build Coastguard Worker          this.cachedMessageData = {message: message,
225*635a8641SAndroid Build Coastguard Worker              messageValidator: messageValidator};
226*635a8641SAndroid Build Coastguard Worker          this.connector_.pauseIncomingMethodCallProcessing();
227*635a8641SAndroid Build Coastguard Worker          return true;
228*635a8641SAndroid Build Coastguard Worker        }
229*635a8641SAndroid Build Coastguard Worker        ok = endpoint.client.handleIncomingMessage(message, messageValidator);
230*635a8641SAndroid Build Coastguard Worker      }
231*635a8641SAndroid Build Coastguard Worker    }
232*635a8641SAndroid Build Coastguard Worker    return ok;
233*635a8641SAndroid Build Coastguard Worker  };
234*635a8641SAndroid Build Coastguard Worker
235*635a8641SAndroid Build Coastguard Worker  Router.prototype.close = function() {
236*635a8641SAndroid Build Coastguard Worker    this.connector_.close();
237*635a8641SAndroid Build Coastguard Worker    // Closing the message pipe won't trigger connection error handler.
238*635a8641SAndroid Build Coastguard Worker    // Explicitly call onPipeConnectionError() so that associated endpoints
239*635a8641SAndroid Build Coastguard Worker    // will get notified.
240*635a8641SAndroid Build Coastguard Worker    this.onPipeConnectionError();
241*635a8641SAndroid Build Coastguard Worker  };
242*635a8641SAndroid Build Coastguard Worker
243*635a8641SAndroid Build Coastguard Worker  Router.prototype.onPeerAssociatedEndpointClosed = function(interfaceId,
244*635a8641SAndroid Build Coastguard Worker      reason) {
245*635a8641SAndroid Build Coastguard Worker    var endpoint = this.endpoints_.get(interfaceId);
246*635a8641SAndroid Build Coastguard Worker    if (!endpoint) {
247*635a8641SAndroid Build Coastguard Worker      endpoint = new InterfaceEndpoint(this, interfaceId);
248*635a8641SAndroid Build Coastguard Worker      this.endpoints_.set(interfaceId, endpoint);
249*635a8641SAndroid Build Coastguard Worker    }
250*635a8641SAndroid Build Coastguard Worker
251*635a8641SAndroid Build Coastguard Worker    if (reason) {
252*635a8641SAndroid Build Coastguard Worker      endpoint.disconnectReason = reason;
253*635a8641SAndroid Build Coastguard Worker    }
254*635a8641SAndroid Build Coastguard Worker
255*635a8641SAndroid Build Coastguard Worker    if (!endpoint.peerClosed) {
256*635a8641SAndroid Build Coastguard Worker      if (endpoint.client) {
257*635a8641SAndroid Build Coastguard Worker        setTimeout(endpoint.client.notifyError.bind(endpoint.client, reason),
258*635a8641SAndroid Build Coastguard Worker                   0);
259*635a8641SAndroid Build Coastguard Worker      }
260*635a8641SAndroid Build Coastguard Worker      this.updateEndpointStateMayRemove(endpoint,
261*635a8641SAndroid Build Coastguard Worker          EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
262*635a8641SAndroid Build Coastguard Worker    }
263*635a8641SAndroid Build Coastguard Worker    return true;
264*635a8641SAndroid Build Coastguard Worker  };
265*635a8641SAndroid Build Coastguard Worker
266*635a8641SAndroid Build Coastguard Worker  Router.prototype.onPipeConnectionError = function() {
267*635a8641SAndroid Build Coastguard Worker    this.encounteredError_ = true;
268*635a8641SAndroid Build Coastguard Worker
269*635a8641SAndroid Build Coastguard Worker    for (var endpoint of this.endpoints_.values()) {
270*635a8641SAndroid Build Coastguard Worker      if (endpoint.client) {
271*635a8641SAndroid Build Coastguard Worker        setTimeout(
272*635a8641SAndroid Build Coastguard Worker            endpoint.client.notifyError.bind(
273*635a8641SAndroid Build Coastguard Worker                endpoint.client, endpoint.disconnectReason),
274*635a8641SAndroid Build Coastguard Worker            0);
275*635a8641SAndroid Build Coastguard Worker      }
276*635a8641SAndroid Build Coastguard Worker      this.updateEndpointStateMayRemove(endpoint,
277*635a8641SAndroid Build Coastguard Worker          EndpointStateUpdateType.PEER_ENDPOINT_CLOSED);
278*635a8641SAndroid Build Coastguard Worker    }
279*635a8641SAndroid Build Coastguard Worker  };
280*635a8641SAndroid Build Coastguard Worker
281*635a8641SAndroid Build Coastguard Worker  Router.prototype.closeEndpointHandle = function(interfaceId, reason) {
282*635a8641SAndroid Build Coastguard Worker    if (!internal.isValidInterfaceId(interfaceId)) {
283*635a8641SAndroid Build Coastguard Worker      return;
284*635a8641SAndroid Build Coastguard Worker    }
285*635a8641SAndroid Build Coastguard Worker    var endpoint = this.endpoints_.get(interfaceId);
286*635a8641SAndroid Build Coastguard Worker    check(endpoint);
287*635a8641SAndroid Build Coastguard Worker    check(!endpoint.client);
288*635a8641SAndroid Build Coastguard Worker    check(!endpoint.closed);
289*635a8641SAndroid Build Coastguard Worker
290*635a8641SAndroid Build Coastguard Worker    this.updateEndpointStateMayRemove(endpoint,
291*635a8641SAndroid Build Coastguard Worker        EndpointStateUpdateType.ENDPOINT_CLOSED);
292*635a8641SAndroid Build Coastguard Worker
293*635a8641SAndroid Build Coastguard Worker    if (!internal.isMasterInterfaceId(interfaceId) || reason) {
294*635a8641SAndroid Build Coastguard Worker      this.controlMessageProxy_.notifyPeerEndpointClosed(interfaceId, reason);
295*635a8641SAndroid Build Coastguard Worker    }
296*635a8641SAndroid Build Coastguard Worker
297*635a8641SAndroid Build Coastguard Worker    if (this.cachedMessageData && interfaceId ===
298*635a8641SAndroid Build Coastguard Worker        this.cachedMessageData.message.getInterfaceId()) {
299*635a8641SAndroid Build Coastguard Worker      this.cachedMessageData = null;
300*635a8641SAndroid Build Coastguard Worker      this.connector_.resumeIncomingMethodCallProcessing();
301*635a8641SAndroid Build Coastguard Worker    }
302*635a8641SAndroid Build Coastguard Worker  };
303*635a8641SAndroid Build Coastguard Worker
304*635a8641SAndroid Build Coastguard Worker  Router.prototype.updateEndpointStateMayRemove = function(endpoint,
305*635a8641SAndroid Build Coastguard Worker      endpointStateUpdateType) {
306*635a8641SAndroid Build Coastguard Worker    if (endpointStateUpdateType === EndpointStateUpdateType.ENDPOINT_CLOSED) {
307*635a8641SAndroid Build Coastguard Worker      endpoint.closed = true;
308*635a8641SAndroid Build Coastguard Worker    } else {
309*635a8641SAndroid Build Coastguard Worker      endpoint.peerClosed = true;
310*635a8641SAndroid Build Coastguard Worker    }
311*635a8641SAndroid Build Coastguard Worker    if (endpoint.closed && endpoint.peerClosed) {
312*635a8641SAndroid Build Coastguard Worker      this.endpoints_.delete(endpoint.id);
313*635a8641SAndroid Build Coastguard Worker    }
314*635a8641SAndroid Build Coastguard Worker  };
315*635a8641SAndroid Build Coastguard Worker
316*635a8641SAndroid Build Coastguard Worker  internal.Router = Router;
317*635a8641SAndroid Build Coastguard Worker})();
318