xref: /aosp_15_r20/external/libchrome/mojo/public/js/bindings.js (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker// Copyright 2017 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
10*635a8641SAndroid Build Coastguard Worker  // |output| could be an interface pointer, InterfacePtrInfo or
11*635a8641SAndroid Build Coastguard Worker  // AssociatedInterfacePtrInfo.
12*635a8641SAndroid Build Coastguard Worker  function makeRequest(output) {
13*635a8641SAndroid Build Coastguard Worker    if (output instanceof mojo.AssociatedInterfacePtrInfo) {
14*635a8641SAndroid Build Coastguard Worker      var {handle0, handle1} = internal.createPairPendingAssociation();
15*635a8641SAndroid Build Coastguard Worker      output.interfaceEndpointHandle = handle0;
16*635a8641SAndroid Build Coastguard Worker      output.version = 0;
17*635a8641SAndroid Build Coastguard Worker
18*635a8641SAndroid Build Coastguard Worker      return new mojo.AssociatedInterfaceRequest(handle1);
19*635a8641SAndroid Build Coastguard Worker    }
20*635a8641SAndroid Build Coastguard Worker
21*635a8641SAndroid Build Coastguard Worker    if (output instanceof mojo.InterfacePtrInfo) {
22*635a8641SAndroid Build Coastguard Worker      var pipe = Mojo.createMessagePipe();
23*635a8641SAndroid Build Coastguard Worker      output.handle = pipe.handle0;
24*635a8641SAndroid Build Coastguard Worker      output.version = 0;
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker      return new mojo.InterfaceRequest(pipe.handle1);
27*635a8641SAndroid Build Coastguard Worker    }
28*635a8641SAndroid Build Coastguard Worker
29*635a8641SAndroid Build Coastguard Worker    var pipe = Mojo.createMessagePipe();
30*635a8641SAndroid Build Coastguard Worker    output.ptr.bind(new mojo.InterfacePtrInfo(pipe.handle0, 0));
31*635a8641SAndroid Build Coastguard Worker    return new mojo.InterfaceRequest(pipe.handle1);
32*635a8641SAndroid Build Coastguard Worker  }
33*635a8641SAndroid Build Coastguard Worker
34*635a8641SAndroid Build Coastguard Worker  // ---------------------------------------------------------------------------
35*635a8641SAndroid Build Coastguard Worker
36*635a8641SAndroid Build Coastguard Worker  // Operations used to setup/configure an interface pointer. Exposed as the
37*635a8641SAndroid Build Coastguard Worker  // |ptr| field of generated interface pointer classes.
38*635a8641SAndroid Build Coastguard Worker  // |ptrInfoOrHandle| could be omitted and passed into bind() later.
39*635a8641SAndroid Build Coastguard Worker  function InterfacePtrController(interfaceType, ptrInfoOrHandle) {
40*635a8641SAndroid Build Coastguard Worker    this.version = 0;
41*635a8641SAndroid Build Coastguard Worker
42*635a8641SAndroid Build Coastguard Worker    this.interfaceType_ = interfaceType;
43*635a8641SAndroid Build Coastguard Worker    this.router_ = null;
44*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = null;
45*635a8641SAndroid Build Coastguard Worker    this.proxy_ = null;
46*635a8641SAndroid Build Coastguard Worker
47*635a8641SAndroid Build Coastguard Worker    // |router_| and |interfaceEndpointClient_| are lazily initialized.
48*635a8641SAndroid Build Coastguard Worker    // |handle_| is valid between bind() and
49*635a8641SAndroid Build Coastguard Worker    // the initialization of |router_| and |interfaceEndpointClient_|.
50*635a8641SAndroid Build Coastguard Worker    this.handle_ = null;
51*635a8641SAndroid Build Coastguard Worker
52*635a8641SAndroid Build Coastguard Worker    if (ptrInfoOrHandle)
53*635a8641SAndroid Build Coastguard Worker      this.bind(ptrInfoOrHandle);
54*635a8641SAndroid Build Coastguard Worker  }
55*635a8641SAndroid Build Coastguard Worker
56*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.bind = function(ptrInfoOrHandle) {
57*635a8641SAndroid Build Coastguard Worker    this.reset();
58*635a8641SAndroid Build Coastguard Worker
59*635a8641SAndroid Build Coastguard Worker    if (ptrInfoOrHandle instanceof mojo.InterfacePtrInfo) {
60*635a8641SAndroid Build Coastguard Worker      this.version = ptrInfoOrHandle.version;
61*635a8641SAndroid Build Coastguard Worker      this.handle_ = ptrInfoOrHandle.handle;
62*635a8641SAndroid Build Coastguard Worker    } else {
63*635a8641SAndroid Build Coastguard Worker      this.handle_ = ptrInfoOrHandle;
64*635a8641SAndroid Build Coastguard Worker    }
65*635a8641SAndroid Build Coastguard Worker  };
66*635a8641SAndroid Build Coastguard Worker
67*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.isBound = function() {
68*635a8641SAndroid Build Coastguard Worker    return this.interfaceEndpointClient_ !== null || this.handle_ !== null;
69*635a8641SAndroid Build Coastguard Worker  };
70*635a8641SAndroid Build Coastguard Worker
71*635a8641SAndroid Build Coastguard Worker  // Although users could just discard the object, reset() closes the pipe
72*635a8641SAndroid Build Coastguard Worker  // immediately.
73*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.reset = function() {
74*635a8641SAndroid Build Coastguard Worker    this.version = 0;
75*635a8641SAndroid Build Coastguard Worker    if (this.interfaceEndpointClient_) {
76*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close();
77*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
78*635a8641SAndroid Build Coastguard Worker    }
79*635a8641SAndroid Build Coastguard Worker    if (this.router_) {
80*635a8641SAndroid Build Coastguard Worker      this.router_.close();
81*635a8641SAndroid Build Coastguard Worker      this.router_ = null;
82*635a8641SAndroid Build Coastguard Worker
83*635a8641SAndroid Build Coastguard Worker      this.proxy_ = null;
84*635a8641SAndroid Build Coastguard Worker    }
85*635a8641SAndroid Build Coastguard Worker    if (this.handle_) {
86*635a8641SAndroid Build Coastguard Worker      this.handle_.close();
87*635a8641SAndroid Build Coastguard Worker      this.handle_ = null;
88*635a8641SAndroid Build Coastguard Worker    }
89*635a8641SAndroid Build Coastguard Worker  };
90*635a8641SAndroid Build Coastguard Worker
91*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.resetWithReason = function(reason) {
92*635a8641SAndroid Build Coastguard Worker    if (this.isBound()) {
93*635a8641SAndroid Build Coastguard Worker      this.configureProxyIfNecessary_();
94*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close(reason);
95*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
96*635a8641SAndroid Build Coastguard Worker    }
97*635a8641SAndroid Build Coastguard Worker    this.reset();
98*635a8641SAndroid Build Coastguard Worker  };
99*635a8641SAndroid Build Coastguard Worker
100*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.setConnectionErrorHandler = function(
101*635a8641SAndroid Build Coastguard Worker      callback) {
102*635a8641SAndroid Build Coastguard Worker    if (!this.isBound())
103*635a8641SAndroid Build Coastguard Worker      throw new Error("Cannot set connection error handler if not bound.");
104*635a8641SAndroid Build Coastguard Worker
105*635a8641SAndroid Build Coastguard Worker    this.configureProxyIfNecessary_();
106*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_.setConnectionErrorHandler(callback);
107*635a8641SAndroid Build Coastguard Worker  };
108*635a8641SAndroid Build Coastguard Worker
109*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.passInterface = function() {
110*635a8641SAndroid Build Coastguard Worker    var result;
111*635a8641SAndroid Build Coastguard Worker    if (this.router_) {
112*635a8641SAndroid Build Coastguard Worker      // TODO(yzshen): Fix Router interface to support extracting handle.
113*635a8641SAndroid Build Coastguard Worker      result = new mojo.InterfacePtrInfo(
114*635a8641SAndroid Build Coastguard Worker          this.router_.connector_.handle_, this.version);
115*635a8641SAndroid Build Coastguard Worker      this.router_.connector_.handle_ = null;
116*635a8641SAndroid Build Coastguard Worker    } else {
117*635a8641SAndroid Build Coastguard Worker      // This also handles the case when this object is not bound.
118*635a8641SAndroid Build Coastguard Worker      result = new mojo.InterfacePtrInfo(this.handle_, this.version);
119*635a8641SAndroid Build Coastguard Worker      this.handle_ = null;
120*635a8641SAndroid Build Coastguard Worker    }
121*635a8641SAndroid Build Coastguard Worker
122*635a8641SAndroid Build Coastguard Worker    this.reset();
123*635a8641SAndroid Build Coastguard Worker    return result;
124*635a8641SAndroid Build Coastguard Worker  };
125*635a8641SAndroid Build Coastguard Worker
126*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.getProxy = function() {
127*635a8641SAndroid Build Coastguard Worker    this.configureProxyIfNecessary_();
128*635a8641SAndroid Build Coastguard Worker    return this.proxy_;
129*635a8641SAndroid Build Coastguard Worker  };
130*635a8641SAndroid Build Coastguard Worker
131*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.configureProxyIfNecessary_ = function() {
132*635a8641SAndroid Build Coastguard Worker    if (!this.handle_)
133*635a8641SAndroid Build Coastguard Worker      return;
134*635a8641SAndroid Build Coastguard Worker
135*635a8641SAndroid Build Coastguard Worker    this.router_ = new internal.Router(this.handle_, true);
136*635a8641SAndroid Build Coastguard Worker    this.handle_ = null;
137*635a8641SAndroid Build Coastguard Worker
138*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = new internal.InterfaceEndpointClient(
139*635a8641SAndroid Build Coastguard Worker        this.router_.createLocalEndpointHandle(internal.kMasterInterfaceId));
140*635a8641SAndroid Build Coastguard Worker
141*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ .setPayloadValidators([
142*635a8641SAndroid Build Coastguard Worker        this.interfaceType_.validateResponse]);
143*635a8641SAndroid Build Coastguard Worker    this.proxy_ = new this.interfaceType_.proxyClass(
144*635a8641SAndroid Build Coastguard Worker        this.interfaceEndpointClient_);
145*635a8641SAndroid Build Coastguard Worker  };
146*635a8641SAndroid Build Coastguard Worker
147*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.queryVersion = function() {
148*635a8641SAndroid Build Coastguard Worker    function onQueryVersion(version) {
149*635a8641SAndroid Build Coastguard Worker      this.version = version;
150*635a8641SAndroid Build Coastguard Worker      return version;
151*635a8641SAndroid Build Coastguard Worker    }
152*635a8641SAndroid Build Coastguard Worker
153*635a8641SAndroid Build Coastguard Worker    this.configureProxyIfNecessary_();
154*635a8641SAndroid Build Coastguard Worker    return this.interfaceEndpointClient_.queryVersion().then(
155*635a8641SAndroid Build Coastguard Worker      onQueryVersion.bind(this));
156*635a8641SAndroid Build Coastguard Worker  };
157*635a8641SAndroid Build Coastguard Worker
158*635a8641SAndroid Build Coastguard Worker  InterfacePtrController.prototype.requireVersion = function(version) {
159*635a8641SAndroid Build Coastguard Worker    this.configureProxyIfNecessary_();
160*635a8641SAndroid Build Coastguard Worker
161*635a8641SAndroid Build Coastguard Worker    if (this.version >= version) {
162*635a8641SAndroid Build Coastguard Worker      return;
163*635a8641SAndroid Build Coastguard Worker    }
164*635a8641SAndroid Build Coastguard Worker    this.version = version;
165*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_.requireVersion(version);
166*635a8641SAndroid Build Coastguard Worker  };
167*635a8641SAndroid Build Coastguard Worker
168*635a8641SAndroid Build Coastguard Worker  // ---------------------------------------------------------------------------
169*635a8641SAndroid Build Coastguard Worker
170*635a8641SAndroid Build Coastguard Worker  // |request| could be omitted and passed into bind() later.
171*635a8641SAndroid Build Coastguard Worker  //
172*635a8641SAndroid Build Coastguard Worker  // Example:
173*635a8641SAndroid Build Coastguard Worker  //
174*635a8641SAndroid Build Coastguard Worker  //    // FooImpl implements mojom.Foo.
175*635a8641SAndroid Build Coastguard Worker  //    function FooImpl() { ... }
176*635a8641SAndroid Build Coastguard Worker  //    FooImpl.prototype.fooMethod1 = function() { ... }
177*635a8641SAndroid Build Coastguard Worker  //    FooImpl.prototype.fooMethod2 = function() { ... }
178*635a8641SAndroid Build Coastguard Worker  //
179*635a8641SAndroid Build Coastguard Worker  //    var fooPtr = new mojom.FooPtr();
180*635a8641SAndroid Build Coastguard Worker  //    var request = makeRequest(fooPtr);
181*635a8641SAndroid Build Coastguard Worker  //    var binding = new Binding(mojom.Foo, new FooImpl(), request);
182*635a8641SAndroid Build Coastguard Worker  //    fooPtr.fooMethod1();
183*635a8641SAndroid Build Coastguard Worker  function Binding(interfaceType, impl, requestOrHandle) {
184*635a8641SAndroid Build Coastguard Worker    this.interfaceType_ = interfaceType;
185*635a8641SAndroid Build Coastguard Worker    this.impl_ = impl;
186*635a8641SAndroid Build Coastguard Worker    this.router_ = null;
187*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = null;
188*635a8641SAndroid Build Coastguard Worker    this.stub_ = null;
189*635a8641SAndroid Build Coastguard Worker
190*635a8641SAndroid Build Coastguard Worker    if (requestOrHandle)
191*635a8641SAndroid Build Coastguard Worker      this.bind(requestOrHandle);
192*635a8641SAndroid Build Coastguard Worker  }
193*635a8641SAndroid Build Coastguard Worker
194*635a8641SAndroid Build Coastguard Worker  Binding.prototype.isBound = function() {
195*635a8641SAndroid Build Coastguard Worker    return this.router_ !== null;
196*635a8641SAndroid Build Coastguard Worker  };
197*635a8641SAndroid Build Coastguard Worker
198*635a8641SAndroid Build Coastguard Worker  Binding.prototype.createInterfacePtrAndBind = function() {
199*635a8641SAndroid Build Coastguard Worker    var ptr = new this.interfaceType_.ptrClass();
200*635a8641SAndroid Build Coastguard Worker    // TODO(yzshen): Set the version of the interface pointer.
201*635a8641SAndroid Build Coastguard Worker    this.bind(makeRequest(ptr));
202*635a8641SAndroid Build Coastguard Worker    return ptr;
203*635a8641SAndroid Build Coastguard Worker  };
204*635a8641SAndroid Build Coastguard Worker
205*635a8641SAndroid Build Coastguard Worker  Binding.prototype.bind = function(requestOrHandle) {
206*635a8641SAndroid Build Coastguard Worker    this.close();
207*635a8641SAndroid Build Coastguard Worker
208*635a8641SAndroid Build Coastguard Worker    var handle = requestOrHandle instanceof mojo.InterfaceRequest ?
209*635a8641SAndroid Build Coastguard Worker        requestOrHandle.handle : requestOrHandle;
210*635a8641SAndroid Build Coastguard Worker    if (!(handle instanceof MojoHandle))
211*635a8641SAndroid Build Coastguard Worker      return;
212*635a8641SAndroid Build Coastguard Worker
213*635a8641SAndroid Build Coastguard Worker    this.router_ = new internal.Router(handle);
214*635a8641SAndroid Build Coastguard Worker
215*635a8641SAndroid Build Coastguard Worker    this.stub_ = new this.interfaceType_.stubClass(this.impl_);
216*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = new internal.InterfaceEndpointClient(
217*635a8641SAndroid Build Coastguard Worker        this.router_.createLocalEndpointHandle(internal.kMasterInterfaceId),
218*635a8641SAndroid Build Coastguard Worker        this.stub_, this.interfaceType_.kVersion);
219*635a8641SAndroid Build Coastguard Worker
220*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ .setPayloadValidators([
221*635a8641SAndroid Build Coastguard Worker        this.interfaceType_.validateRequest]);
222*635a8641SAndroid Build Coastguard Worker  };
223*635a8641SAndroid Build Coastguard Worker
224*635a8641SAndroid Build Coastguard Worker  Binding.prototype.close = function() {
225*635a8641SAndroid Build Coastguard Worker    if (!this.isBound())
226*635a8641SAndroid Build Coastguard Worker      return;
227*635a8641SAndroid Build Coastguard Worker
228*635a8641SAndroid Build Coastguard Worker    if (this.interfaceEndpointClient_) {
229*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close();
230*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
231*635a8641SAndroid Build Coastguard Worker    }
232*635a8641SAndroid Build Coastguard Worker
233*635a8641SAndroid Build Coastguard Worker    this.router_.close();
234*635a8641SAndroid Build Coastguard Worker    this.router_ = null;
235*635a8641SAndroid Build Coastguard Worker    this.stub_ = null;
236*635a8641SAndroid Build Coastguard Worker  };
237*635a8641SAndroid Build Coastguard Worker
238*635a8641SAndroid Build Coastguard Worker  Binding.prototype.closeWithReason = function(reason) {
239*635a8641SAndroid Build Coastguard Worker    if (this.interfaceEndpointClient_) {
240*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close(reason);
241*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
242*635a8641SAndroid Build Coastguard Worker    }
243*635a8641SAndroid Build Coastguard Worker    this.close();
244*635a8641SAndroid Build Coastguard Worker  };
245*635a8641SAndroid Build Coastguard Worker
246*635a8641SAndroid Build Coastguard Worker  Binding.prototype.setConnectionErrorHandler = function(callback) {
247*635a8641SAndroid Build Coastguard Worker    if (!this.isBound()) {
248*635a8641SAndroid Build Coastguard Worker      throw new Error("Cannot set connection error handler if not bound.");
249*635a8641SAndroid Build Coastguard Worker    }
250*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_.setConnectionErrorHandler(callback);
251*635a8641SAndroid Build Coastguard Worker  };
252*635a8641SAndroid Build Coastguard Worker
253*635a8641SAndroid Build Coastguard Worker  Binding.prototype.unbind = function() {
254*635a8641SAndroid Build Coastguard Worker    if (!this.isBound())
255*635a8641SAndroid Build Coastguard Worker      return new mojo.InterfaceRequest(null);
256*635a8641SAndroid Build Coastguard Worker
257*635a8641SAndroid Build Coastguard Worker    var result = new mojo.InterfaceRequest(this.router_.connector_.handle_);
258*635a8641SAndroid Build Coastguard Worker    this.router_.connector_.handle_ = null;
259*635a8641SAndroid Build Coastguard Worker    this.close();
260*635a8641SAndroid Build Coastguard Worker    return result;
261*635a8641SAndroid Build Coastguard Worker  };
262*635a8641SAndroid Build Coastguard Worker
263*635a8641SAndroid Build Coastguard Worker  // ---------------------------------------------------------------------------
264*635a8641SAndroid Build Coastguard Worker
265*635a8641SAndroid Build Coastguard Worker  function BindingSetEntry(bindingSet, interfaceType, bindingType, impl,
266*635a8641SAndroid Build Coastguard Worker      requestOrHandle, bindingId) {
267*635a8641SAndroid Build Coastguard Worker    this.bindingSet_ = bindingSet;
268*635a8641SAndroid Build Coastguard Worker    this.bindingId_ = bindingId;
269*635a8641SAndroid Build Coastguard Worker    this.binding_ = new bindingType(interfaceType, impl,
270*635a8641SAndroid Build Coastguard Worker        requestOrHandle);
271*635a8641SAndroid Build Coastguard Worker
272*635a8641SAndroid Build Coastguard Worker    this.binding_.setConnectionErrorHandler(function(reason) {
273*635a8641SAndroid Build Coastguard Worker      this.bindingSet_.onConnectionError(bindingId, reason);
274*635a8641SAndroid Build Coastguard Worker    }.bind(this));
275*635a8641SAndroid Build Coastguard Worker  }
276*635a8641SAndroid Build Coastguard Worker
277*635a8641SAndroid Build Coastguard Worker  BindingSetEntry.prototype.close = function() {
278*635a8641SAndroid Build Coastguard Worker    this.binding_.close();
279*635a8641SAndroid Build Coastguard Worker  };
280*635a8641SAndroid Build Coastguard Worker
281*635a8641SAndroid Build Coastguard Worker  function BindingSet(interfaceType) {
282*635a8641SAndroid Build Coastguard Worker    this.interfaceType_ = interfaceType;
283*635a8641SAndroid Build Coastguard Worker    this.nextBindingId_ = 0;
284*635a8641SAndroid Build Coastguard Worker    this.bindings_ = new Map();
285*635a8641SAndroid Build Coastguard Worker    this.errorHandler_ = null;
286*635a8641SAndroid Build Coastguard Worker    this.bindingType_ = Binding;
287*635a8641SAndroid Build Coastguard Worker  }
288*635a8641SAndroid Build Coastguard Worker
289*635a8641SAndroid Build Coastguard Worker  BindingSet.prototype.isEmpty = function() {
290*635a8641SAndroid Build Coastguard Worker    return this.bindings_.size == 0;
291*635a8641SAndroid Build Coastguard Worker  };
292*635a8641SAndroid Build Coastguard Worker
293*635a8641SAndroid Build Coastguard Worker  BindingSet.prototype.addBinding = function(impl, requestOrHandle) {
294*635a8641SAndroid Build Coastguard Worker    this.bindings_.set(
295*635a8641SAndroid Build Coastguard Worker        this.nextBindingId_,
296*635a8641SAndroid Build Coastguard Worker        new BindingSetEntry(this, this.interfaceType_, this.bindingType_, impl,
297*635a8641SAndroid Build Coastguard Worker            requestOrHandle, this.nextBindingId_));
298*635a8641SAndroid Build Coastguard Worker    ++this.nextBindingId_;
299*635a8641SAndroid Build Coastguard Worker  };
300*635a8641SAndroid Build Coastguard Worker
301*635a8641SAndroid Build Coastguard Worker  BindingSet.prototype.closeAllBindings = function() {
302*635a8641SAndroid Build Coastguard Worker    for (var entry of this.bindings_.values())
303*635a8641SAndroid Build Coastguard Worker      entry.close();
304*635a8641SAndroid Build Coastguard Worker    this.bindings_.clear();
305*635a8641SAndroid Build Coastguard Worker  };
306*635a8641SAndroid Build Coastguard Worker
307*635a8641SAndroid Build Coastguard Worker  BindingSet.prototype.setConnectionErrorHandler = function(callback) {
308*635a8641SAndroid Build Coastguard Worker    this.errorHandler_ = callback;
309*635a8641SAndroid Build Coastguard Worker  };
310*635a8641SAndroid Build Coastguard Worker
311*635a8641SAndroid Build Coastguard Worker  BindingSet.prototype.onConnectionError = function(bindingId, reason) {
312*635a8641SAndroid Build Coastguard Worker    this.bindings_.delete(bindingId);
313*635a8641SAndroid Build Coastguard Worker
314*635a8641SAndroid Build Coastguard Worker    if (this.errorHandler_)
315*635a8641SAndroid Build Coastguard Worker      this.errorHandler_(reason);
316*635a8641SAndroid Build Coastguard Worker  };
317*635a8641SAndroid Build Coastguard Worker
318*635a8641SAndroid Build Coastguard Worker  // ---------------------------------------------------------------------------
319*635a8641SAndroid Build Coastguard Worker
320*635a8641SAndroid Build Coastguard Worker  // Operations used to setup/configure an associated interface pointer.
321*635a8641SAndroid Build Coastguard Worker  // Exposed as |ptr| field of generated associated interface pointer classes.
322*635a8641SAndroid Build Coastguard Worker  // |associatedPtrInfo| could be omitted and passed into bind() later.
323*635a8641SAndroid Build Coastguard Worker  //
324*635a8641SAndroid Build Coastguard Worker  // Example:
325*635a8641SAndroid Build Coastguard Worker  //    // IntegerSenderImpl implements mojom.IntegerSender
326*635a8641SAndroid Build Coastguard Worker  //    function IntegerSenderImpl() { ... }
327*635a8641SAndroid Build Coastguard Worker  //    IntegerSenderImpl.prototype.echo = function() { ... }
328*635a8641SAndroid Build Coastguard Worker  //
329*635a8641SAndroid Build Coastguard Worker  //    // IntegerSenderConnectionImpl implements mojom.IntegerSenderConnection
330*635a8641SAndroid Build Coastguard Worker  //    function IntegerSenderConnectionImpl() {
331*635a8641SAndroid Build Coastguard Worker  //      this.senderBinding_ = null;
332*635a8641SAndroid Build Coastguard Worker  //    }
333*635a8641SAndroid Build Coastguard Worker  //    IntegerSenderConnectionImpl.prototype.getSender = function(
334*635a8641SAndroid Build Coastguard Worker  //        associatedRequest) {
335*635a8641SAndroid Build Coastguard Worker  //      this.senderBinding_ = new AssociatedBinding(mojom.IntegerSender,
336*635a8641SAndroid Build Coastguard Worker  //          new IntegerSenderImpl(),
337*635a8641SAndroid Build Coastguard Worker  //          associatedRequest);
338*635a8641SAndroid Build Coastguard Worker  //    }
339*635a8641SAndroid Build Coastguard Worker  //
340*635a8641SAndroid Build Coastguard Worker  //    var integerSenderConnection = new mojom.IntegerSenderConnectionPtr();
341*635a8641SAndroid Build Coastguard Worker  //    var integerSenderConnectionBinding = new Binding(
342*635a8641SAndroid Build Coastguard Worker  //        mojom.IntegerSenderConnection,
343*635a8641SAndroid Build Coastguard Worker  //        new IntegerSenderConnectionImpl(),
344*635a8641SAndroid Build Coastguard Worker  //        mojo.makeRequest(integerSenderConnection));
345*635a8641SAndroid Build Coastguard Worker  //
346*635a8641SAndroid Build Coastguard Worker  //    // A locally-created associated interface pointer can only be used to
347*635a8641SAndroid Build Coastguard Worker  //    // make calls when the corresponding associated request is sent over
348*635a8641SAndroid Build Coastguard Worker  //    // another interface (either the master interface or another
349*635a8641SAndroid Build Coastguard Worker  //    // associated interface).
350*635a8641SAndroid Build Coastguard Worker  //    var associatedInterfacePtrInfo = new AssociatedInterfacePtrInfo();
351*635a8641SAndroid Build Coastguard Worker  //    var associatedRequest = makeRequest(interfacePtrInfo);
352*635a8641SAndroid Build Coastguard Worker  //
353*635a8641SAndroid Build Coastguard Worker  //    integerSenderConnection.getSender(associatedRequest);
354*635a8641SAndroid Build Coastguard Worker  //
355*635a8641SAndroid Build Coastguard Worker  //    // Create an associated interface and bind the associated handle.
356*635a8641SAndroid Build Coastguard Worker  //    var integerSender = new mojom.AssociatedIntegerSenderPtr();
357*635a8641SAndroid Build Coastguard Worker  //    integerSender.ptr.bind(associatedInterfacePtrInfo);
358*635a8641SAndroid Build Coastguard Worker  //    integerSender.echo();
359*635a8641SAndroid Build Coastguard Worker
360*635a8641SAndroid Build Coastguard Worker  function AssociatedInterfacePtrController(interfaceType, associatedPtrInfo) {
361*635a8641SAndroid Build Coastguard Worker    this.version = 0;
362*635a8641SAndroid Build Coastguard Worker
363*635a8641SAndroid Build Coastguard Worker    this.interfaceType_ = interfaceType;
364*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = null;
365*635a8641SAndroid Build Coastguard Worker    this.proxy_ = null;
366*635a8641SAndroid Build Coastguard Worker
367*635a8641SAndroid Build Coastguard Worker    if (associatedPtrInfo) {
368*635a8641SAndroid Build Coastguard Worker      this.bind(associatedPtrInfo);
369*635a8641SAndroid Build Coastguard Worker    }
370*635a8641SAndroid Build Coastguard Worker  }
371*635a8641SAndroid Build Coastguard Worker
372*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.bind = function(
373*635a8641SAndroid Build Coastguard Worker      associatedPtrInfo) {
374*635a8641SAndroid Build Coastguard Worker    this.reset();
375*635a8641SAndroid Build Coastguard Worker    this.version = associatedPtrInfo.version;
376*635a8641SAndroid Build Coastguard Worker
377*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = new internal.InterfaceEndpointClient(
378*635a8641SAndroid Build Coastguard Worker        associatedPtrInfo.interfaceEndpointHandle);
379*635a8641SAndroid Build Coastguard Worker
380*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ .setPayloadValidators([
381*635a8641SAndroid Build Coastguard Worker        this.interfaceType_.validateResponse]);
382*635a8641SAndroid Build Coastguard Worker    this.proxy_ = new this.interfaceType_.proxyClass(
383*635a8641SAndroid Build Coastguard Worker        this.interfaceEndpointClient_);
384*635a8641SAndroid Build Coastguard Worker  };
385*635a8641SAndroid Build Coastguard Worker
386*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.isBound = function() {
387*635a8641SAndroid Build Coastguard Worker    return this.interfaceEndpointClient_ !== null;
388*635a8641SAndroid Build Coastguard Worker  };
389*635a8641SAndroid Build Coastguard Worker
390*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.reset = function() {
391*635a8641SAndroid Build Coastguard Worker    this.version = 0;
392*635a8641SAndroid Build Coastguard Worker    if (this.interfaceEndpointClient_) {
393*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close();
394*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
395*635a8641SAndroid Build Coastguard Worker    }
396*635a8641SAndroid Build Coastguard Worker    if (this.proxy_) {
397*635a8641SAndroid Build Coastguard Worker      this.proxy_ = null;
398*635a8641SAndroid Build Coastguard Worker    }
399*635a8641SAndroid Build Coastguard Worker  };
400*635a8641SAndroid Build Coastguard Worker
401*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.resetWithReason = function(
402*635a8641SAndroid Build Coastguard Worker      reason) {
403*635a8641SAndroid Build Coastguard Worker    if (this.isBound()) {
404*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close(reason);
405*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
406*635a8641SAndroid Build Coastguard Worker    }
407*635a8641SAndroid Build Coastguard Worker    this.reset();
408*635a8641SAndroid Build Coastguard Worker  };
409*635a8641SAndroid Build Coastguard Worker
410*635a8641SAndroid Build Coastguard Worker  // Indicates whether an error has been encountered. If true, method calls
411*635a8641SAndroid Build Coastguard Worker  // on this interface will be dropped (and may already have been dropped).
412*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.getEncounteredError = function() {
413*635a8641SAndroid Build Coastguard Worker    return this.interfaceEndpointClient_ ?
414*635a8641SAndroid Build Coastguard Worker        this.interfaceEndpointClient_.getEncounteredError() : false;
415*635a8641SAndroid Build Coastguard Worker  };
416*635a8641SAndroid Build Coastguard Worker
417*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.setConnectionErrorHandler =
418*635a8641SAndroid Build Coastguard Worker      function(callback) {
419*635a8641SAndroid Build Coastguard Worker    if (!this.isBound()) {
420*635a8641SAndroid Build Coastguard Worker      throw new Error("Cannot set connection error handler if not bound.");
421*635a8641SAndroid Build Coastguard Worker    }
422*635a8641SAndroid Build Coastguard Worker
423*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_.setConnectionErrorHandler(callback);
424*635a8641SAndroid Build Coastguard Worker  };
425*635a8641SAndroid Build Coastguard Worker
426*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.passInterface = function() {
427*635a8641SAndroid Build Coastguard Worker    if (!this.isBound()) {
428*635a8641SAndroid Build Coastguard Worker      return new mojo.AssociatedInterfacePtrInfo(null);
429*635a8641SAndroid Build Coastguard Worker    }
430*635a8641SAndroid Build Coastguard Worker
431*635a8641SAndroid Build Coastguard Worker    var result = new mojo.AssociatedInterfacePtrInfo(
432*635a8641SAndroid Build Coastguard Worker        this.interfaceEndpointClient_.passHandle(), this.version);
433*635a8641SAndroid Build Coastguard Worker    this.reset();
434*635a8641SAndroid Build Coastguard Worker    return result;
435*635a8641SAndroid Build Coastguard Worker  };
436*635a8641SAndroid Build Coastguard Worker
437*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.getProxy = function() {
438*635a8641SAndroid Build Coastguard Worker    return this.proxy_;
439*635a8641SAndroid Build Coastguard Worker  };
440*635a8641SAndroid Build Coastguard Worker
441*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.queryVersion = function() {
442*635a8641SAndroid Build Coastguard Worker    function onQueryVersion(version) {
443*635a8641SAndroid Build Coastguard Worker      this.version = version;
444*635a8641SAndroid Build Coastguard Worker      return version;
445*635a8641SAndroid Build Coastguard Worker    }
446*635a8641SAndroid Build Coastguard Worker
447*635a8641SAndroid Build Coastguard Worker    return this.interfaceEndpointClient_.queryVersion().then(
448*635a8641SAndroid Build Coastguard Worker      onQueryVersion.bind(this));
449*635a8641SAndroid Build Coastguard Worker  };
450*635a8641SAndroid Build Coastguard Worker
451*635a8641SAndroid Build Coastguard Worker  AssociatedInterfacePtrController.prototype.requireVersion = function(
452*635a8641SAndroid Build Coastguard Worker      version) {
453*635a8641SAndroid Build Coastguard Worker    if (this.version >= version) {
454*635a8641SAndroid Build Coastguard Worker      return;
455*635a8641SAndroid Build Coastguard Worker    }
456*635a8641SAndroid Build Coastguard Worker    this.version = version;
457*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_.requireVersion(version);
458*635a8641SAndroid Build Coastguard Worker  };
459*635a8641SAndroid Build Coastguard Worker
460*635a8641SAndroid Build Coastguard Worker  // ---------------------------------------------------------------------------
461*635a8641SAndroid Build Coastguard Worker
462*635a8641SAndroid Build Coastguard Worker  // |associatedInterfaceRequest| could be omitted and passed into bind()
463*635a8641SAndroid Build Coastguard Worker  // later.
464*635a8641SAndroid Build Coastguard Worker  function AssociatedBinding(interfaceType, impl, associatedInterfaceRequest) {
465*635a8641SAndroid Build Coastguard Worker    this.interfaceType_ = interfaceType;
466*635a8641SAndroid Build Coastguard Worker    this.impl_ = impl;
467*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = null;
468*635a8641SAndroid Build Coastguard Worker    this.stub_ = null;
469*635a8641SAndroid Build Coastguard Worker
470*635a8641SAndroid Build Coastguard Worker    if (associatedInterfaceRequest) {
471*635a8641SAndroid Build Coastguard Worker      this.bind(associatedInterfaceRequest);
472*635a8641SAndroid Build Coastguard Worker    }
473*635a8641SAndroid Build Coastguard Worker  }
474*635a8641SAndroid Build Coastguard Worker
475*635a8641SAndroid Build Coastguard Worker  AssociatedBinding.prototype.isBound = function() {
476*635a8641SAndroid Build Coastguard Worker    return this.interfaceEndpointClient_ !== null;
477*635a8641SAndroid Build Coastguard Worker  };
478*635a8641SAndroid Build Coastguard Worker
479*635a8641SAndroid Build Coastguard Worker  AssociatedBinding.prototype.bind = function(associatedInterfaceRequest) {
480*635a8641SAndroid Build Coastguard Worker    this.close();
481*635a8641SAndroid Build Coastguard Worker
482*635a8641SAndroid Build Coastguard Worker    this.stub_ = new this.interfaceType_.stubClass(this.impl_);
483*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ = new internal.InterfaceEndpointClient(
484*635a8641SAndroid Build Coastguard Worker        associatedInterfaceRequest.interfaceEndpointHandle, this.stub_,
485*635a8641SAndroid Build Coastguard Worker        this.interfaceType_.kVersion);
486*635a8641SAndroid Build Coastguard Worker
487*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_ .setPayloadValidators([
488*635a8641SAndroid Build Coastguard Worker        this.interfaceType_.validateRequest]);
489*635a8641SAndroid Build Coastguard Worker  };
490*635a8641SAndroid Build Coastguard Worker
491*635a8641SAndroid Build Coastguard Worker
492*635a8641SAndroid Build Coastguard Worker  AssociatedBinding.prototype.close = function() {
493*635a8641SAndroid Build Coastguard Worker    if (!this.isBound()) {
494*635a8641SAndroid Build Coastguard Worker      return;
495*635a8641SAndroid Build Coastguard Worker    }
496*635a8641SAndroid Build Coastguard Worker
497*635a8641SAndroid Build Coastguard Worker    if (this.interfaceEndpointClient_) {
498*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close();
499*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
500*635a8641SAndroid Build Coastguard Worker    }
501*635a8641SAndroid Build Coastguard Worker
502*635a8641SAndroid Build Coastguard Worker    this.stub_ = null;
503*635a8641SAndroid Build Coastguard Worker  };
504*635a8641SAndroid Build Coastguard Worker
505*635a8641SAndroid Build Coastguard Worker  AssociatedBinding.prototype.closeWithReason = function(reason) {
506*635a8641SAndroid Build Coastguard Worker    if (this.interfaceEndpointClient_) {
507*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_.close(reason);
508*635a8641SAndroid Build Coastguard Worker      this.interfaceEndpointClient_ = null;
509*635a8641SAndroid Build Coastguard Worker    }
510*635a8641SAndroid Build Coastguard Worker    this.close();
511*635a8641SAndroid Build Coastguard Worker  };
512*635a8641SAndroid Build Coastguard Worker
513*635a8641SAndroid Build Coastguard Worker  AssociatedBinding.prototype.setConnectionErrorHandler = function(callback) {
514*635a8641SAndroid Build Coastguard Worker    if (!this.isBound()) {
515*635a8641SAndroid Build Coastguard Worker      throw new Error("Cannot set connection error handler if not bound.");
516*635a8641SAndroid Build Coastguard Worker    }
517*635a8641SAndroid Build Coastguard Worker    this.interfaceEndpointClient_.setConnectionErrorHandler(callback);
518*635a8641SAndroid Build Coastguard Worker  };
519*635a8641SAndroid Build Coastguard Worker
520*635a8641SAndroid Build Coastguard Worker  AssociatedBinding.prototype.unbind = function() {
521*635a8641SAndroid Build Coastguard Worker    if (!this.isBound()) {
522*635a8641SAndroid Build Coastguard Worker      return new mojo.AssociatedInterfaceRequest(null);
523*635a8641SAndroid Build Coastguard Worker    }
524*635a8641SAndroid Build Coastguard Worker
525*635a8641SAndroid Build Coastguard Worker    var result = new mojo.AssociatedInterfaceRequest(
526*635a8641SAndroid Build Coastguard Worker        this.interfaceEndpointClient_.passHandle());
527*635a8641SAndroid Build Coastguard Worker    this.close();
528*635a8641SAndroid Build Coastguard Worker    return result;
529*635a8641SAndroid Build Coastguard Worker  };
530*635a8641SAndroid Build Coastguard Worker
531*635a8641SAndroid Build Coastguard Worker  // ---------------------------------------------------------------------------
532*635a8641SAndroid Build Coastguard Worker
533*635a8641SAndroid Build Coastguard Worker  function AssociatedBindingSet(interfaceType) {
534*635a8641SAndroid Build Coastguard Worker    mojo.BindingSet.call(this, interfaceType);
535*635a8641SAndroid Build Coastguard Worker    this.bindingType_ = AssociatedBinding;
536*635a8641SAndroid Build Coastguard Worker  }
537*635a8641SAndroid Build Coastguard Worker
538*635a8641SAndroid Build Coastguard Worker  AssociatedBindingSet.prototype = Object.create(BindingSet.prototype);
539*635a8641SAndroid Build Coastguard Worker  AssociatedBindingSet.prototype.constructor = AssociatedBindingSet;
540*635a8641SAndroid Build Coastguard Worker
541*635a8641SAndroid Build Coastguard Worker  mojo.makeRequest = makeRequest;
542*635a8641SAndroid Build Coastguard Worker  mojo.AssociatedInterfacePtrController = AssociatedInterfacePtrController;
543*635a8641SAndroid Build Coastguard Worker  mojo.AssociatedBinding = AssociatedBinding;
544*635a8641SAndroid Build Coastguard Worker  mojo.AssociatedBindingSet = AssociatedBindingSet;
545*635a8641SAndroid Build Coastguard Worker  mojo.Binding = Binding;
546*635a8641SAndroid Build Coastguard Worker  mojo.BindingSet = BindingSet;
547*635a8641SAndroid Build Coastguard Worker  mojo.InterfacePtrController = InterfacePtrController;
548*635a8641SAndroid Build Coastguard Worker})();
549