blob: 5fa9533cf96f356302de9df0e46ebda68aa51b5e [file] [log] [blame]
// Copyright 2017 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/associated_bindings", [
"mojo/public/js/bindings",
"mojo/public/js/core",
"mojo/public/js/interface_types",
"mojo/public/js/lib/interface_endpoint_client",
"mojo/public/js/lib/interface_endpoint_handle",
], function(bindings,
core,
types,
interfaceEndpointClient,
interfaceEndpointHandle) {
var InterfaceEndpointClient = interfaceEndpointClient.InterfaceEndpointClient;
// ---------------------------------------------------------------------------
function makeRequest(associatedInterfacePtrInfo) {
var {handle0, handle1} =
interfaceEndpointHandle.createPairPendingAssociation();
associatedInterfacePtrInfo.interfaceEndpointHandle = handle0;
associatedInterfacePtrInfo.version = 0;
var request = new types.AssociatedInterfaceRequest(handle1);
return request;
}
// ---------------------------------------------------------------------------
// Operations used to setup/configure an associated interface pointer.
// Exposed as |ptr| field of generated associated interface pointer classes.
// |associatedPtrInfo| could be omitted and passed into bind() later.
//
// Example:
// // IntegerSenderImpl implements mojom.IntegerSender
// function IntegerSenderImpl() { ... }
// IntegerSenderImpl.prototype.echo = function() { ... }
//
// // IntegerSenderConnectionImpl implements mojom.IntegerSenderConnection
// function IntegerSenderConnectionImpl() {
// this.senderBinding_ = null;
// }
// IntegerSenderConnectionImpl.prototype.getSender = function(
// associatedRequest) {
// this.senderBinding_ = new AssociatedBinding(mojom.IntegerSender,
// new IntegerSenderImpl(),
// associatedRequest);
// }
//
// var integerSenderConnection = new mojom.IntegerSenderConnectionPtr();
// var integerSenderConnectionBinding = new Binding(
// mojom.IntegerSenderConnection,
// new IntegerSenderConnectionImpl(),
// bindings.makeRequest(integerSenderConnection));
//
// // A locally-created associated interface pointer can only be used to
// // make calls when the corresponding associated request is sent over
// // another interface (either the master interface or another
// // associated interface).
// var associatedInterfacePtrInfo = new AssociatedInterfacePtrInfo();
// var associatedRequest = makeRequest(interfacePtrInfo);
//
// integerSenderConnection.getSender(associatedRequest);
//
// // Create an associated interface and bind the associated handle.
// var integerSender = new mojom.AssociatedIntegerSenderPtr();
// integerSender.ptr.bind(associatedInterfacePtrInfo);
// integerSender.echo();
function AssociatedInterfacePtrController(interfaceType, associatedPtrInfo) {
this.version = 0;
this.interfaceType_ = interfaceType;
this.interfaceEndpointClient_ = null;
this.proxy_ = null;
if (associatedPtrInfo) {
this.bind(associatedPtrInfo);
}
}
AssociatedInterfacePtrController.prototype.bind = function(
associatedPtrInfo) {
this.reset();
this.version = associatedPtrInfo.version;
this.interfaceEndpointClient_ = new InterfaceEndpointClient(
associatedPtrInfo.interfaceEndpointHandle);
this.interfaceEndpointClient_ .setPayloadValidators([
this.interfaceType_.validateResponse]);
this.proxy_ = new this.interfaceType_.proxyClass(
this.interfaceEndpointClient_);
};
AssociatedInterfacePtrController.prototype.isBound = function() {
return this.interfaceEndpointClient_ !== null;
};
AssociatedInterfacePtrController.prototype.reset = function() {
this.version = 0;
if (this.interfaceEndpointClient_) {
this.interfaceEndpointClient_.close();
this.interfaceEndpointClient_ = null;
}
if (this.proxy_) {
this.proxy_ = null;
}
};
AssociatedInterfacePtrController.prototype.resetWithReason = function(
reason) {
if (this.isBound()) {
this.interfaceEndpointClient_.close(reason);
this.interfaceEndpointClient_ = null;
}
this.reset();
};
// Indicates whether an error has been encountered. If true, method calls
// on this interface will be dropped (and may already have been dropped).
AssociatedInterfacePtrController.prototype.getEncounteredError = function() {
return this.interfaceEndpointClient_ ?
this.interfaceEndpointClient_.getEncounteredError() : false;
};
AssociatedInterfacePtrController.prototype.setConnectionErrorHandler =
function(callback) {
if (!this.isBound()) {
throw new Error("Cannot set connection error handler if not bound.");
}
this.interfaceEndpointClient_.setConnectionErrorHandler(callback);
};
AssociatedInterfacePtrController.prototype.passInterface = function() {
if (!this.isBound()) {
return new types.AssociatedInterfacePtrInfo(null);
}
var result = new types.AssociatedInterfacePtrInfo(
this.interfaceEndpointClient_.passHandle(), this.version);
this.reset();
return result;
};
AssociatedInterfacePtrController.prototype.getProxy = function() {
return this.proxy_;
};
AssociatedInterfacePtrController.prototype.queryVersion = function() {
function onQueryVersion(version) {
this.version = version;
return version;
}
return this.interfaceEndpointClient_.queryVersion().then(
onQueryVersion.bind(this));
};
AssociatedInterfacePtrController.prototype.requireVersion = function(
version) {
if (this.version >= version) {
return;
}
this.version = version;
this.interfaceEndpointClient_.requireVersion(version);
};
// ---------------------------------------------------------------------------
// |associatedInterfaceRequest| could be omitted and passed into bind()
// later.
function AssociatedBinding(interfaceType, impl, associatedInterfaceRequest) {
this.interfaceType_ = interfaceType;
this.impl_ = impl;
this.interfaceEndpointClient_ = null;
this.stub_ = null;
if (associatedInterfaceRequest) {
this.bind(associatedInterfaceRequest);
}
}
AssociatedBinding.prototype.isBound = function() {
return this.interfaceEndpointClient_ !== null;
};
AssociatedBinding.prototype.bind = function(associatedInterfaceRequest) {
this.close();
this.stub_ = new this.interfaceType_.stubClass(this.impl_);
this.interfaceEndpointClient_ = new InterfaceEndpointClient(
associatedInterfaceRequest.interfaceEndpointHandle, this.stub_,
this.interfaceType_.kVersion);
this.interfaceEndpointClient_ .setPayloadValidators([
this.interfaceType_.validateRequest]);
};
AssociatedBinding.prototype.close = function() {
if (!this.isBound()) {
return;
}
if (this.interfaceEndpointClient_) {
this.interfaceEndpointClient_.close();
this.interfaceEndpointClient_ = null;
}
this.stub_ = null;
};
AssociatedBinding.prototype.closeWithReason = function(reason) {
if (this.interfaceEndpointClient_) {
this.interfaceEndpointClient_.close(reason);
this.interfaceEndpointClient_ = null;
}
this.close();
};
AssociatedBinding.prototype.setConnectionErrorHandler = function(callback) {
if (!this.isBound()) {
throw new Error("Cannot set connection error handler if not bound.");
}
this.interfaceEndpointClient_.setConnectionErrorHandler(callback);
};
AssociatedBinding.prototype.unbind = function() {
if (!this.isBound()) {
return new types.AssociatedInterfaceRequest(null);
}
var result = new types.AssociatedInterfaceRequest(
this.interfaceEndpointClient_.passHandle());
this.close();
return result;
};
// ---------------------------------------------------------------------------
function AssociatedBindingSet(interfaceType) {
bindings.BindingSet.call(this, interfaceType);
this.bindingType_ = AssociatedBinding;
}
AssociatedBindingSet.prototype = Object.create(bindings.BindingSet.prototype);
AssociatedBindingSet.prototype.constructor = AssociatedBindingSet;
var exports = {};
exports.AssociatedInterfacePtrInfo = types.AssociatedInterfacePtrInfo;
exports.AssociatedInterfaceRequest = types.AssociatedInterfaceRequest;
exports.makeRequest = makeRequest;
exports.AssociatedInterfacePtrController = AssociatedInterfacePtrController;
exports.AssociatedBinding = AssociatedBinding;
exports.AssociatedBindingSet = AssociatedBindingSet;
return exports;
});