cryptpad/www/common/sframe-common.js

412 lines
14 KiB
JavaScript
Raw Normal View History

2017-08-17 22:28:54 +08:00
define([
2017-08-23 17:04:44 +08:00
'jquery',
2017-08-17 22:56:18 +08:00
'/bower_components/nthen/index.js',
2017-08-21 21:20:38 +08:00
'/customize/messages.js',
2017-08-17 22:28:54 +08:00
'/common/sframe-chainpad-netflux-inner.js',
2017-08-18 00:28:05 +08:00
'/common/sframe-channel.js',
'/common/sframe-common-title.js',
2017-11-10 01:17:49 +08:00
'/common/common-ui-elements.js',
2017-08-21 23:40:21 +08:00
'/common/sframe-common-history.js',
'/common/sframe-common-file.js',
2017-09-08 00:56:58 +08:00
'/common/sframe-common-codemirror.js',
'/common/metadata-manager.js',
2017-08-18 00:28:05 +08:00
2017-08-22 00:30:51 +08:00
'/customize/application_config.js',
'/common/common-realtime.js',
'/common/common-util.js',
2017-11-13 23:32:40 +08:00
'/common/common-hash.js',
2017-11-07 21:51:53 +08:00
'/common/common-thumbnail.js',
'/common/common-interface.js',
2017-11-23 19:28:49 +08:00
'/common/common-feedback.js',
2017-12-07 19:20:26 +08:00
'/common/common-language.js',
2017-11-07 21:51:53 +08:00
'/bower_components/localforage/dist/localforage.min.js'
2017-09-11 21:52:14 +08:00
], function (
$,
nThen,
Messages,
CpNfInner,
SFrameChannel,
Title,
UIElements,
2017-09-11 21:52:14 +08:00
History,
File,
CodeMirror,
2017-09-08 00:56:58 +08:00
MetadataMgr,
2017-09-11 21:52:14 +08:00
AppConfig,
CommonRealtime,
Util,
2017-11-13 23:32:40 +08:00
Hash,
2017-11-07 21:51:53 +08:00
Thumb,
UI,
2017-11-23 19:28:49 +08:00
Feedback,
2017-12-07 19:20:26 +08:00
Language,
2017-11-07 21:51:53 +08:00
localForage
2017-09-11 21:52:14 +08:00
) {
2017-08-17 22:28:54 +08:00
// Chainpad Netflux Inner
2017-08-17 22:56:18 +08:00
var funcs = {};
var ctx = {};
2017-08-21 23:40:21 +08:00
funcs.Messages = Messages;
var evRealtimeSynced = Util.mkEvent(true);
2017-08-17 22:56:18 +08:00
funcs.startRealtime = function (options) {
if (ctx.cpNfInner) { return ctx.cpNfInner; }
options.sframeChan = ctx.sframeChan;
options.metadataMgr = ctx.metadataMgr;
2017-08-17 22:56:18 +08:00
ctx.cpNfInner = CpNfInner.start(options);
ctx.cpNfInner.metadataMgr.onChangeLazy(options.onLocal);
ctx.cpNfInner.whenRealtimeSyncs(function () { evRealtimeSynced.fire(); });
2017-08-17 22:56:18 +08:00
return ctx.cpNfInner;
};
2017-09-07 00:26:10 +08:00
funcs.getMetadataMgr = function () { return ctx.metadataMgr; };
funcs.getSframeChannel = function () { return ctx.sframeChan; };
funcs.getAppConfig = function () { return AppConfig; };
2017-08-21 23:40:21 +08:00
2017-09-08 00:56:58 +08:00
funcs.isLoggedIn = function () {
2017-09-13 00:40:11 +08:00
return ctx.metadataMgr.getPrivateData().accountName;
2017-08-17 22:28:54 +08:00
};
2017-09-07 00:26:10 +08:00
// MISC
// Call the selected function with 'funcs' as a (new) first parameter
var callWithCommon = function (f) {
return function () {
[].unshift.call(arguments, funcs);
return f.apply(null, arguments);
};
};
// UI
funcs.createUserAdminMenu = callWithCommon(UIElements.createUserAdminMenu);
funcs.initFilePicker = callWithCommon(UIElements.initFilePicker);
funcs.openFilePicker = callWithCommon(UIElements.openFilePicker);
funcs.openTemplatePicker = callWithCommon(UIElements.openTemplatePicker);
funcs.displayMediatagImage = callWithCommon(UIElements.displayMediatagImage);
funcs.displayAvatar = callWithCommon(UIElements.displayAvatar);
funcs.createButton = callWithCommon(UIElements.createButton);
funcs.createUsageBar = callWithCommon(UIElements.createUsageBar);
funcs.updateTags = callWithCommon(UIElements.updateTags);
funcs.createLanguageSelector = callWithCommon(UIElements.createLanguageSelector);
funcs.createMarkdownToolbar = callWithCommon(UIElements.createMarkdownToolbar);
2017-12-08 01:51:50 +08:00
funcs.getPadCreationScreen = callWithCommon(UIElements.getPadCreationScreen);
2018-01-12 16:48:40 +08:00
funcs.createNewPadModal = callWithCommon(UIElements.createNewPadModal);
// Thumb
2017-11-07 21:51:53 +08:00
funcs.displayThumbnail = callWithCommon(Thumb.displayThumbnail);
2017-08-21 23:40:21 +08:00
// History
2017-09-07 00:26:10 +08:00
funcs.getHistory = callWithCommon(History.create);
2017-08-21 23:40:21 +08:00
2017-08-18 00:28:05 +08:00
// Title module
2017-09-07 00:26:10 +08:00
funcs.createTitle = callWithCommon(Title.create);
// Files
funcs.uploadFile = callWithCommon(File.uploadFile);
funcs.createFileManager = callWithCommon(File.create);
2017-09-13 00:40:11 +08:00
funcs.getMediatagScript = function () {
var origin = ctx.metadataMgr.getPrivateData().origin;
return '<script src="' + origin + '/common/media-tag-nacl.min.js"></script>';
};
funcs.getMediatagFromHref = function (href) {
2017-11-13 23:32:40 +08:00
var parsed = Hash.parsePadUrl(href);
var secret = Hash.getSecrets('file', parsed.hash);
2017-09-13 00:40:11 +08:00
var data = ctx.metadataMgr.getPrivateData();
if (secret.keys && secret.channel) {
var cryptKey = secret.keys && secret.keys.fileKeyStr;
2017-11-13 23:32:40 +08:00
var hexFileName = Util.base64ToHex(secret.channel);
2017-09-13 00:40:11 +08:00
var origin = data.fileHost || data.origin;
2017-11-13 23:32:40 +08:00
var src = origin + Hash.getBlobPathFromHex(hexFileName);
2017-09-13 00:40:11 +08:00
return '<media-tag src="' + src + '" data-crypto-key="cryptpad:' + cryptKey + '">' +
'</media-tag>';
}
return;
};
2017-09-13 22:19:26 +08:00
funcs.getFileSize = function (href, cb) {
2017-11-13 23:32:40 +08:00
var channelId = Hash.hrefToHexChannelId(href);
2017-09-13 22:19:26 +08:00
funcs.sendAnonRpcMsg("GET_FILE_SIZE", channelId, function (data) {
if (!data) { return void cb("No response"); }
if (data.error) { return void cb(data.error); }
if (data.response && data.response.length && typeof(data.response[0]) === 'number') {
return void cb(void 0, data.response[0]);
} else {
cb('INVALID_RESPONSE');
}
});
};
2017-08-18 00:28:05 +08:00
2017-09-08 00:56:58 +08:00
// CodeMirror
funcs.initCodeMirrorApp = callWithCommon(CodeMirror.create);
2017-08-18 00:28:05 +08:00
// Window
funcs.logout = function (cb) {
2017-09-07 00:26:10 +08:00
cb = cb || $.noop;
ctx.sframeChan.query('Q_LOGOUT', null, cb);
};
2017-08-29 17:20:02 +08:00
funcs.notify = function () {
ctx.sframeChan.event('EV_NOTIFY');
};
funcs.setTabTitle = function (newTitle) {
ctx.sframeChan.event('EV_SET_TAB_TITLE', newTitle);
};
2017-08-29 17:20:02 +08:00
funcs.setLoginRedirect = function (cb) {
2017-09-07 00:26:10 +08:00
cb = cb || $.noop;
ctx.sframeChan.query('Q_SET_LOGIN_REDIRECT', null, cb);
};
2017-09-08 00:56:58 +08:00
funcs.isPresentUrl = function (cb) {
ctx.sframeChan.query('Q_PRESENT_URL_GET_VALUE', null, cb);
};
funcs.setPresentUrl = function (value) {
ctx.sframeChan.event('EV_PRESENT_URL_SET_VALUE', value);
};
// Store
funcs.createPad = function (cfg, cb) {
ctx.sframeChan.query("Q_CREATE_PAD", {
owned: cfg.owned,
expire: cfg.expire,
template: cfg.template
}, cb);
};
2017-08-21 18:01:38 +08:00
funcs.sendAnonRpcMsg = function (msg, content, cb) {
ctx.sframeChan.query('Q_ANON_RPC_MESSAGE', {
msg: msg,
content: content
}, function (err, data) {
if (cb) { cb(data); }
});
};
2017-09-21 23:56:24 +08:00
funcs.getPinUsage = function (cb) {
cb = cb || $.noop;
ctx.sframeChan.query('Q_PIN_GET_USAGE', null, function (err, data) {
cb(err || data.error, data.data);
});
};
2017-08-21 18:01:38 +08:00
2017-08-21 18:24:33 +08:00
funcs.isOverPinLimit = function (cb) {
ctx.sframeChan.query('Q_GET_PIN_LIMIT_STATUS', null, function (err, data) {
cb(data.error, data.overLimit, data.limits);
});
};
2017-08-21 23:40:21 +08:00
funcs.getFullHistory = function (realtime, cb) {
ctx.sframeChan.query('Q_GET_FULL_HISTORY', null, function (err, messages) {
if (err) { return void console.error(err); }
if (!Array.isArray(messages)) { return; }
messages.forEach(function (m) {
realtime.message(m);
});
cb();
2017-08-21 23:40:21 +08:00
});
};
2017-08-31 00:47:50 +08:00
funcs.getPadAttribute = function (key, cb) {
ctx.sframeChan.query('Q_GET_PAD_ATTRIBUTE', {
key: key
}, function (err, res) {
cb (err || res.error, res.data);
});
};
funcs.setPadAttribute = function (key, value, cb) {
cb = cb || $.noop;
2017-08-31 00:47:50 +08:00
ctx.sframeChan.query('Q_SET_PAD_ATTRIBUTE', {
key: key,
value: value
}, cb);
};
funcs.getAttribute = function (key, cb) {
ctx.sframeChan.query('Q_GET_ATTRIBUTE', {
key: key
}, function (err, res) {
cb (err || res.error, res.data);
});
};
funcs.setAttribute = function (key, value, cb) {
cb = cb || $.noop;
ctx.sframeChan.query('Q_SET_ATTRIBUTE', {
key: key,
value: value
}, cb);
};
2017-11-07 21:51:53 +08:00
// Thumbnails
funcs.setThumbnail = function (key, value, cb) {
cb = cb || $.noop;
ctx.sframeChan.query('Q_THUMBNAIL_SET', {
key: key,
value: value
}, cb);
};
funcs.getThumbnail = function (key, cb) {
ctx.sframeChan.query('Q_THUMBNAIL_GET', {
key: key
}, function (err, res) {
cb (err || res.error, res.data);
});
};
2017-09-23 01:35:06 +08:00
funcs.sessionStorage = {
put: function (key, value, cb) {
ctx.sframeChan.query('Q_SESSIONSTORAGE_PUT', {
key: key,
value: value
}, cb);
}
};
2017-09-07 00:26:10 +08:00
funcs.isStrongestStored = function () {
var data = ctx.metadataMgr.getPrivateData();
2017-09-13 00:40:11 +08:00
if (data.availableHashes.fileHash) { return true; }
2017-09-07 00:26:10 +08:00
return !data.readOnly || !data.availableHashes.editHash;
2017-08-31 00:47:50 +08:00
};
2017-09-08 00:56:58 +08:00
funcs.setDisplayName = function (name, cb) {
cb = cb || $.noop;
ctx.sframeChan.query('Q_SETTINGS_SET_DISPLAY_NAME', name, cb);
};
2017-09-23 01:35:06 +08:00
funcs.mergeAnonDrive = function (cb) {
ctx.sframeChan.query('Q_MERGE_ANON_DRIVE', null, cb);
};
// Friends
var pendingFriends = [];
funcs.getPendingFriends = function () {
return pendingFriends.slice();
};
funcs.sendFriendRequest = function (netfluxId) {
ctx.sframeChan.query('Q_SEND_FRIEND_REQUEST', netfluxId, $.noop);
pendingFriends.push(netfluxId);
};
// Feedback
2017-09-07 00:26:10 +08:00
funcs.prepareFeedback = function (key) {
2017-08-23 00:18:58 +08:00
if (typeof(key) !== 'string') { return $.noop; }
2017-08-21 21:20:38 +08:00
2017-08-23 00:18:58 +08:00
var type = ctx.metadataMgr.getMetadata().type;
return function () {
2017-11-23 19:28:49 +08:00
Feedback.send((key + (type? '_' + type: '')).toUpperCase());
2017-08-23 00:18:58 +08:00
};
};
2017-08-21 21:20:38 +08:00
2017-09-07 00:26:10 +08:00
// RESTRICTED
// Filepicker app
2017-09-05 17:35:15 +08:00
funcs.getFilesList = function (types, cb) {
ctx.sframeChan.query('Q_GET_FILES_LIST', types, function (err, data) {
cb(err || data.error, data.data);
});
};
2017-08-19 00:43:04 +08:00
/* funcs.storeLinkToClipboard = function (readOnly, cb) {
ctx.sframeChan.query('Q_STORE_LINK_TO_CLIPBOARD', readOnly, function (err) {
if (cb) { cb(err); }
});
2017-09-07 00:26:10 +08:00
}; */
2017-08-30 23:57:10 +08:00
funcs.gotoURL = function (url) { ctx.sframeChan.event('EV_GOTO_URL', url); };
2017-09-23 01:35:06 +08:00
funcs.openURL = function (url) { ctx.sframeChan.event('EV_OPEN_URL', url); };
funcs.openUnsafeURL = function (url) {
var bounceHref = window.location.origin + '/bounce/#' + encodeURIComponent(url);
window.open(bounceHref);
};
funcs.whenRealtimeSyncs = evRealtimeSynced.reg;
var logoutHandlers = [];
funcs.onLogout = function (h) {
if (typeof (h) !== "function") { return; }
if (logoutHandlers.indexOf(h) !== -1) { return; }
logoutHandlers.push(h);
};
2017-08-17 22:56:18 +08:00
Object.freeze(funcs);
return { create: function (cb) {
// TODO(cjd): This is crap but this gets loaded multiple places by /code/ and it is
// not ok with being loaded more than once.
if (window.CryptPad_sframe_common) {
setTimeout(function () { cb(window.CryptPad_sframe_common); });
return;
}
window.CryptPad_sframe_common = funcs;
2017-08-17 22:56:18 +08:00
nThen(function (waitFor) {
2017-09-06 16:56:27 +08:00
SFrameChannel.create(window.parent, waitFor(function (sfc) { ctx.sframeChan = sfc; }), true);
2017-08-17 22:56:18 +08:00
// CpNfInner.start() should be here....
2017-12-01 00:21:58 +08:00
}).nThen(function (waitFor) {
2017-11-07 21:51:53 +08:00
localForage.clear();
2017-12-07 19:20:26 +08:00
Language.applyTranslation();
2017-11-07 21:51:53 +08:00
ctx.metadataMgr = MetadataMgr.create(ctx.sframeChan);
ctx.sframeChan.whenReg('EV_CACHE_PUT', function () {
if (Object.keys(window.cryptpadCache.updated).length) {
ctx.sframeChan.event('EV_CACHE_PUT', window.cryptpadCache.updated);
}
window.cryptpadCache._put = window.cryptpadCache.put;
window.cryptpadCache.put = function (k, v, cb) {
window.cryptpadCache._put(k, v, cb);
var x = {};
x[k] = v;
ctx.sframeChan.event('EV_CACHE_PUT', x);
};
});
2017-09-21 23:56:24 +08:00
ctx.sframeChan.whenReg('EV_LOCALSTORE_PUT', function () {
if (Object.keys(window.cryptpadStore.updated).length) {
ctx.sframeChan.event('EV_LOCALSTORE_PUT', window.cryptpadStore.updated);
}
window.cryptpadStore._put = window.cryptpadStore.put;
window.cryptpadStore.put = function (k, v, cb) {
window.cryptpadStore._put(k, v, cb);
var x = {};
x[k] = v;
ctx.sframeChan.event('EV_LOCALSTORE_PUT', x);
};
});
UI.addTooltips();
ctx.sframeChan.on('EV_LOGOUT', function () {
$(window).on('keyup', function (e) {
if (e.keyCode === 27) {
UI.removeLoadingScreen();
}
});
UI.addLoadingScreen({hideTips: true});
UI.errorLoadingScreen(Messages.onLogout, true);
logoutHandlers.forEach(function (h) {
if (typeof (h) === "function") { h(); }
});
});
ctx.sframeChan.on('Q_INCOMING_FRIEND_REQUEST', function (confirmMsg, cb) {
UI.confirm(confirmMsg, cb, null, true);
});
ctx.sframeChan.on('EV_FRIEND_REQUEST', function (data) {
var i = pendingFriends.indexOf(data.netfluxId);
if (i !== -1) { pendingFriends.splice(i, 1); }
UI.log(data.logText);
});
2017-11-23 19:28:49 +08:00
ctx.metadataMgr.onChange(function () {
try {
var feedback = ctx.metadataMgr.getPrivateData().feedbackAllowed;
Feedback.init(feedback);
} catch (e) { Feedback.init(false); }
});
2017-12-01 00:21:58 +08:00
ctx.metadataMgr.onReady(waitFor());
}).nThen(function () {
ctx.sframeChan.ready();
2017-08-17 22:56:18 +08:00
cb(funcs);
});
} };
2017-08-17 22:28:54 +08:00
});