this.source.postMessage("hello", this.expectedOrigin);
return;
}
this._incoming(event.data);
},
close: function () {
this.closed = true;
window.removeEventListener("message", this._receiveMessage, false);
if (this._pingTimeout) {
clearTimeout(this._pingTimeout);
}
if (this.onclose) {
this.onclose();
}
this.emit("close");
}
});
channels.Router = util.Class(util.mixinEvents({
constructor: function (channel) {
this._channelMessage = this._channelMessage.bind(this);
this._channelClosed = this._channelClosed.bind(this);
this._routes = Object.create(null);
if (channel) {
this.bindChannel(channel);
}
},
bindChannel: function (channel) {
if (this.channel) {
this.channel.removeListener("message", this._channelMessage);
this.channel.removeListener("close", this._channelClosed);
}
this.channel = channel;
this.channel.on("message", this._channelMessage.bind(this));
this.channel.on("close", this._channelClosed.bind(this));
},
_channelMessage: function (msg) {
if (msg.type == "route") {
var id = msg.routeId;
var route = this._routes[id];
if (! route) {
console.warn("No route with the id", id);
return;
}
if (msg.close) {
this._closeRoute(route.id);
} else {
if (route.onmessage) {
route.onmessage(msg.message);
}
route.emit("message", msg.message);
}
}
},
_channelClosed: function () {
for (var id in this._routes) {
this._closeRoute(id);
}
},
_closeRoute: function (id) {
var route = this._routes[id];
if (route.onclose) {
route.onclose();
}
route.emit("close");
delete this._routes[id];
},
makeRoute: function (id) {
id = id || util.generateId();
var route = Route(this, id);
this._routes[id] = route;
return route;
}
}));
var Route = util.Class(util.mixinEvents({
constructor: function (router, id) {
this.router = router;
this.id = id;
},
send: function (msg) {
this.router.channel.send({
type: "route",
routeId: this.id,
message: msg
});
},
close: function () {
if (this.router._routes[this.id] !== this) {