Use the network from the async store for pads

pull/1/head
yflory 7 years ago
parent e164edec03
commit 52712c4bb9

@ -486,7 +486,20 @@ define([
messenger.onFriendEvent = Util.mkEvent(); messenger.onFriendEvent = Util.mkEvent();
messenger.onUnfriendEvent = Util.mkEvent(); messenger.onUnfriendEvent = Util.mkEvent();
// HERE // Pad RPC
var pad = common.padRpc = {};
pad.joinPad = function (data, cb) {
postMessage("JOIN_PAD", data, cb);
};
pad.sendPadMsg = function (data, cb) {
postMessage("SEND_PAD_MSG", data, cb);
};
pad.onReadyEvent = Util.mkEvent();
pad.onMessageEvent = Util.mkEvent();
pad.onJoinEvent = Util.mkEvent();
pad.onLeaveEvent = Util.mkEvent();
pad.onDisconnectEvent = Util.mkEvent();
common.getShareHashes = function (secret, cb) { common.getShareHashes = function (secret, cb) {
var hashes; var hashes;
if (!window.location.hash) { if (!window.location.hash) {
@ -597,6 +610,22 @@ define([
case 'CONTACTS_UNFRIEND': { case 'CONTACTS_UNFRIEND': {
common.messenger.onUnfriendEvent.fire(data); break; common.messenger.onUnfriendEvent.fire(data); break;
} }
// Pad
case 'PAD_READY': {
common.padRpc.onReadyEvent.fire(); break;
}
case 'PAD_MESSAGE': {
common.padRpc.onMessageEvent.fire(data); break;
}
case 'PAD_JOIN': {
common.padRpc.onJoinEvent.fire(data); break;
}
case 'PAD_LEAVE': {
common.padRpc.onLeaveEvent.fire(data); break;
}
case 'PAD_DISCONNECT': {
common.padRpc.onDisconnectEvent.fire(data); break;
}
} }
}; };

@ -8,13 +8,14 @@ define([
'/common/common-realtime.js', '/common/common-realtime.js',
'/common/common-messaging.js', '/common/common-messaging.js',
'/common/common-messenger.js', '/common/common-messenger.js',
'/common/outer/chainpad-netflux-worker.js',
'/common/outer/network-config.js', '/common/outer/network-config.js',
'/bower_components/chainpad-crypto/crypto.js?v=0.1.5', '/bower_components/chainpad-crypto/crypto.js?v=0.1.5',
'/bower_components/chainpad/chainpad.dist.js', '/bower_components/chainpad/chainpad.dist.js',
'/bower_components/chainpad-listmap/chainpad-listmap.js', '/bower_components/chainpad-listmap/chainpad-listmap.js',
], function (UserObject, Migrate, Hash, Util, Constants, Feedback, Realtime, Messaging, Messenger, ], function (UserObject, Migrate, Hash, Util, Constants, Feedback, Realtime, Messaging, Messenger,
NetConfig, CpNfWorker, NetConfig,
Crypto, ChainPad, Listmap) { Crypto, ChainPad, Listmap) {
var Store = {}; var Store = {};
@ -95,7 +96,6 @@ define([
var getCanonicalChannelList = function () { var getCanonicalChannelList = function () {
return Util.deduplicateString(getUserChannelList()).sort(); return Util.deduplicateString(getUserChannelList()).sort();
}; };
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
/////////////////////// RPC ////////////////////////////////////// /////////////////////// RPC //////////////////////////////////////
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
@ -715,6 +715,66 @@ define([
} }
}; };
//////////////////////////////////////////////////////////////////
/////////////////////// PAD //////////////////////////////////////
//////////////////////////////////////////////////////////////////
// TODO with sharedworker
// channel will be an object storing the webchannel associated to each browser tab
var channel = {
queue: []
};
Store.joinPad = function (data, cb) {
var conf = {
onReady: function () {
postMessage("PAD_READY");
}, // post EV_PAD_READY
onMessage: function (m) {
postMessage("PAD_MESSAGE", m);
}, // post EV_PAD_MESSAGE
onJoin: function (m) {
postMessage("PAD_JOIN", m);
}, // post EV_PAD_JOIN
onLeave: function (m) {
postMessage("PAD_LEAVE", m);
}, // post EV_PAD_LEAVE
onDisconnect: function () {
postMessage("PAD_DISCONNECT");
}, // post EV_PAD_DISCONNECT
channel: data.channel,
validateKey: data.validateKey,
network: store.network,
readOnly: data.readOnly,
onConnect: function (wc, sendMessage) {
channel.sendMessage = sendMessage;
channel.wc = wc;
channel.queue.forEach(function (data) {
sendMessage(data.message);
});
cb({
myID: wc.myID,
id: wc.id,
members: wc.members
});
}
};
CpNfWorker.start(conf);
};
Store.sendPadMsg = function (data, cb) {
if (!channel.wc) { channel.queue.push(data); }
channel.sendMessage(data, cb);
};
// TODO
// GET_FULL_HISTORY from sframe-common-outer
// TODO with sharedworker
// when the tab is closed, leave the pad
//////////////////////////////////////////////////////////////////
/////////////////////// Init /////////////////////////////////////
//////////////////////////////////////////////////////////////////
var onReady = function (returned, cb) { var onReady = function (returned, cb) {
var proxy = store.proxy; var proxy = store.proxy;
var userObject = store.userObject = UserObject.init(proxy.drive, { var userObject = store.userObject = UserObject.init(proxy.drive, {
@ -815,6 +875,7 @@ define([
store.proxy = rt.proxy; store.proxy = rt.proxy;
store.loggedIn = typeof(data.userHash) !== "undefined"; store.loggedIn = typeof(data.userHash) !== "undefined";
var returned = {};
rt.proxy.on('create', function (info) { rt.proxy.on('create', function (info) {
store.realtime = info.realtime; store.realtime = info.realtime;
store.network = info.network; store.network = info.network;

@ -146,6 +146,13 @@ define([
case 'CONTACTS_SET_CHANNEL_HEAD': { case 'CONTACTS_SET_CHANNEL_HEAD': {
Store.messenger.setChannelHead(data, cb); break; Store.messenger.setChannelHead(data, cb); break;
} }
// Pad
case 'SEND_PAD_MSG': {
Store.sendPadMsg(data, cb); break;
}
case 'JOIN_PAD': {
Store.joinPad(data, cb); break;
}
default: { default: {
break; break;

@ -1,3 +1,5 @@
/* jshint ignore:start */
var window = self; var window = self;
importScripts('/bower_components/requirejs/require.js'); importScripts('/bower_components/requirejs/require.js');

@ -27,32 +27,17 @@ define([], function () {
var Crypto = conf.crypto; var Crypto = conf.crypto;
var validateKey = conf.validateKey; var validateKey = conf.validateKey;
var readOnly = conf.readOnly || false; var readOnly = conf.readOnly || false;
var network = conf.network; var padRpc = conf.padRpc;
var sframeChan = conf.sframeChan; var sframeChan = conf.sframeChan;
var onConnect = conf.onConnect || function () { }; var onConnect = conf.onConnect || function () { };
conf = undefined; conf = undefined;
var initializing = true; padRpc.onReadyEvent.reg(function () {
var lastKnownHash;
var queue = [];
var messageFromInner = function (m, cb) { queue.push([ m, cb ]); };
sframeChan.on('Q_RT_MESSAGE', function (message, cb) {
messageFromInner(message, cb);
});
var onReady = function () {
// Trigger onReady only if not ready yet. This is important because the history keeper sends a direct
// message through "network" when it is synced, and it triggers onReady for each channel joined.
if (!initializing) { return; }
sframeChan.event('EV_RT_READY', null); sframeChan.event('EV_RT_READY', null);
// we're fully synced });
initializing = false;
};
// shim between chainpad and netflux // shim between chainpad and netflux
var msgIn = function (peerId, msg) { var msgIn = function (msg) {
msg = msg.replace(/^cp\|/, '');
try { try {
var decryptedMsg = Crypto.decrypt(msg, validateKey); var decryptedMsg = Crypto.decrypt(msg, validateKey);
return decryptedMsg; return decryptedMsg;
@ -74,44 +59,14 @@ define([], function () {
} }
}; };
var onMessage = function(peer, msg, wc, network, direct) { sframeChan.on('Q_RT_MESSAGE', function (message, cb) {
// unpack the history keeper from the webchannel var msg = msgOut(message);
var hk = network.historyKeeper; if (!msg) { return; }
padRpc.sendPadMsg(msg, cb);
if (direct && peer !== hk) { });
return;
}
if (direct) {
var parsed = JSON.parse(msg);
if (parsed.validateKey && parsed.channel) {
if (parsed.channel === wc.id && !validateKey) {
validateKey = parsed.validateKey;
}
// We have to return even if it is not the current channel:
// we don't want to continue with other channels messages here
return;
}
if (parsed.state && parsed.state === 1 && parsed.channel) {
if (parsed.channel === wc.id) {
onReady(wc);
}
// We have to return even if it is not the current channel:
// we don't want to continue with other channels messages here
return;
}
}
// The history keeper is different for each channel :
// no need to check if the message is related to the current channel
if (peer === hk) {
// if the peer is the 'history keeper', extract their message
var parsed1 = JSON.parse(msg);
msg = parsed1[4];
// Check that this is a message for us
if (parsed1[3] !== wc.id) { return; }
}
lastKnownHash = msg.slice(0,64); var onMessage = function(msg) {
var message = msgIn(peer, msg); var message = msgIn(msg);
verbose(message); verbose(message);
@ -124,118 +79,32 @@ define([], function () {
sframeChan.query('Q_RT_MESSAGE', message, function () { }); sframeChan.query('Q_RT_MESSAGE', message, function () { });
}; };
// We use an object to store the webchannel so that we don't have to push new handlers to chainpad var onOpen = function(data) {
// and remove the old ones when reconnecting and keeping the same 'realtime' object
// See realtime.onMessage below: we call wc.bcast(...) but wc may change
var wcObject = {};
var onOpen = function(wc, network, firstConnection) {
wcObject.wc = wc;
channel = wc.id;
onConnect(wc);
onConnect = function () { };
// Add the existing peers in the userList // Add the existing peers in the userList
sframeChan.event('EV_RT_CONNECT', { myID: wc.myID, members: wc.members, readOnly: readOnly }); console.log(data);
onConnect(data.id);
// Add the handlers to the WebChannel onConnect = function () {};
wc.on('message', function (msg, sender) { //Channel msg
onMessage(sender, msg, wc, network);
});
wc.on('join', function (m) { sframeChan.event('EV_RT_JOIN', m); });
wc.on('leave', function (m) { sframeChan.event('EV_RT_LEAVE', m); });
if (firstConnection) {
// Sending a message...
messageFromInner = function(message, cb) {
// Filter messages sent by Chainpad to make it compatible with Netflux
message = msgOut(message);
if (message) {
// Do not remove wcObject, it allows us to use a new 'wc' without changing the handler if we
// want to keep the same chainpad (realtime) object
try {
if (window.Cryptpad_SUPPRESS_MSG) { return; }
wcObject.wc.bcast(message).then(function() {
if (window.Cryptpad_SUPPRESS_ACK) { return; }
cb();
}, function(err) {
// The message has not been sent, display the error.
console.error(err);
});
} catch (e) {
console.log(e);
// Just skip calling back and it will fail on the inside.
}
}
};
queue.forEach(function (arr) { messageFromInner(arr[0], arr[1]); });
}
// Get the channel history
if (USE_HISTORY) {
var hk;
wc.members.forEach(function (p) {
if (p.length === 16) { hk = p; }
});
network.historyKeeper = hk;
var msg = ['GET_HISTORY', wc.id];
// Add the validateKey if we are the channel creator and we have a validateKey
msg.push(validateKey);
msg.push(lastKnownHash);
if (hk) { network.sendto(hk, JSON.stringify(msg)); }
} else {
onReady(wc);
}
};
var isIntentionallyLeaving = false;
window.addEventListener("beforeunload", function () {
isIntentionallyLeaving = true;
});
var findChannelById = function (webChannels, channelId) { sframeChan.event('EV_RT_CONNECT', { myID: data.myID, members: data.members, readOnly: readOnly });
var webChannel;
// Array.some terminates once a truthy value is returned // Add the handlers to the WebChannel
// best case is faster than forEach, though webchannel arrays seem padRpc.onMessageEvent.reg(function (msg) { onMessage(msg); });
// to consistently have a length of 1 padRpc.onJoinEvent.reg(function (m) { sframeChan.event('EV_RT_JOIN', m); });
webChannels.some(function(chan) { padRpc.onLeaveEvent.reg(function (m) { sframeChan.event('EV_RT_LEAVE', m); });
if(chan.id === channelId) { webChannel = chan; return true;}
});
return webChannel;
};
var connectTo = function (network, firstConnection) {
// join the netflux network, promise to handle opening of the channel
network.join(channel || null).then(function(wc) {
onOpen(wc, network, firstConnection);
}, function(error) {
console.error(error);
});
}; };
network.on('disconnect', function (reason) { padRpc.onDisconnectEvent.reg(function () {
console.log('disconnect');
if (isIntentionallyLeaving) { return; }
if (reason === "network.disconnect() called") { return; }
sframeChan.event('EV_RT_DISCONNECT'); sframeChan.event('EV_RT_DISCONNECT');
}); });
network.on('reconnect', function () { // join the netflux network, promise to handle opening of the channel
initializing = true; padRpc.joinPad({
connectTo(network, false); channel: channel || null,
}); validateKey: validateKey,
readOnly: readOnly
network.on('message', function (msg, sender) { // Direct message }, function(data) {
var wchan = findChannelById(network.webChannels, channel); onOpen(data);
if (wchan) {
onMessage(sender, msg, wchan, network, true);
}
}); });
connectTo(network, true);
}; };
return { return {

@ -581,7 +581,7 @@ define([
CpNfOuter.start({ CpNfOuter.start({
sframeChan: sframeChan, sframeChan: sframeChan,
channel: secret.channel, channel: secret.channel,
network: cfg.newNetwork || network, padRpc: Cryptpad.padRpc,
validateKey: secret.keys.validateKey || undefined, validateKey: secret.keys.validateKey || undefined,
readOnly: readOnly, readOnly: readOnly,
crypto: Crypto.createEncryptor(secret.keys), crypto: Crypto.createEncryptor(secret.keys),

@ -16,8 +16,8 @@ define([
Cryptpad, Cryptpad,
nThen, nThen,
SFCommon, SFCommon,
UI, UI
Messages /*Messages*/
) )
{ {
var APP = window.APP = {}; var APP = window.APP = {};
@ -31,7 +31,6 @@ define([
sFrameChan = common.getSframeChannel(); sFrameChan = common.getSframeChannel();
sFrameChan.onReady(waitFor()); sFrameChan.onReady(waitFor());
}).nThen(function (/*waitFor*/) { }).nThen(function (/*waitFor*/) {
var $body = $('body');
var $container = $('#cp-app-worker-container'); var $container = $('#cp-app-worker-container');
var $bar = $('.cp-toolbar-container'); var $bar = $('.cp-toolbar-container');

@ -1,3 +1,5 @@
/* jshint ignore:start */
var window = self; var window = self;
var localStorage = { var localStorage = {
setItem: function (k, v) { localStorage[k] = v; }, setItem: function (k, v) { localStorage[k] = v; },

Loading…
Cancel
Save