You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cryptpad/www/common/cryptpad-common.js

923 lines
32 KiB
JavaScript

define([
'/api/config',
'/customize/messages.js',
'/common/common-util.js',
8 years ago
'/common/common-hash.js',
'/common/common-messaging.js',
'/common/common-constants.js',
'/common/common-feedback.js',
'/common/outer/local-store.js',
'/common/outer/store-rpc.js',
'/customize/application_config.js',
'/bower_components/nthen/index.js',
], function (Config, Messages, Util, Hash,
Messaging, Constants, Feedback, LocalStore, AStore,
AppConfig, Nthen) {
/* This file exposes functionality which is specific to Cryptpad, but not to
any particular pad type. This includes functions for committing metadata
about pads to your local storage for future use and improved usability.
Additionally, there is some basic functionality for import/export.
*/
var postMessage = function (cmd, data, cb) {
setTimeout(function () {
AStore.query(cmd, data, cb);
});
};
var tryParsing = function (x) {
try { return JSON.parse(x); }
catch (e) {
console.error(e);
return null;
}
};
var origin = encodeURIComponent(window.location.hostname);
var common = window.Cryptpad = {
8 years ago
Messages: Messages,
donateURL: 'https://accounts.cryptpad.fr/#/donate?on=' + origin,
upgradeURL: 'https://accounts.cryptpad.fr/#/?on=' + origin,
account: {},
};
var PINNING_ENABLED = AppConfig.enablePinning;
// COMMON
common.getLanguage = function () {
return Messages._languageUsed;
};
common.setLanguage = function (l, cb) {
var LS_LANG = "CRYPTPAD_LANG";
localStorage.setItem(LS_LANG, l);
cb();
};
// RESTRICTED
// Settings only
common.resetDrive = function (cb) {
postMessage("RESET_DRIVE", null, function (obj) {
if (obj.error) { return void cb(obj.error); }
cb();
});
};
common.logoutFromAll = function (cb) {
var token = Math.floor(Math.random()*Number.MAX_SAFE_INTEGER);
localStorage.setItem(Constants.tokenKey, token);
postMessage("SET", {
key: [Constants.tokenKey],
value: token
}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb();
});
};
// Settings and drive and auth
common.getUserObject = function (cb) {
postMessage("GET", [], function (obj) {
cb(obj);
});
};
// Settings and ready
common.mergeAnonDrive = function (cb) {
var data = {
anonHash: LocalStore.getFSHash()
};
postMessage("MIGRATE_ANON_DRIVE", data, cb);
};
// Settings
common.deleteAccount = function (cb) {
postMessage("DELETE_ACCOUNT", null, cb);
};
// Drive
common.userObjectCommand = function (data, cb) {
postMessage("DRIVE_USEROBJECT", data, cb);
};
common.drive = {};
common.drive.onLog = Util.mkEvent();
common.drive.onChange = Util.mkEvent();
common.drive.onRemove = Util.mkEvent();
// Profile
common.getProfileEditUrl = function (cb) {
postMessage("GET", ['profile', 'edit'], function (obj) {
cb(obj);
});
};
common.setNewProfile = function (profile) {
postMessage("SET", {
key: ['profile'],
value: profile
}, function () {});
};
7 years ago
common.setAvatar = function (data, cb) {
var postData = {
key: ['profile', 'avatar']
};
// If we don't have "data", it means we want to remove the avatar and we should not have a
// "postData.value", even set to undefined (JSON.stringify transforms undefined to null)
if (data) { postData.value = data; }
postMessage("SET", postData, cb);
};
// Todo
common.getTodoHash = function (cb) {
postMessage("GET", ['todo'], function (obj) {
cb(obj);
});
};
common.setTodoHash = function (hash) {
postMessage("SET", {
key: ['todo'],
value: hash
}, function () {});
};
// RPC
common.pinPads = function (pads, cb) {
postMessage("PIN_PADS", pads, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj.hash);
});
};
common.unpinPads = function (pads, cb) {
postMessage("UNPIN_PADS", pads, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj.hash);
});
};
common.getPinnedUsage = function (cb) {
postMessage("GET_PINNED_USAGE", null, function (obj) {
if (obj.error) { return void cb(obj.error); }
cb(null, obj.bytes);
});
};
common.updatePinLimit = function (cb) {
postMessage("UPDATE_PIN_LIMIT", null, function (obj) {
if (obj.error) { return void cb(obj.error); }
cb(undefined, obj.limit, obj.plan, obj.note);
});
};
common.getPinLimit = function (cb) {
postMessage("GET_PIN_LIMIT", null, function (obj) {
if (obj.error) { return void cb(obj.error); }
cb(undefined, obj.limit, obj.plan, obj.note);
});
};
common.isOverPinLimit = function (cb) {
if (!LocalStore.isLoggedIn()) { return void cb(null, false); }
var usage;
var andThen = function (e, limit, plan) {
if (e) { return void cb(e); }
var data = {usage: usage, limit: limit, plan: plan};
if (usage > limit) {
return void cb (null, true, data);
}
return void cb (null, false, data);
};
var todo = function (e, used) {
if (e) { return void cb(e); }
usage = used;
common.getPinLimit(andThen);
};
common.getPinnedUsage(todo);
};
common.clearOwnedChannel = function (channel, cb) {
postMessage("CLEAR_OWNED_CHANNEL", channel, cb);
};
common.removeOwnedChannel = function (channel, cb) {
postMessage("REMOVE_OWNED_CHANNEL", channel, cb);
};
common.getDeletedPads = function (cb) {
postMessage("GET_DELETED_PADS", null, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
common.uploadComplete = function (cb) {
postMessage("UPLOAD_COMPLETE", null, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
common.uploadStatus = function (size, cb) {
postMessage("UPLOAD_STATUS", {size: size}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
common.uploadCancel = function (cb) {
postMessage("UPLOAD_CANCEL", null, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
common.uploadChunk = function (data, cb) {
postMessage("UPLOAD_CHUNK", {chunk: data}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
// ANON RPC
// SFRAME: talk to anon_rpc from the iframe
common.anonRpcMsg = function (msg, data, cb) {
if (!msg) { return; }
postMessage("ANON_RPC_MESSAGE", {
msg: msg,
data: data
}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
common.getFileSize = function (href, password, cb) {
postMessage("GET_FILE_SIZE", {href: href, password: password}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(undefined, obj.size);
});
};
common.getMultipleFileSize = function (files, cb) {
postMessage("GET_MULTIPLE_FILE_SIZE", {files:files}, function (obj) {
if (obj.error) { return void cb(obj.error); }
cb(undefined, obj.size);
});
};
common.isNewChannel = function (href, password, cb) {
postMessage('IS_NEW_CHANNEL', {href: href, password: password}, function (obj) {
if (obj.error) { return void cb(obj.error); }
if (!obj) { return void cb('INVALID_RESPONSE'); }
cb(undefined, obj.isNew);
});
};
// Store
common.getMetadata = function (cb) {
postMessage("GET_METADATA", null, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
common.setDisplayName = function (value, cb) {
postMessage("SET_DISPLAY_NAME", value, cb);
};
common.setPadAttribute = function (attr, value, cb, href) {
cb = cb || function () {};
href = Hash.getRelativeHref(href || window.location.href);
postMessage("SET_PAD_ATTRIBUTE", {
href: href,
attr: attr,
value: value
}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb();
});
};
common.getPadAttribute = function (attr, cb, href) {
href = Hash.getRelativeHref(href || window.location.href);
postMessage("GET_PAD_ATTRIBUTE", {
href: href,
attr: attr,
}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
common.setAttribute = function (attr, value, cb) {
cb = cb || function () {};
postMessage("SET_ATTRIBUTE", {
attr: attr,
value: value
}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb();
});
};
common.getAttribute = function (attr, cb) {
postMessage("GET_ATTRIBUTE", {
attr: attr
}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(null, obj);
});
};
// Tags
common.resetTags = function (href, tags, cb) {
// set pad attribute
7 years ago
cb = cb || function () {};
if (!Array.isArray(tags)) { return void cb('INVALID_TAGS'); }
common.setPadAttribute('tags', tags.slice(), cb, href);
};
common.tagPad = function (href, tag, cb) {
if (typeof(cb) !== 'function') {
return void console.error('EXPECTED_CALLBACK');
}
if (typeof(tag) !== 'string') { return void cb('INVALID_TAG'); }
common.getPadAttribute('tags', function (e, tags) {
if (e) { return void cb(e); }
var newTags;
if (!tags) {
newTags = [tag];
} else if (tags.indexOf(tag) === -1) {
newTags = tags.slice();
newTags.push(tag);
}
common.setPadAttribute('tags', newTags, cb, href);
}, href);
};
common.untagPad = function (href, tag, cb) {
if (typeof(cb) !== 'function') {
return void console.error('EXPECTED_CALLBACK');
}
if (typeof(tag) !== 'string') { return void cb('INVALID_TAG'); }
common.getPadAttribute('tags', function (e, tags) {
if (e) { return void cb(e); }
if (!tags) { return void cb(); }
var idx = tags.indexOf(tag);
if (idx === -1) { return void cb(); }
var newTags = tags.slice();
newTags.splice(idx, 1);
common.setPadAttribute('tags', newTags, cb, href);
}, href);
};
common.getPadTags = function (href, cb) {
if (typeof(cb) !== 'function') { return; }
common.getPadAttribute('tags', function (e, tags) {
if (e) { return void cb(e); }
cb(void 0, tags ? tags.slice() : []);
}, href);
};
common.listAllTags = function (cb) {
postMessage("LIST_ALL_TAGS", null, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb(void 0, obj);
});
};
// STORAGE - TEMPLATES
common.listTemplates = function (type, cb) {
postMessage("GET_TEMPLATES", null, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
if (!Array.isArray(obj)) { return void cb ('NOT_AN_ARRAY'); }
if (!type) { return void cb(null, obj); }
var templates = obj.filter(function (f) {
// Password not needed here since we don't access hashData
var parsed = Hash.parsePadUrl(f.href);
return parsed.type === type;
});
cb(null, templates);
});
};
common.saveAsTemplate = function (Cryptput, data, cb) {
// Password not needed here since we don't access hashData
var p = Hash.parsePadUrl(window.location.href);
if (!p.type) { return; }
// XXX PPP
var hash = Hash.createRandomHash(p.type);
var href = '/' + p.type + '/#' + hash;
// XXX PPP
Cryptput(hash, data.toSave, function (e) {
if (e) { throw new Error(e); }
postMessage("ADD_PAD", {
href: href,
title: data.title,
path: ['template']
}, function (obj) {
if (obj && obj.error) { return void cb(obj.error); }
cb();
});
});
};
common.isTemplate = function (href, cb) {
var rhref = Hash.getRelativeHref(href);
common.listTemplates(null, function (err, templates) {
cb(void 0, templates.some(function (t) {
return t.href === rhref;
}));
});
};
common.useTemplate = function (href, Crypt, cb, optsPut) {
// opts is used to overrides options for chainpad-netflux in cryptput
// it allows us to add owners and expiration time if it is a new file
// Password not needed here, we only need the hash and to know if
// we need to get the password
var parsed = Hash.parsePadUrl(href);
var parsed2 = Hash.parsePadUrl(window.location.href);
if(!parsed) { throw new Error("Cannot get template hash"); }
postMessage("INCREMENT_TEMPLATE_USE", href);
optsPut = optsPut || {};
var optsGet = {};
Nthen(function (waitFor) {
if (parsed.hashData && parsed.hashData.password) {
common.getPadAttribute('password', waitFor(function (err, password) {
optsGet.password = password;
}), href);
}
if (parsed2.hashData && parsed2.hashData.password) {
common.getPadAttribute('password', waitFor(function (err, password) {
optsPut.password = password;
}));
}
}).nThen(function () {
Crypt.get(parsed.hash, function (err, val) {
if (err) { throw new Error(err); }
Crypt.put(parsed2.hash, val, cb, optsPut);
}, optsGet);
});
};
// Forget button
common.moveToTrash = function (cb, href) {
href = href || window.location.href;
postMessage("MOVE_TO_TRASH", { href: href }, cb);
};
// When opening a new pad or renaming it, store the new title
common.setPadTitle = function (title, padHref, path, cb) {
var href = padHref || window.location.href;
// Password not needed here since we don't access hashData
var parsed = Hash.parsePadUrl(href);
if (!parsed.hash) { return; }
href = parsed.getUrl({present: parsed.present});
if (title === null) { return; }
if (title.trim() === "") { title = Hash.getDefaultName(parsed); }
postMessage("SET_PAD_TITLE", {
href: href,
title: title,
path: path
}, function (obj) {
if (obj && obj.error) {
console.log("unable to set pad title");
return void cb(obj.error);
}
cb();
});
};
// Needed for the secure filepicker app
common.getSecureFilesList = function (query, cb) {
postMessage("GET_SECURE_FILES_LIST", query, function (list) {
cb(void 0, list);
});
};
// Get a template href from its id
common.getPadData = function (id, cb) {
postMessage("GET_PAD_DATA", id, function (data) {
cb(void 0, data);
});
};
// Set initial path when creating a pad from pad creation screen
common.setInitialPath = function (path) {
postMessage("SET_INITIAL_PATH", path);
};
common.setNewPadPassword = function (password) {
postMessage("SET_NEW_PAD_PASSWORD", password);
};
// Messaging (manage friends from the userlist)
common.inviteFromUserlist = function (netfluxId, cb) {
postMessage("INVITE_FROM_USERLIST", {
netfluxId: netfluxId,
href: window.location.href
}, function (obj) {
7 years ago
if (obj && obj.error) { return void cb(obj.error); }
cb();
});
};
// Network
common.onNetworkDisconnect = Util.mkEvent();
common.onNetworkReconnect = Util.mkEvent();
// Messaging
var messaging = common.messaging = {};
messaging.onFriendRequest = Util.mkEvent();
messaging.onFriendComplete = Util.mkEvent();
// Messenger
var messenger = common.messenger = {};
messenger.getFriendList = function (cb) {
postMessage("CONTACTS_GET_FRIEND_LIST", null, cb);
};
messenger.getMyInfo = function (cb) {
postMessage("CONTACTS_GET_MY_INFO", null, cb);
};
messenger.getFriendInfo = function (curvePublic, cb) {
postMessage("CONTACTS_GET_FRIEND_INFO", curvePublic, cb);
};
messenger.removeFriend = function (curvePublic, cb) {
postMessage("CONTACTS_REMOVE_FRIEND", curvePublic, cb);
};
messenger.openFriendChannel = function (curvePublic, cb) {
postMessage("CONTACTS_OPEN_FRIEND_CHANNEL", curvePublic, cb);
};
messenger.getFriendStatus = function (curvePublic, cb) {
postMessage("CONTACTS_GET_FRIEND_STATUS", curvePublic, cb);
};
messenger.getMoreHistory = function (data, cb) {
postMessage("CONTACTS_GET_MORE_HISTORY", data, cb);
};
messenger.sendMessage = function (data, cb) {
postMessage("CONTACTS_SEND_MESSAGE", data, cb);
};
messenger.setChannelHead = function (data, cb) {
postMessage("CONTACTS_SET_CHANNEL_HEAD", data, cb);
7 years ago
};
messenger.onMessageEvent = Util.mkEvent();
messenger.onJoinEvent = Util.mkEvent();
messenger.onLeaveEvent = Util.mkEvent();
messenger.onUpdateEvent = Util.mkEvent();
messenger.onFriendEvent = Util.mkEvent();
messenger.onUnfriendEvent = Util.mkEvent();
// 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();
pad.onErrorEvent = Util.mkEvent();
common.getFullHistory = function (data, cb) {
postMessage("GET_FULL_HISTORY", data, cb);
};
common.getShareHashes = function (secret, cb) {
7 years ago
var hashes;
if (!window.location.hash) {
hashes = Hash.getHashes(secret);
return void cb(null, hashes);
}
// Password not needed here since only want the type
var parsed = Hash.parsePadUrl(window.location.href);
if (!parsed.type || !parsed.hashData) { return void cb('E_INVALID_HREF'); }
if (parsed.type === 'file') { secret.channel = Util.base64ToHex(secret.channel); }
hashes = Hash.getHashes(secret);
if (secret.version === 0) {
// It means we're using an old hash
hashes.editHash = window.location.hash.slice(1);
return void cb(null, hashes);
}
if (hashes.editHash) {
// no need to find stronger if we already have edit hash
return void cb(null, hashes);
}
postMessage("GET_STRONGER_HASH", {
href: window.location.href,
password: secret.password
}, function (hash) {
if (hash) { hashes.editHash = hash; }
cb(null, hashes);
});
};
var CRYPTPAD_VERSION = 'cryptpad-version';
var updateLocalVersion = function () {
// Check for CryptPad updates
var urlArgs = Config.requireConf ? Config.requireConf.urlArgs : null;
if (!urlArgs) { return; }
var arr = /ver=([0-9.]+)(-[0-9]*)?/.exec(urlArgs);
var ver = arr[1];
if (!ver) { return; }
var verArr = ver.split('.');
verArr[2] = 0;
if (verArr.length !== 3) { return; }
var stored = localStorage[CRYPTPAD_VERSION] || '0.0.0';
var storedArr = stored.split('.');
storedArr[2] = 0;
var shouldUpdate = parseInt(verArr[0]) > parseInt(storedArr[0]) ||
(parseInt(verArr[0]) === parseInt(storedArr[0]) &&
parseInt(verArr[1]) > parseInt(storedArr[1]));
if (!shouldUpdate) { return; }
localStorage[CRYPTPAD_VERSION] = ver;
};
var _onMetadataChanged = [];
common.onMetadataChanged = function (h) {
if (typeof(h) !== "function") { return; }
if (_onMetadataChanged.indexOf(h) !== -1) { return; }
_onMetadataChanged.push(h);
};
common.changeMetadata = function () {
_onMetadataChanged.forEach(function (h) { h(); });
};
var requestLogin = function () {
// log out so that you don't go into an endless loop...
LocalStore.logout();
// redirect them to log in, and come back when they're done.
sessionStorage.redirectTo = window.location.href;
window.location.href = '/login/';
};
common.startAccountDeletion = function (cb) {
// Logout other tabs
LocalStore.logout(null, true);
cb();
};
var onMessage = function (cmd, data, cb) {
cb = cb || function () {};
switch (cmd) {
case 'REQUEST_LOGIN': {
requestLogin();
break;
}
case 'UPDATE_METADATA': {
common.changeMetadata();
break;
}
case 'UPDATE_TOKEN': {
var localToken = tryParsing(localStorage.getItem(Constants.tokenKey));
if (localToken !== data.token) { requestLogin(); }
break;
}
7 years ago
case 'Q_FRIEND_REQUEST': {
common.messaging.onFriendRequest.fire(data, cb);
7 years ago
break;
}
case 'EV_FRIEND_COMPLETE': {
common.messaging.onFriendComplete.fire(data);
7 years ago
break;
}
// Network
case 'NETWORK_DISCONNECT': {
common.onNetworkDisconnect.fire(); break;
}
case 'NETWORK_RECONNECT': {
common.onNetworkReconnect.fire(data); break;
}
// Messenger
case 'CONTACTS_MESSAGE': {
common.messenger.onMessageEvent.fire(data); break;
}
case 'CONTACTS_JOIN': {
common.messenger.onJoinEvent.fire(data); break;
}
case 'CONTACTS_LEAVE': {
common.messenger.onLeaveEvent.fire(data); break;
}
case 'CONTACTS_UPDATE': {
common.messenger.onUpdateEvent.fire(data); break;
}
case 'CONTACTS_FRIEND': {
common.messenger.onFriendEvent.fire(data); break;
}
case 'CONTACTS_UNFRIEND': {
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;
}
case 'PAD_ERROR': {
common.padRpc.onErrorEvent.fire(data); break;
}
// Drive
case 'DRIVE_LOG': {
7 years ago
common.drive.onLog.fire(data); break;
}
case 'DRIVE_CHANGE': {
7 years ago
common.drive.onChange.fire(data); break;
}
case 'DRIVE_REMOVE': {
7 years ago
common.drive.onRemove.fire(data); break;
}
// Account deletion
case 'DELETE_ACCOUNT': {
common.startAccountDeletion(cb); break;
}
}
};
common.ready = (function () {
var env = {};
var initialized = false;
return function (f, rdyCfg) {
7 years ago
rdyCfg = rdyCfg || {};
if (initialized) {
return void setTimeout(function () { f(void 0, env); });
}
var provideFeedback = function () {
if (typeof(window.Proxy) === 'undefined') {
Feedback.send("NO_PROXIES");
}
var shimPattern = /CRYPTPAD_SHIM/;
if (shimPattern.test(Array.isArray.toString())) {
Feedback.send("NO_ISARRAY");
}
if (shimPattern.test(Array.prototype.fill.toString())) {
Feedback.send("NO_ARRAYFILL");
}
if (typeof(Symbol) === 'undefined') {
Feedback.send('NO_SYMBOL');
}
if (typeof(SharedWorker) === "undefined") {
Feedback.send('NO_SHAREDWORKER');
} else {
Feedback.send('SHAREDWORKER');
}
if (typeof(Worker) === "undefined") {
Feedback.send('NO_WEBWORKER');
}
if (typeof(ServiceWorker) === "undefined") {
Feedback.send('NO_SERVICEWORKER');
}
Feedback.reportScreenDimensions();
Feedback.reportLanguage();
};
var initFeedback = function (feedback) {
// Initialize feedback
Feedback.init(feedback);
provideFeedback();
};
8 years ago
Nthen(function (waitFor) {
if (AppConfig.beforeLogin) {
AppConfig.beforeLogin(LocalStore.isLoggedIn(), waitFor());
}
}).nThen(function (waitFor) {
var cfg = {
query: onMessage, // TODO temporary, will be replaced by a webworker channel
userHash: LocalStore.getUserHash(),
anonHash: LocalStore.getFSHash(),
localToken: tryParsing(localStorage.getItem(Constants.tokenKey)),
language: common.getLanguage(),
messenger: rdyCfg.messenger,
driveEvents: rdyCfg.driveEvents
};
if (sessionStorage[Constants.newPadPathKey]) {
cfg.initialPath = sessionStorage[Constants.newPadPathKey];
delete sessionStorage[Constants.newPadPathKey];
}
AStore.query("CONNECT", cfg, waitFor(function (data) {
if (data.error) { throw new Error(data.error); }
if (data.state === 'ALREADY_INIT') {
data = data.returned;
}
if (data.anonHash && !cfg.userHash) { LocalStore.setFSHash(data.anonHash); }
/*if (cfg.userHash && sessionStorage) {
// copy User_hash into sessionStorage because cross-domain iframes
// on safari replaces localStorage with sessionStorage or something
sessionStorage.setItem(Constants.userHashKey, cfg.userHash);
}*/
if (cfg.userHash) {
var localToken = tryParsing(localStorage.getItem(Constants.tokenKey));
if (localToken === null) {
// if that number hasn't been set to localStorage, do so.
localStorage.setItem(Constants.tokenKey, data[Constants.tokenKey]);
}
}
initFeedback(data.feedback);
initialized = true;
}));
}).nThen(function (waitFor) {
// Load the new pad when the hash has changed
var oldHref = document.location.href;
window.onhashchange = function (ev) {
if (ev && ev.reset) { oldHref = document.location.href; return; }
var newHref = document.location.href;
// Password not needed here since we don't access hashData
var parsedOld = Hash.parsePadUrl(oldHref);
var parsedNew = Hash.parsePadUrl(newHref);
if (parsedOld.hashData && parsedNew.hashData &&
parsedOld.getUrl() !== parsedNew.getUrl()) {
/*parseOld && parsedNew && (
parsedOld.type !== parsedNew.type
|| parsedOld.channel !== parsedNew.channel
|| parsedOld.mode !== parsedNew.mode
|| parsedOld.key !== parsedNew.key)) {*/
if (!parsedOld.hashData.channel) { oldHref = newHref; return; }
document.location.reload();
return;
}
if (parsedNew.hashData) { oldHref = newHref; }
};
// Listen for login/logout in other tabs
window.addEventListener('storage', function (e) {
if (e.key !== Constants.userHashKey) { return; }
var o = e.oldValue;
var n = e.newValue;
if (!o && n) {
document.location.reload();
} else if (o && !n) {
LocalStore.logout();
postMessage("DISCONNECT");
}
});
if (PINNING_ENABLED && LocalStore.isLoggedIn()) {
console.log("logged in. pads will be pinned");
7 years ago
postMessage("INIT_RPC", null, waitFor(function (obj) {
console.log('RPC handshake complete');
7 years ago
if (obj.error) { return; }
localStorage.plan = obj.plan;
}));
} else if (PINNING_ENABLED) {
console.log('not logged in. pads will not be pinned');
} else {
console.log('pinning disabled');
}
postMessage("INIT_ANON_RPC", null, waitFor(function () {
console.log('Anonymous RPC ready');
}));
}).nThen(function (waitFor) {
if (sessionStorage.createReadme) {
var data = {
driveReadme: Messages.driveReadme,
driveReadmeTitle: Messages.driveReadmeTitle,
};
postMessage("CREATE_README", data, waitFor(function (e) {
if (e && e.error) { return void console.error(e.error); }
delete sessionStorage.createReadme;
}));
}
}).nThen(function (waitFor) {
if (sessionStorage.migrateAnonDrive) {
common.mergeAnonDrive(waitFor(function() {
delete sessionStorage.migrateAnonDrive;
}));
}
}).nThen(function (waitFor) {
if (AppConfig.afterLogin) {
AppConfig.afterLogin(common, waitFor());
}
}).nThen(function () {
updateLocalVersion();
f(void 0, env);
if (typeof(window.onhashchange) === 'function') { window.onhashchange(); }
});
};
}());
return common;
});