Comparing version 0.2.1 to 0.2.2
{ | ||
"name": "freedom", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"homepage": "http://freedomjs.com", | ||
@@ -5,0 +5,0 @@ "repository": {"type": "git", "url": "git://github.com/UWNetworksLab/freedom.git"}, |
@@ -27,3 +27,3 @@ var FILES = { | ||
'spec/providers/storage/**/*.unit.spec.js', | ||
//'spec/providers/transport/**/*.unit.spec.js', | ||
'spec/providers/transport/**/*.unit.spec.js', | ||
], | ||
@@ -30,0 +30,0 @@ specintegration: [ |
@@ -37,4 +37,6 @@ fdom.apis.set("core", { | ||
'onConnection': {type: "event", value: { | ||
"serverSocketId": "number", | ||
"clientSocketId": "number"}}, | ||
'serverSocketId': "number", | ||
'clientSocketId': "number"}}, | ||
'onDisconnect': {type: "event", value: { | ||
"socketId": "number", "error": "string"}}, | ||
'getInfo': {type: "method", value: ["number"]} | ||
@@ -66,4 +68,4 @@ }); | ||
// The list of STUN servers to use. | ||
// format is of a single entry is stun:HOST:PORT, where HOST and | ||
// PORT are the hostname and port, respectively. | ||
// The format of a single entry is stun:HOST:PORT, where HOST | ||
// and PORT are a stun server hostname and port, respectively. | ||
["array", "string"] | ||
@@ -70,0 +72,0 @@ ] |
{ | ||
"name": "freedom", | ||
"description": "Embracing a distributed web", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"homepage": "http://freedomjs.com", | ||
@@ -6,0 +6,0 @@ "main": "src/util/node.js", |
@@ -13,3 +13,3 @@ /*globals fdom:true */ | ||
*/ | ||
var Core_unprivileged = function(manager) { | ||
var Core_unprivileged = function(manager, postMessage) { | ||
this.manager = manager; | ||
@@ -16,0 +16,0 @@ }; |
@@ -12,5 +12,6 @@ /*globals fdom:true */ | ||
*/ | ||
var Echo_unprivileged = function(app) { | ||
var Echo_unprivileged = function(app, dispatchEvent) { | ||
fdom.debug.log('Echo Created!'); | ||
this.app = app; | ||
this.dispatchEvent = dispatchEvent; | ||
fdom.util.handleEvents(this); | ||
@@ -17,0 +18,0 @@ |
@@ -95,3 +95,2 @@ // A FreeDOM interface to a WebRTC Peer Connection via the peerdata wrapper. | ||
continuation(); | ||
this._dataChannelCallbacks.onOpenFn(dataChannel, {label: channelId}); | ||
}.bind(this); | ||
@@ -174,3 +173,5 @@ }.bind(this)); | ||
// channel.onopen = callbacks.onOpenFn.bind(this, channel, {label: channelId}); | ||
if (channel.readyState === "connecting") { | ||
channel.onopen = callbacks.onOpenFn.bind(this, channel, {label: channelId}); | ||
} | ||
@@ -263,8 +264,16 @@ channel.onclose = callbacks.onCloseFn.bind(this, channel, {label: channelId}); | ||
this._addDataChannel(event.channel.label, event.channel); | ||
// RTCDataChannels created by a RTCDataChannelEvent have an initial | ||
// state of open, so the onopen event for the channel will not | ||
// fire. We need to fire the onOpenDataChannel event here | ||
// http://www.w3.org/TR/webrtc/#idl-def-RTCDataChannelState | ||
this._dataChannelCallbacks.onOpenFn(event.channel, | ||
{label: event.channel.label}); | ||
}; | ||
// _signallingChannel is a channel for emitting events back to the freedom Hub. | ||
function PeerConnection(portApp) { | ||
function PeerConnection(portApp, dispatchEvent) { | ||
// Channel for emitting events to consumer. | ||
this.dispatchEvent = dispatchEvent; | ||
// a (hopefully unique) ID for debugging. | ||
// a (hopefully unique) ID for debugging. | ||
this.peerName = "p" + Math.random(); | ||
@@ -271,0 +280,0 @@ |
@@ -12,3 +12,3 @@ /** | ||
*/ | ||
var Storage_unprivileged = function(app) { | ||
var Storage_unprivileged = function(app, dispatchEvent) { | ||
this.app = app; | ||
@@ -15,0 +15,0 @@ fdom.util.handleEvents(this); |
@@ -11,3 +11,4 @@ /** | ||
*/ | ||
var View_unprivileged = function(app) { | ||
var View_unprivileged = function(app, dispatchEvent) { | ||
this.dispatchEvent = dispatchEvent; | ||
this.host = null; | ||
@@ -95,3 +96,3 @@ this.win = null; | ||
if (m.source == this.win.contentWindow) { | ||
this['dispatchEvent']('message', m.data); | ||
this.dispatchEvent('message', m.data); | ||
} | ||
@@ -98,0 +99,0 @@ }; |
@@ -14,3 +14,5 @@ /** | ||
function LoopbackSocialProvider() { | ||
function LoopbackSocialProvider(dispatchEvent) { | ||
this.dispatchEvent = dispatchEvent; | ||
//Constants | ||
@@ -17,0 +19,0 @@ this.NETWORK_ID = 'loopback'; |
var window = {}; | ||
var view = freedom['core.view'](); | ||
function IdentityProvider() { | ||
function IdentityProvider(dispatchEvent) { | ||
console.log("Manual Identity Provider"); | ||
this.dispatchEvent = dispatchEvent; | ||
this.status = 'offline'; | ||
@@ -7,0 +8,0 @@ this.userId = 'manual'; |
@@ -0,1 +1,4 @@ | ||
/*globals freedom:true, WebSocket */ | ||
/*jslint indent:2, white:true, node:true, sloppy:true, browser:true */ | ||
/** | ||
@@ -12,7 +15,9 @@ * Implementation of a Social provider that depends on | ||
* - ephemeral userIds and clientIds | ||
* @class WSSocialProvider | ||
* @constructor | ||
* @param {Function} dispatchEvent callback to signal events | ||
* @param {WebSocket} webSocket Alternative webSocket implementation for tests | ||
**/ | ||
//var this.WS_URL = 'ws://localhost:8082/route/'; | ||
function WSSocialProvider() { | ||
function WSSocialProvider(dispatchEvent, webSocket) { | ||
this.dispatchEvent = dispatchEvent; | ||
this.WS_URL = 'ws://p2pbr.com:8082/route/'; | ||
@@ -26,3 +31,6 @@ this.NETWORK_ID = 'websockets'; | ||
this.roster = {}; // List of seen users | ||
setTimeout(this._sendStatus.bind(this,'OFFLINE', 'offline'),0); | ||
this.provider = webSocket || WebSocket; | ||
setTimeout(this.sendStatus.bind(this, 'OFFLINE', 'offline'), 0); | ||
} | ||
@@ -40,22 +48,32 @@ | ||
WSSocialProvider.prototype.login = function(loginOpts, continuation) { | ||
var finishLogin = { | ||
finished: false, | ||
continuation: continuation, | ||
finish: function(msg) { | ||
if (this.continuation) { | ||
this.continuation(msg); | ||
delete this.continuation; | ||
} | ||
} | ||
}; | ||
if (this.conn !== null) { | ||
console.warn("Already logged in"); | ||
continuation(this._sendStatus("ONLINE")); | ||
finishLogin.finish(this.sendStatus("ONLINE")); | ||
return; | ||
} | ||
this.conn = new WebSocket(this.WS_URL+loginOpts.agent); | ||
this.conn = new this.provider(this.WS_URL + loginOpts.agent); | ||
// Save the continuation until we get a status message for | ||
// successful login. | ||
this._cont = continuation; | ||
this.conn.onmessage = this._onMessage.bind(this); | ||
this.conn.onerror = (function (cont, error) { | ||
this.conn.onmessage = this.onMessage.bind(this, finishLogin); | ||
this.conn.onerror = function (cont, error) { | ||
this.conn = null; | ||
this._cont(this._sendStatus('ERR_CONNECTION', error)); | ||
}).bind(this, continuation); | ||
this.conn.onclose = (function (cont, msg) { | ||
cont.finish(this.sendStatus('ERR_CONNECTION', error)); | ||
}.bind(this, finishLogin); | ||
this.conn.onclose = function (cont, msg) { | ||
this.conn = null; | ||
this._cont(this._sendStatus('OFFLINE', 'offline')); | ||
}).bind(this, continuation); | ||
cont.finish(this.sendStatus('OFFLINE', 'offline')); | ||
}.bind(this, finishLogin); | ||
this._sendStatus('CONNECTING', 'connecting'); | ||
this.sendStatus('CONNECTING', 'connecting'); | ||
}; | ||
@@ -111,9 +129,9 @@ | ||
console.warn("Already logged out"); | ||
continuation(this._sendStatus('OFFLINE', 'offline')); | ||
continuation(this.sendStatus('OFFLINE', 'offline')); | ||
return; | ||
} | ||
this.conn.onclose = function() { | ||
this.conn.onclose = function(continuation) { | ||
this.conn = null; | ||
continuation(this._sendStatus('OFFLINE', 'offline')); | ||
}.bind(this); | ||
continuation(this.sendStatus('OFFLINE', 'offline')); | ||
}.bind(this, continuation); | ||
this.conn.close(); | ||
@@ -129,3 +147,4 @@ }; | ||
* | ||
* @method _sendStatus | ||
* @method sendStatus | ||
* @private | ||
* @param {String} stat - One of the error codes in STATUS_NETWORK | ||
@@ -135,3 +154,3 @@ * @param {String} message - Display message in the event | ||
**/ | ||
WSSocialProvider.prototype._sendStatus = function(stat, message) { | ||
WSSocialProvider.prototype.sendStatus = function(stat, message) { | ||
var result = { | ||
@@ -152,16 +171,18 @@ network: this.NETWORK_ID, | ||
* | ||
* @method _changeRoster | ||
* @method changeRoster | ||
* @private | ||
* @param {String} id - userId of user | ||
* @return nothing | ||
**/ | ||
WSSocialProvider.prototype._changeRoster = function(id, online) { | ||
WSSocialProvider.prototype.changeRoster = function(id, online) { | ||
//Keep track if we've actually made changes | ||
var sendChange = false; | ||
var sendChange = false, | ||
clients = {}; | ||
//Create entry if not there | ||
if (!this.roster[id]) { | ||
sendChange = true; | ||
var c = {}; | ||
c[id] = { | ||
clients[id] = { | ||
clientId: id, | ||
status: this.STATUS_CLIENT["MESSAGEABLE"] | ||
network: this.NETWORK_ID, | ||
status: this.STATUS_CLIENT.MESSAGEABLE | ||
}; | ||
@@ -171,11 +192,13 @@ this.roster[id] = { | ||
name: id, | ||
clients: c | ||
clients: clients | ||
}; | ||
} | ||
//Update online/offline status | ||
if (online && this.roster[id].clients[id].status !== this.STATUS_CLIENT["MESSAGEABLE"]) { | ||
this.roster[id].clients[id].status = this.STATUS_CLIENT["MESSAGEABLE"]; | ||
if (online && this.roster[id].clients[id].status !== | ||
this.STATUS_CLIENT.MESSAGEABLE) { | ||
this.roster[id].clients[id].status = this.STATUS_CLIENT.MESSAGEABLE; | ||
sendChange = true; | ||
} else if (!online && this.roster[id].clients[id].status !== this.STATUS_CLIENT["OFFLINE"]) { | ||
this.roster[id].clients[id].status = this.STATUS_CLIENT["OFFLINE"]; | ||
} else if (!online && this.roster[id].clients[id].status !== | ||
this.STATUS_CLIENT.OFFLINE) { | ||
this.roster[id].clients[id].status = this.STATUS_CLIENT.OFFLINE; | ||
sendChange = true; | ||
@@ -196,27 +219,27 @@ } | ||
* | ||
* @method _onMessage | ||
* @param {String} msg - message from the server (see server/router.py for schema) | ||
* @method onMessage | ||
* @private | ||
* @param {Object} continuation Function to call upon successful login | ||
* @param {String} msg Message from the server (see server/router.py for schema) | ||
* @return nothing | ||
**/ | ||
WSSocialProvider.prototype._onMessage = function(msg) { | ||
WSSocialProvider.prototype.onMessage = function(continuation, msg) { | ||
var i; | ||
msg = JSON.parse(msg.data); | ||
// If state information from the server | ||
// Store my own ID and all known users at the time | ||
if (msg.cmd == 'state') { | ||
if (msg.cmd === 'state') { | ||
this.id = msg.id; | ||
this._changeRoster(this.id, true); | ||
for (var i=0; i<msg.msg.length; i++) { | ||
this._changeRoster(msg.msg[i], true); | ||
this.changeRoster(this.id, true); | ||
for (i = 0; i < msg.msg.length; i += 1) { | ||
this.changeRoster(msg.msg[i], true); | ||
} | ||
if (typeof this._cont === 'function') { | ||
this.conn.onclose = null; | ||
this.conn.onerror = null; | ||
this._cont(this._sendStatus('ONLINE', 'online')); | ||
this._cont = null; | ||
if (!continuation.finished) { | ||
continuation.finish(this.sendStatus('ONLINE', 'online')); | ||
} | ||
// If directed message, emit event | ||
} else if (msg.cmd == 'message') { | ||
this._changeRoster(msg.from, true); | ||
} else if (msg.cmd === 'message') { | ||
this.changeRoster(msg.from, true); | ||
this.dispatchEvent('onMessage', { | ||
@@ -231,7 +254,7 @@ fromUserId: msg.from, | ||
// Roster change event | ||
} else if (msg.cmd == 'roster') { | ||
this._changeRoster(msg.id, msg.online); | ||
} else if (msg.cmd === 'roster') { | ||
this.changeRoster(msg.id, msg.online); | ||
// No idea what this message is, but let's keep track of who it's from | ||
} else if (msg.from) { | ||
this._changeRoster(msg.from, true); | ||
this.changeRoster(msg.from, true); | ||
} | ||
@@ -238,0 +261,0 @@ }; |
@@ -1,18 +0,3 @@ | ||
fdom.apis.set("core.socket", { | ||
'create': {type: "method", value: ["string", "object"]}, | ||
'connect': {type: "method", value: ["number", "string", "number"]}, | ||
'onData': {type: "event", value: {"socketId": "number", "data": "buffer"}}, | ||
'write': {type: "method", value: ["number", "buffer"]}, | ||
'disconnect': {type: "method", value: ["number"]}, | ||
'destroy': {type: "method", value: ["number"]}, | ||
'listen': {type: "method", value: ["number", "string", "number"]}, | ||
'onConnection': {type: "event", value: { | ||
"serverSocketId": "number", | ||
"clientSocketId": "number"}}, | ||
'getInfo': {type: "method", value: ["number"]} | ||
}); | ||
function TransportProvider() { | ||
function TransportProvider(dispatchEvent) { | ||
this.dispatchEvent = dispatchEvent; | ||
this.state = TransportProvider.state.DISCONNECTED; | ||
@@ -19,0 +4,0 @@ this.channel = null; |
@@ -1,9 +0,1 @@ | ||
var stun_servers = [ | ||
"stun:stun.l.google.com:19302", | ||
"stun:stun1.l.google.com:19302", | ||
"stun:stun2.l.google.com:19302", | ||
"stun:stun3.l.google.com:19302", | ||
"stun:stun4.l.google.com:19302" | ||
]; | ||
/* | ||
@@ -14,4 +6,4 @@ * Peer 2 Peer transport provider. | ||
function TransportProvider() { | ||
console.log("TransportProvider: running in worker " + self.location.href); | ||
var WebRTCTransportProvider = function(dispatchEvent) { | ||
this.dispatchEvent = dispatchEvent; | ||
this.name = null; | ||
@@ -22,15 +14,23 @@ this.pc = freedom['core.peerconnection'](); | ||
this._tags = []; | ||
} | ||
}; | ||
WebRTCTransportProvider.stun_servers = [ | ||
"stun:stun.l.google.com:19302", | ||
"stun:stun1.l.google.com:19302", | ||
"stun:stun2.l.google.com:19302", | ||
"stun:stun3.l.google.com:19302", | ||
"stun:stun4.l.google.com:19302" | ||
]; | ||
// The argument |channelId| is a freedom communication channel id to use | ||
// to open a peer connection. | ||
TransportProvider.prototype.setup = function(name, channelId, continuation) { | ||
console.log("TransportProvider.setup." + name); | ||
WebRTCTransportProvider.prototype.setup = function(name, channelId, continuation) { | ||
// console.log("TransportProvider.setup." + name); | ||
this.name = name; | ||
var promise = this.pc.setup(channelId, name, stun_servers); | ||
var promise = this.pc.setup(channelId, name, WebRTCTransportProvider.stun_servers); | ||
promise.done(continuation); | ||
}; | ||
TransportProvider.prototype.send = function(tag, data, continuation) { | ||
console.log("TransportProvider.send." + this.name); | ||
WebRTCTransportProvider.prototype.send = function(tag, data, continuation) { | ||
// console.log("TransportProvider.send." + this.name); | ||
if (this._tags.indexOf(tag) >= 0) { | ||
@@ -47,3 +47,3 @@ var promise = this.pc.send({"channelLabel": tag, "buffer": data}); | ||
TransportProvider.prototype.close = function(continuation) { | ||
WebRTCTransportProvider.prototype.close = function(continuation) { | ||
// TODO: Close data channels. | ||
@@ -55,4 +55,4 @@ this._tags = []; | ||
// Called when the peer-connection receives data, it then passes it here. | ||
TransportProvider.prototype.onData = function(msg) { | ||
console.log("TransportProvider.prototype.message: Got Message:" + JSON.stringify(msg)); | ||
WebRTCTransportProvider.prototype.onData = function(msg) { | ||
// console.log("TransportProvider.prototype.message: Got Message:" + JSON.stringify(msg)); | ||
if (msg.buffer) { | ||
@@ -72,3 +72,3 @@ this.dispatchEvent('onData', { | ||
TransportProvider.prototype.onClose = function() { | ||
WebRTCTransportProvider.prototype.onClose = function() { | ||
this._tags = []; | ||
@@ -80,3 +80,3 @@ this.dispatchEvent('onClose', null); | ||
if (typeof freedom !== 'undefined') { | ||
freedom.transport().provideAsynchronous(TransportProvider); | ||
freedom.transport().provideAsynchronous(WebRTCTransportProvider); | ||
} |
freedom.js | ||
======= | ||
[](https://travis-ci.org/UWNetworksLab/freedom) | ||
[](https://coveralls.io/r/UWNetworksLab/freedom) | ||
[](https://coveralls.io/r/UWNetworksLab/freedom?branch=master) | ||
@@ -9,6 +9,5 @@ freedom.js is a runtime for distributed web applications | ||
Building distributed systems is hard! Debugging machines out of your control | ||
or in states you don't fully understand is accompanied by a plethora of potential missteps. | ||
or in states you don't fully understand is miserable. Trust us. | ||
The freedom.js runtime gives you the benefits of distribution without the headaches. The runtime comes with a solid set of service implementations | ||
for storage, communication, and navigating a social graph, and an architecture to allow building, thinking about, and debugging your application from the perspective of a single user. | ||
The freedom.js library gives you the benefits of distribution without the headaches. freedom.js comes with a tested set of implementations for storage, communication, and navigating the social graph. The library exposes an architecture allowing you to build, think about, and debug your application from the perspective of a single user. | ||
@@ -18,5 +17,7 @@ Use freedom.js | ||
A generated one-file version of freedom.js is maintained [here](https://homes.cs.washington.edu/~wrs/freedom.js). | ||
If you want to drop freedom.js into your website, grab the copy [here](https://homes.cs.washington.edu/~wrs/freedom.js). | ||
Documentation for generating freedom.js yourself, or including it in your project, is maintained | ||
If you want to include freedom.js in your build process, run ```npm install freedom```. | ||
More documentation for building freedom.js, and including it in your project is | ||
on the github [wiki](https://github.com/UWNetworksLab/freedom/wiki). | ||
@@ -27,8 +28,7 @@ | ||
Several demonstrations of the freedom.js library are available as included [```demos```](https://homes.cs.washington.edu/~wrs/demo/). | ||
[Demos](https://homes.cs.washington.edu/~wrs/demo/) show many of the common freedom.js patterns. | ||
To run the demonstrations locally, freedom.js must be [generated](#build-freedomjs) on your machine. Note that the freedom.js library cannot work when included as a ```file://``` URL (where xhr requests are not allowed by browser security policies). For testing locally, we recommend running ```python -m SimpleHTTPServer``` to access your page via a local HTTP URL. | ||
To run the demonstrations locally, first [build freedom.js](#build-freedomjs). freedom.js will not work when included as a ```file://``` URL (since reading from other file protocol URLs is disallowed). Instead, we recommend running ```python -m SimpleHTTPServer``` to access your page via a local HTTP URL. | ||
Note: FreeDOM has only been tested using Chrome and Firefox. | ||
Other browsers may experience issues. | ||
freedom.js is being developed against current versions of Chrome and Firefox. | ||
@@ -38,5 +38,5 @@ Build freedom.js | ||
You can get started with freedom.js by using the generated version linked above. If you want to bundle freedom.js with custom providers, or otherwise need to generate your own version, run [```grunt```](http://gruntjs.com) in the main repository. This will compile, lint, unit test, and optionally compress the code base. freedom.js can also be included in your project as an NPM dependency: | ||
To create your own freedom.js, run [```grunt```](http://gruntjs.com) in the main repository. This will compile, lint, unit test, and optionally compress the code base. freedom.js can also be included in your project as an NPM dependency: | ||
npm install freedom --save-dev | ||
npm install freedom --save | ||
@@ -48,4 +48,4 @@ Help freedom.js | ||
Pull requests are automatically reviewed by travis to verify code quality and unit tests. You can predict that a pull request will fail if running ```grunt``` locally fails. | ||
Pull requests are automatically reviewed by travis to verify code quality and unit tests. You can predict that a pull request will fail if running ```grunt test``` locally fails. | ||
Internal documentation for the library is also [automatically generated](https://homes.cs.washington.edu/~wrs/tools/doc) and provides a reasonable starting point for understanding how the internals of freedom.js work together. | ||
Internal documentation for the library is [automatically generated](https://homes.cs.washington.edu/~wrs/tools/doc) and provides a reasonable starting point for understanding the internals of freedom.js. |
function RTCPeerConnection(configuration, constraints) { | ||
RTCPeerConnection.mostRecent = this; | ||
this.configuration = configuration; | ||
this.constraints = constraints; | ||
this.listeners = {}; | ||
} | ||
RTCPeerConnection.prototype.addEventListener = function(event, func) { | ||
// We only allow registering one listener for simplicity | ||
this.listeners[event] = func; | ||
}; | ||
RTCPeerConnection.setRemoteDescriptionSuccess = true; | ||
RTCPeerConnection.prototype.setRemoteDescription = function(description, | ||
successCallback, | ||
failureCallback) { | ||
if (RTCPeerConnection.setRemoteDescriptionSuccess) { | ||
this.remoteDescription = description; | ||
successCallback(); | ||
} else { | ||
failureCallback(); | ||
} | ||
RTCPeerConnection.prototype.createDataChannel = function(label, dict) { | ||
var dataChannel = new RTCDataChannel(label, dict); | ||
return dataChannel; | ||
}; | ||
function RTCDataChannel(label, dict) { | ||
RTCDataChannel.mostRecent = this; | ||
this.label = label; | ||
this._closed = false; | ||
setTimeout(function() { | ||
if (typeof this.onopen === 'function') { | ||
this.onopen(); | ||
} | ||
}.bind(this), 0); | ||
} | ||
RTCDataChannel.prototype.send = function() { | ||
}; | ||
RTCDataChannel.prototype.close = function() { | ||
this._closed = true; | ||
}; | ||
function RTCSessionDescription(descriptionInitDict) { | ||
this.descriptionInitDict = descriptionInitDict; | ||
this.sdp = descriptionInitDict.sdp; | ||
this.type = descriptionInitDict.type; | ||
} | ||
describe("providers/core/peerconnection", function() { | ||
var portApp, events, emitted, listeningOn; | ||
var portApp, signalChannel, emitted, listeningOn; | ||
var dispatchedEvents; | ||
var peerconnection; | ||
@@ -33,25 +53,16 @@ var turnServers = []; | ||
function Core () { | ||
}; | ||
function Core () { | ||
}; | ||
Core.prototype.bindChannel = function(id, continuation) { | ||
console.info("bind channel"); | ||
continuation(events); | ||
}; | ||
Core.prototype.bindChannel = function(id, continuation) { | ||
continuation(signalChannel); | ||
}; | ||
function setup(done) { | ||
function setupCalled() { | ||
expect(emitted).toContain({eventName: "ready", eventData: undefined}); | ||
done(); | ||
} | ||
peerconnection.setup(PROXY, "setup peer", turnServers, setupCalled); | ||
} | ||
beforeEach(function beforeEach() { | ||
beforeEach(function beforeEach(done) { | ||
emitted = []; | ||
listeningOn = {}; | ||
dispatchedEvents = {}; | ||
RTCPeerConnection.setRemoteDescriptionSuccess = true; | ||
events = { | ||
// signalling channel events | ||
signalChannel = { | ||
emit: function(eventName, eventData) { | ||
@@ -65,3 +76,3 @@ emitted.push({eventName: eventName, | ||
}; | ||
portApp = { | ||
@@ -76,15 +87,107 @@ once: function(name, func) { | ||
peerconnection = new PeerConnection(portApp); | ||
peerconnection.dispatchEvent = function(event, data) { | ||
dispatchedEvents[event] = data; | ||
}; | ||
function setupCalled() { | ||
expect(emitted).toContain({eventName: "ready", eventData: undefined}); | ||
done(); | ||
} | ||
peerconnection.setup(PROXY, "setup peer", turnServers, setupCalled); | ||
}); | ||
it("sets up.", setup); | ||
it("Opens data channel", function(done) { | ||
var rtcpc = RTCPeerConnection.mostRecent; | ||
spyOn(rtcpc, "createDataChannel").and.callThrough(); | ||
peerconnection.openDataChannel("openDC", openDataChannelContinuation); | ||
it("handles remote offer messages.", function(done) { | ||
var message = JSON.stringify({sdp: "v=0"}); | ||
setup(sendMessage); | ||
function sendMessage() { | ||
listeningOn.message(message); | ||
function openDataChannelContinuation() { | ||
var dataChannel; | ||
expect(rtcpc.createDataChannel).toHaveBeenCalledWith("openDC", {}); | ||
dataChannel = RTCDataChannel.mostRecent; | ||
expect(dataChannel).toBeDefined(); | ||
expect(dataChannel.label).toEqual("openDC"); | ||
done(); | ||
} | ||
}); | ||
it("Fires onOpenDataChannel for peer created data channels.", function(done) { | ||
var rtcpc = RTCPeerConnection.mostRecent; | ||
var dataChannel = new RTCDataChannel("onOpenDC", {}); | ||
var event = {channel: dataChannel}; | ||
rtcpc.listeners.datachannel(event); | ||
expect(dispatchedEvents.onOpenDataChannel).toEqual("onOpenDC"); | ||
done(); | ||
}); | ||
it("Closes data channel", function(done) { | ||
var rtcpc = RTCPeerConnection.mostRecent; | ||
var dataChannel; | ||
peerconnection.openDataChannel("closeDC", openDataChannelContinuation); | ||
function openDataChannelContinuation() { | ||
dataChannel = RTCDataChannel.mostRecent; | ||
expect(dataChannel).toBeDefined(); | ||
spyOn(dataChannel, "close").and.callThrough(); | ||
peerconnection.closeDataChannel("closeDC", closeDataChannelContinuation); | ||
} | ||
function closeDataChannelContinuation() { | ||
expect(dataChannel.close).toHaveBeenCalled(); | ||
done(); | ||
} | ||
}); | ||
it("Fires onClose when closed", function(done) { | ||
var rtcpc = RTCPeerConnection.mostRecent; | ||
var dataChannel; | ||
peerconnection.openDataChannel("oncloseDC", openDataChannelContinuation); | ||
function openDataChannelContinuation() { | ||
dataChannel = RTCDataChannel.mostRecent; | ||
expect(dataChannel.onclose).toEqual(jasmine.any(Function)); | ||
dataChannel.onclose(); | ||
expect(dispatchedEvents.onCloseDataChannel).toBeDefined(); | ||
done(); | ||
} | ||
}); | ||
it("Sends message", function(done) { | ||
var rtcpc = RTCPeerConnection.mostRecent; | ||
var dataChannel; | ||
var sendInfo = {channelLabel: "sendDC", | ||
text: "Hello World"}; | ||
peerconnection.openDataChannel("sendDC", openDataChannelContinuation); | ||
function openDataChannelContinuation() { | ||
dataChannel = RTCDataChannel.mostRecent; | ||
expect(dataChannel).toBeDefined(); | ||
spyOn(dataChannel, "send"); | ||
peerconnection.send(sendInfo, sendContinuation); | ||
} | ||
function sendContinuation() { | ||
expect(dataChannel.send).toHaveBeenCalledWith("Hello World"); | ||
done(); | ||
} | ||
}); | ||
it("Receives messages", function(done) { | ||
var rtcpc = RTCPeerConnection.mostRecent; | ||
var dataChannel; | ||
peerconnection.openDataChannel("receiveDC", openDataChannelContinuation); | ||
function openDataChannelContinuation() { | ||
dataChannel = RTCDataChannel.mostRecent; | ||
expect(dataChannel.onmessage).toEqual(jasmine.any(Function)); | ||
dataChannel.onmessage({data: "Hello World"}); | ||
var message = dispatchedEvents.onReceived; | ||
expect(message).toBeDefined(); | ||
expect(message.channelLabel).toEqual("receiveDC"); | ||
expect(message.text).toEqual("Hello World"); | ||
done(); | ||
} | ||
}); | ||
}); |
describe("core.view", function() { | ||
var provider, app; | ||
var provider, app, el; | ||
@@ -13,9 +13,15 @@ beforeEach(function() { | ||
provider = new View_unprivileged(app); | ||
el = document.createElement('div'); | ||
el.id = 'myview'; | ||
document.body.appendChild(el); | ||
}); | ||
afterEach(function() { | ||
document.body.removeChild(el); | ||
delete el; | ||
}); | ||
it("Places objects and cleans up.", function() { | ||
app.config.views['myview'] = true; | ||
var el = document.createElement('div'); | ||
el.id = 'myview'; | ||
document.body.appendChild(el); | ||
@@ -33,9 +39,10 @@ var cb = jasmine.createSpy('cb'); | ||
// TODO: Understand phantom security model better. | ||
xit("Roundtrips messages", function(done) { | ||
var onReturn = function() { | ||
expect(provider.dispatchEvent).toHaveBeenCalledWith('msg'); | ||
it("Roundtrips messages", function(done) { | ||
app.config.views['myview'] = true; | ||
provider.dispatchEvent = jasmine.createSpy('de'); | ||
provider.dispatchEvent.and.callFake(function() { | ||
expect(provider.dispatchEvent).toHaveBeenCalledWith('message', 'msg'); | ||
provider.close(done); | ||
}; | ||
provider.dispatchEvent = jasmine.createSpy('cb'); | ||
provider.dispatchEvent.and.callFake(onReturn); | ||
}); | ||
var sendMsg = function() { | ||
@@ -50,4 +57,4 @@ provider.postMessage('msg', function() {}); | ||
}; | ||
provider.open('myview', {'code': '<script>window.addEventListener("message", function(m) {parent.postMessage(m, "*");}, true);</script>'}, onOpen); | ||
provider.open('myview', {'code': '<script>window.addEventListener("message", function(m) {m.source.postMessage(m.data, "*");}, true);</script>'}, onOpen); | ||
}); | ||
}); |
describe("unit: social.loopback.json", function () { | ||
var provider; | ||
var TIMEOUT = 1000; | ||
beforeEach(function() { | ||
// Comment for more debugging messages. | ||
spyOn(console, 'log'); | ||
freedom = { | ||
@@ -14,4 +16,3 @@ social: mockIface([], [ | ||
jasmine.clock().install(); | ||
provider = new LoopbackSocialProvider(); | ||
provider.dispatchEvent = jasmine.createSpy('dispatchEvent'); | ||
provider = new LoopbackSocialProvider(jasmine.createSpy('dispatchEvent')); | ||
}); | ||
@@ -18,0 +19,0 @@ |
describe("unit: storage.isolated.json", function () { | ||
var provider; | ||
beforeEach(function() { | ||
// Comment for log messages. | ||
spyOn(console, "log"); | ||
freedom = { | ||
@@ -5,0 +8,0 @@ core: mockIface([['getId', ['myId']]]), |
@@ -186,5 +186,7 @@ /*globals fdom:true */ | ||
} | ||
var instance = new this.providerCls(), | ||
events = {}; | ||
var events = {}, | ||
dispatchEvent, | ||
instance; | ||
fdom.util.eachProp(this.definition, function(prop, name) { | ||
@@ -195,5 +197,5 @@ if (prop.type === 'event') { | ||
}); | ||
instance.dispatchEvent = function(events, id, name, value) { | ||
if (events[name]) { | ||
dispatchEvent = function(ev, id, name, value) { | ||
if (ev[name]) { | ||
this.emit(this.emitChannel, { | ||
@@ -205,3 +207,3 @@ type: 'message', | ||
type: 'event', | ||
value: fdom.proxy.conform(events[name].value, value) | ||
value: fdom.proxy.conform(ev[name].value, value) | ||
} | ||
@@ -212,2 +214,4 @@ }); | ||
instance = new this.providerCls(dispatchEvent); | ||
return function(port, msg) { | ||
@@ -214,0 +218,0 @@ if (msg.action === 'method') { |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
4575749
765
79953
79