michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: michael@0: function TCPSocketParentIntermediary() { michael@0: } michael@0: michael@0: TCPSocketParentIntermediary.prototype = { michael@0: _setCallbacks: function(aParentSide, socket) { michael@0: aParentSide.initJS(this); michael@0: this._socket = socket; michael@0: michael@0: // Create handlers for every possible callback that attempt to trigger michael@0: // corresponding callbacks on the child object. michael@0: // ondrain event is not forwarded, since the decision of firing ondrain michael@0: // is made in child. michael@0: ["open", "data", "error", "close"].forEach( michael@0: function(p) { michael@0: socket["on" + p] = function(data) { michael@0: aParentSide.sendEvent(p, data.data, socket.readyState, michael@0: socket.bufferedAmount); michael@0: }; michael@0: } michael@0: ); michael@0: }, michael@0: michael@0: _onUpdateBufferedAmountHandler: function(aParentSide, aBufferedAmount, aTrackingNumber) { michael@0: aParentSide.sendUpdateBufferedAmount(aBufferedAmount, aTrackingNumber); michael@0: }, michael@0: michael@0: open: function(aParentSide, aHost, aPort, aUseSSL, aBinaryType, aAppId) { michael@0: let baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket); michael@0: let socket = baseSocket.open(aHost, aPort, {useSecureTransport: aUseSSL, binaryType: aBinaryType}); michael@0: if (!socket) michael@0: return null; michael@0: michael@0: let socketInternal = socket.QueryInterface(Ci.nsITCPSocketInternal); michael@0: if (socketInternal) { michael@0: socketInternal.setAppId(aAppId); michael@0: } michael@0: michael@0: // Handle parent's request to update buffered amount. michael@0: socketInternal.setOnUpdateBufferedAmountHandler( michael@0: this._onUpdateBufferedAmountHandler.bind(this, aParentSide)); michael@0: michael@0: // Handlers are set to the JS-implemented socket object on the parent side. michael@0: this._setCallbacks(aParentSide, socket); michael@0: return socket; michael@0: }, michael@0: michael@0: listen: function(aTCPServerSocketParent, aLocalPort, aBacklog, aBinaryType) { michael@0: let baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket); michael@0: let serverSocket = baseSocket.listen(aLocalPort, { binaryType: aBinaryType }, aBacklog); michael@0: if (!serverSocket) michael@0: return null; michael@0: michael@0: let localPort = serverSocket.localPort; michael@0: michael@0: serverSocket["onconnect"] = function(socket) { michael@0: var socketParent = Cc["@mozilla.org/tcp-socket-parent;1"] michael@0: .createInstance(Ci.nsITCPSocketParent); michael@0: var intermediary = new TCPSocketParentIntermediary(); michael@0: // Handlers are set to the JS-implemented socket object on the parent side, michael@0: // so that the socket parent object can communicate data michael@0: // with the corresponding socket child object through IPC. michael@0: intermediary._setCallbacks(socketParent, socket); michael@0: // The members in the socket parent object are set with arguments, michael@0: // so that the socket parent object can communicate data michael@0: // with the JS socket object on the parent side via the intermediary object. michael@0: socketParent.setSocketAndIntermediary(socket, intermediary); michael@0: aTCPServerSocketParent.sendCallbackAccept(socketParent); michael@0: }; michael@0: michael@0: serverSocket["onerror"] = function(data) { michael@0: var error = data.data; michael@0: michael@0: aTCPServerSocketParent.sendCallbackError(error.message, error.filename, michael@0: error.lineNumber, error.columnNumber); michael@0: }; michael@0: michael@0: return serverSocket; michael@0: }, michael@0: michael@0: onRecvSendString: function(aData, aTrackingNumber) { michael@0: let socketInternal = this._socket.QueryInterface(Ci.nsITCPSocketInternal); michael@0: return socketInternal.onRecvSendFromChild(aData, 0, 0, aTrackingNumber); michael@0: }, michael@0: michael@0: onRecvSendArrayBuffer: function(aData, aTrackingNumber) { michael@0: let socketInternal = this._socket.QueryInterface(Ci.nsITCPSocketInternal); michael@0: return socketInternal.onRecvSendFromChild(aData, 0, aData.byteLength, michael@0: aTrackingNumber); michael@0: }, michael@0: michael@0: classID: Components.ID("{afa42841-a6cb-4a91-912f-93099f6a3d18}"), michael@0: QueryInterface: XPCOMUtils.generateQI([ michael@0: Ci.nsITCPSocketIntermediary michael@0: ]) michael@0: }; michael@0: michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TCPSocketParentIntermediary]);