Invalidate corrupted caches

pull/1/head
yflory 4 years ago
parent 3a24ef8935
commit e998c21691

@ -1006,6 +1006,10 @@ define([
postMessage("GIVE_PAD_ACCESS", data, cb);
};
common.onCorruptedCache = function (channel) {
postMessage("CORRUPTED_CACHE", channel);
};
common.setPadMetadata = function (data, cb) {
postMessage('SET_PAD_METADATA', data, cb);
};

@ -1607,7 +1607,7 @@ define([
if (padData && padData.validateKey && store.messenger) {
store.messenger.storeValidateKey(data.channel, padData.validateKey);
}
postMessage(clientId, "PAD_READY");
postMessage(clientId, "PAD_READY", pad.noCache);
},
onMessage: function (m, user, validateKey, isCp, hash) {
channel.lastHash = hash;
@ -1738,6 +1738,14 @@ define([
channel.sendMessage(msg, clientId, cb);
};
Store.corruptedCache = function (clientId, channel) {
var chan = channels[channel];
if (!chan || !chan.cpNf) { return; }
Cache.clearChannel(channel);
if (!chan.cpNf.resetCache) { return; }
chan.cpNf.resetCache();
};
// Unpin and pin the new channel in all team when changing a pad password
Store.changePadPasswordPin = function (clientId, data, cb) {
var oldChannel = data.oldChannel;

@ -1,7 +1,7 @@
define([
// XXX Load util and use mkAsync
'/common/common-util.js',
'/bower_components/localforage/dist/localforage.min.js',
], function (localForage) {
], function (Util, localForage) {
var S = {};
var cache = localForage.createInstance({
@ -11,43 +11,50 @@ define([
// id: channel ID or blob ID
// returns array of messages
S.getChannelCache = function (id, cb) {
cb = Util.once(Util.mkAsync(cb || function () {}));
cache.getItem(id, function (err, obj) {
if (err || !obj || !Array.isArray(obj.c)) {
return void cb(err || 'EINVAL');
}
cb(null, obj);
obj.t = +new Date();
cache.setItem(id, obj);
});
};
// Keep the last two checkpoint + any checkpoint that may exist in the last 100 messages
// FIXME: duplicate system with sliceCpIndex from lib/hk-util.js
var checkCheckpoints = function (array) {
if (!Array.isArray(array)) { return; }
var cp = 0;
// XXX check sliceCpIndex from hk-util: use the same logic for forks
for (var i = array.length - 1; i >= 0; i--) {
if (array[i].isCheckpoint) { cp++; }
if (cp === 2) {
array.splice(0, i);
break;
}
// Keep the last 100 messages
if (array.length > 100) {
array.splice(0, array.length - 100);
}
// Remove every message before the first checkpoint
var firstCpIdx;
array.some(function (el, i) {
if (!el.isCheckpoint) { return; }
firstCpIdx = i;
return true;
});
array.splice(0, firstCpIdx);
};
S.storeCache = function (id, validateKey, val, cb) {
cb = cb || function () {};
cb = Util.once(Util.mkAsync(cb || function () {}));
if (!Array.isArray(val) || !validateKey) { return void cb('EINVAL'); }
checkCheckpoints(val);
cache.setItem(id, {
k: validateKey,
c: val
// XXX add "time" here +new Date() ==> we want to store the time when it was updated in our indexeddb in case we want to remove inactive entries from indexeddb later
// XXX we would also need to update the time when we "getChannelCache"
c: val,
t: (+new Date()) // 't' represent the "lastAccess" of this cache (get or set)
}, function (err) {
cb(err);
});
};
S.clearChannel = function (id, cb) {
cb = cb || function () {};
cb = Util.once(Util.mkAsync(cb || function () {}));
cache.removeItem(id, cb);
};

@ -88,6 +88,7 @@ define([
CHANGE_PAD_PASSWORD_PIN: Store.changePadPasswordPin,
GET_LAST_HASH: Store.getLastHash,
GET_SNAPSHOT: Store.getSnapshot,
CORRUPTED_CACHE: Store.corruptedCache,
// Drive
DRIVE_USEROBJECT: Store.userObjectCommand,
// Settings,

@ -467,6 +467,10 @@ define([
});
};
var onCorruptedCache = function (cb) {
var sframeChan = common.getSframeChannel();
sframeChan.event("Q_CORRUPTED_CACHE", cb);
};
var onCacheReady = function () {
stateChange(STATE.DISCONNECTED);
toolbar.offline(true);
@ -475,23 +479,19 @@ define([
// Check if we have a new chainpad instance
toolbar.resetChainpad(cpNfInner.chainpad);
}
console.log(newContentStr);
// Invalid cache? abort
// XXX tell outer/worker to invalidate cache
if (newContentStr === '') { return; }
// Invalid cache
if (newContentStr === '') { return void onCorruptedCache(); }
var privateDat = cpNfInner.metadataMgr.getPrivateData();
var type = privateDat.app;
var newContent = JSON.parse(newContentStr);
var metadata = extractMetadata(newContent);
console.log('OKOK');
// Make sure we're using the correct app for this cache
if (metadata && typeof(metadata.type) !== 'undefined' && metadata.type !== type) {
console.error('return');
return;
return void onCorruptedCache();
}
cpNfInner.metadataMgr.updateMetadata(metadata);
@ -504,7 +504,7 @@ console.log('OKOK');
};
var onReady = function () {
toolbar.offline(false);
console.error('READY');
var newContentStr = cpNfInner.chainpad.getUserDoc();
if (state === STATE.DELETED) { return; }
@ -545,7 +545,12 @@ console.log('OKOK');
console.log("Either this is an empty document which has not been touched");
console.log("Or else something is terribly wrong, reloading.");
Feedback.send("NON_EMPTY_NEWDOC");
// The cache may be wrong, empty it and reload after.
waitFor.abort();
UI.errorLoadingScreen("MAYBE CORRUPTED CACHE... RELOADING"); // XXX
onCorruptedCache(function () {
setTimeout(function () { common.gotoURL(); }, 1000);
});
return;
}
console.log('updating title');

@ -94,13 +94,8 @@ define([
evInfiniteSpinner.fire();
}, 2000);
sframeChan.on('EV_RT_CACHE', function (isPermanent) {
// XXX
});
sframeChan.on('EV_RT_CACHE_READY', function (isPermanent) {
// XXX
onCacheReady({realtime: chainpad});
console.error('PEWPEWPEW');
});
sframeChan.on('EV_RT_DISCONNECT', function (isPermanent) {
isReady = false;
@ -143,7 +138,6 @@ define([
evConnected.fire();
});
sframeChan.on('Q_RT_MESSAGE', function (content, cb) {
console.log(content);
if (isReady) {
onLocal(true); // should be onBeforeMessage
}

@ -89,7 +89,6 @@ define([], function () {
validateKey = msgObj.validateKey;
}
var message = msgIn(msgObj.user, msgObj.msg);
console.log(message);
if (!message) { return; }
lastTime = msgObj.time;
@ -127,7 +126,6 @@ define([], function () {
});
padRpc.onCacheReadyEvent.reg(function () {
console.log('ONCACHEREADY');
sframeChan.event('EV_RT_CACHE_READY');
});

@ -53,12 +53,13 @@ define([
'/common/common-constants.js',
'/common/common-feedback.js',
'/common/outer/local-store.js',
'/common/outer/cache-store.js',
'/customize/application_config.js',
'/common/test.js',
'/common/userObject.js',
], waitFor(function (_CpNfOuter, _Cryptpad, _Crypto, _Cryptget, _SFrameChannel,
_SecureIframe, _Messaging, _Notifier, _Hash, _Util, _Realtime,
_Constants, _Feedback, _LocalStore, _AppConfig, _Test, _UserObject) {
_Constants, _Feedback, _LocalStore, _Cache, _AppConfig, _Test, _UserObject) {
CpNfOuter = _CpNfOuter;
Cryptpad = _Cryptpad;
Crypto = Utils.Crypto = _Crypto;
@ -73,6 +74,7 @@ define([
Utils.Constants = _Constants;
Utils.Feedback = _Feedback;
Utils.LocalStore = _LocalStore;
Utils.Cache = _Cache;
Utils.UserObject = _UserObject;
AppConfig = _AppConfig;
Test = _Test;
@ -1635,6 +1637,11 @@ define([
});
};
sframeChan.on('Q_CORRUPTED_CACHE', function (cb) {
Utils.Cache.clearChannel(secret.channel, cb);
Cryptpad.onCorruptedCache(secret.channel);
});
sframeChan.on('Q_CREATE_PAD', function (data, cb) {
if (!isNewFile || rtStarted) { return; }
// Create a new hash

Loading…
Cancel
Save