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); postMessage("GIVE_PAD_ACCESS", data, cb);
}; };
common.onCorruptedCache = function (channel) {
postMessage("CORRUPTED_CACHE", channel);
};
common.setPadMetadata = function (data, cb) { common.setPadMetadata = function (data, cb) {
postMessage('SET_PAD_METADATA', data, cb); postMessage('SET_PAD_METADATA', data, cb);
}; };

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

@ -1,7 +1,7 @@
define([ define([
// XXX Load util and use mkAsync '/common/common-util.js',
'/bower_components/localforage/dist/localforage.min.js', '/bower_components/localforage/dist/localforage.min.js',
], function (localForage) { ], function (Util, localForage) {
var S = {}; var S = {};
var cache = localForage.createInstance({ var cache = localForage.createInstance({
@ -11,43 +11,50 @@ define([
// id: channel ID or blob ID // id: channel ID or blob ID
// returns array of messages // returns array of messages
S.getChannelCache = function (id, cb) { S.getChannelCache = function (id, cb) {
cb = Util.once(Util.mkAsync(cb || function () {}));
cache.getItem(id, function (err, obj) { cache.getItem(id, function (err, obj) {
if (err || !obj || !Array.isArray(obj.c)) { if (err || !obj || !Array.isArray(obj.c)) {
return void cb(err || 'EINVAL'); return void cb(err || 'EINVAL');
} }
cb(null, obj); 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) { var checkCheckpoints = function (array) {
if (!Array.isArray(array)) { return; } if (!Array.isArray(array)) { return; }
var cp = 0; // Keep the last 100 messages
// XXX check sliceCpIndex from hk-util: use the same logic for forks if (array.length > 100) {
for (var i = array.length - 1; i >= 0; i--) { array.splice(0, array.length - 100);
if (array[i].isCheckpoint) { cp++; }
if (cp === 2) {
array.splice(0, i);
break;
}
} }
// 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) { 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'); } if (!Array.isArray(val) || !validateKey) { return void cb('EINVAL'); }
checkCheckpoints(val); checkCheckpoints(val);
cache.setItem(id, { cache.setItem(id, {
k: validateKey, k: validateKey,
c: val 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 t: (+new Date()) // 't' represent the "lastAccess" of this cache (get or set)
// XXX we would also need to update the time when we "getChannelCache"
}, function (err) { }, function (err) {
cb(err); cb(err);
}); });
}; };
S.clearChannel = function (id, cb) { S.clearChannel = function (id, cb) {
cb = cb || function () {}; cb = Util.once(Util.mkAsync(cb || function () {}));
cache.removeItem(id, cb); cache.removeItem(id, cb);
}; };

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

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

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

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

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

Loading…
Cancel
Save