More cache eviction tools

pull/1/head
yflory 4 years ago
parent a0df168ff4
commit 5ca7247304

@ -985,6 +985,24 @@ define([
}, {timeout: -1}); }, {timeout: -1});
}; };
common.disableCache = function (disabled, cb) {
postMessage("CACHE_DISABLE", disabled, cb);
};
window.addEventListener('storage', function (e) {
if (e.key !== 'CRYPTPAD_STORE|disableCache') { return; }
var o = e.oldValue;
var n = e.newValue;
if (n) {
Cache.disable();
common.disableCache(true, function () {});
} else {
Cache.enable();
common.disableCache(false, function () {});
}
});
if (localStorage['CRYPTPAD_STORE|disableCache']) {
Cache.disable();
}
// Admin // Admin
common.adminRpc = function (data, cb) { common.adminRpc = function (data, cb) {
@ -2226,6 +2244,7 @@ define([
localToken: tryParsing(localStorage.getItem(Constants.tokenKey)), // TODO move this to LocalStore ? localToken: tryParsing(localStorage.getItem(Constants.tokenKey)), // TODO move this to LocalStore ?
language: common.getLanguage(), language: common.getLanguage(),
cache: rdyCfg.cache, cache: rdyCfg.cache,
disableCache: localStorage['CRYPTPAD_STORE|disableCache'],
driveEvents: true //rdyCfg.driveEvents // Boolean driveEvents: true //rdyCfg.driveEvents // Boolean
}; };
common.userHash = userHash; common.userHash = userHash;

@ -37,6 +37,9 @@ define([
var onReadyEvt = Util.mkEvent(true); var onReadyEvt = Util.mkEvent(true);
var onCacheReadyEvt = Util.mkEvent(true); var onCacheReadyEvt = Util.mkEvent(true);
// XXX Number of days before deleting the cache for a channel or blob
var CACHE_MAX_AGE = 90; // DAYS
// Default settings for new users // Default settings for new users
var NEW_USER_SETTINGS = { var NEW_USER_SETTINGS = {
drive: { drive: {
@ -334,7 +337,6 @@ define([
if (!s.rpc) { return void cb({error: 'RPC_NOT_READY'}); } if (!s.rpc) { return void cb({error: 'RPC_NOT_READY'}); }
s.rpc.removeOwnedChannel(channel, function (err) { s.rpc.removeOwnedChannel(channel, function (err) {
if (!err) { Cache.clearChannel(channel); }
cb({error:err}); cb({error:err});
}); });
}; };
@ -2861,6 +2863,15 @@ define([
}, PING_INTERVAL); }, PING_INTERVAL);
}; };
Store.disableCache = function (clientId, disabled, cb) {
if (disabled) {
Cache.disable();
} else {
Cache.enable();
}
cb();
};
/** /**
* Data: * Data:
* - userHash or anonHash * - userHash or anonHash
@ -2901,6 +2912,11 @@ define([
}); });
}); });
} }
if (data.disableCache) {
Cache.disable();
}
initialized = true; initialized = true;
postMessage = function (clientId, cmd, d, cb) { postMessage = function (clientId, cmd, d, cb) {
data.query(clientId, cmd, d, cb); data.query(clientId, cmd, d, cb);
@ -2920,6 +2936,27 @@ define([
callback(ret); callback(ret);
}); });
// Clear inactive channels from cache
onReadyEvt.reg(function () {
var inactiveTime = (+new Date()) - CACHE_MAX_AGE * (24 * 3600 * 1000);
Cache.getKeys(function (err, keys) {
if (err) { return void console.error(err); }
var next = function (cb) {
if (!keys.length) { return; }
var key = keys.pop();
var value = Cache.getTime(key, function (err, atime) {
if (err) { return void next(); }
if (!atime || atime < inactiveTime) {
Cache.clearChannel(key, next());
return;
}
next();
});
};
next();
});
});
}; };
Store.disconnect = function () { Store.disconnect = function () {

@ -7,10 +7,14 @@ define([
// Check if indexedDB is allowed // Check if indexedDB is allowed
var allowed = false; var allowed = false;
var disabled = false;
var supported = false;
try { try {
var request = window.indexedDB.open('test_db', 1); var request = window.indexedDB.open('test_db', 1);
request.onsuccess = function () { request.onsuccess = function () {
allowed = true; supported = true;
allowed = supported && !disabled;
onReady.fire(); onReady.fire();
}; };
request.onerror = function () { request.onerror = function () {
@ -20,6 +24,15 @@ define([
onReady.fire(); onReady.fire();
} }
S.enable = function () {
disabled = false;
allowed = supported && !disabled;
};
S.disable = function () {
disabled = true;
allowed = supported && !disabled;
};
var cache = localForage.createInstance({ var cache = localForage.createInstance({
driver: localForage.INDEXEDDB, driver: localForage.INDEXEDDB,
name: "cp_cache" name: "cp_cache"
@ -141,6 +154,30 @@ define([
}); });
}; };
S.getKeys = function (cb) {
cb = Util.once(Util.mkAsync(cb || function () {}));
onReady.reg(function () {
if (!allowed) { return void cb('NOCACHE'); }
cache.keys().then(function (keys) {
cb(null, keys);
}).catch(function (err) {
cb(err);
});
});
};
S.getTime = function (id, cb) {
cb = Util.once(Util.mkAsync(cb || function () {}));
onReady.reg(function () {
if (!allowed) { return void cb('NOCACHE'); }
cache.getItem(id, function (err, obj) {
if (err || !obj || !obj.c) {
return void cb(Util.serializeError(err || 'EINVAL'));
}
cb(null, obj.t);
});
});
};
self.CryptPad_clearIndexedDB = S.clear; self.CryptPad_clearIndexedDB = S.clear;
return S; return S;

@ -14,6 +14,7 @@ define([
CREATE_README: Store.createReadme, CREATE_README: Store.createReadme,
MIGRATE_ANON_DRIVE: Store.migrateAnonDrive, MIGRATE_ANON_DRIVE: Store.migrateAnonDrive,
PING: function (cId, data, cb) { cb(); }, PING: function (cId, data, cb) { cb(); },
CACHE_DISABLE: Store.disableCache,
// RPC // RPC
UPDATE_PIN_LIMIT: Store.updatePinLimit, UPDATE_PIN_LIMIT: Store.updatePinLimit,
GET_PIN_LIMIT: Store.getPinLimit, GET_PIN_LIMIT: Store.getPinLimit,

@ -76,9 +76,15 @@ define([
}; };
// Fire an event. channel.event('EV_SOMETHING', { args: "whatever" }); // Fire an event. channel.event('EV_SOMETHING', { args: "whatever" });
var event = chan.event = function (e, content) { var event = chan.event = function (e, content, opts) {
opts = opts || {};
evReady.reg(function () { evReady.reg(function () {
postMsg(JSON.stringify({ content: content, q: e })); var toSend = {
content: content,
q: e,
raw: opts.raw
};
postMsg(opts.raw ? toSend : JSON.stringify(toSend));
}); });
}; };

@ -1,6 +1,6 @@
(function () { (function () {
var factory = function (Util, Rpc) { var factory = function (Util, Rpc) {
var create = function (network, proxy, _cb) { var create = function (network, proxy, _cb, Cache) {
if (typeof(_cb) !== 'function') { throw new Error("Expected callback"); } if (typeof(_cb) !== 'function') { throw new Error("Expected callback"); }
var cb = Util.once(Util.mkAsync(_cb)); var cb = Util.once(Util.mkAsync(_cb));
@ -155,6 +155,9 @@ var factory = function (Util, Rpc) {
if (e) { return void cb(e); } if (e) { return void cb(e); }
if (response && response.length && response[0] === "OK") { if (response && response.length && response[0] === "OK") {
cb(); cb();
if (Cache && Cache.clearChannel) {
Cache.clearChannel(channel);
}
} else { } else {
cb('INVALID_RESPONSE'); cb('INVALID_RESPONSE');
} }

@ -1476,6 +1476,21 @@ define([
}); });
}); });
sframeChan.on('Q_CACHE_DISABLE', function (data, cb) {
if (data.disabled) {
Utils.Cache.clear(function () {
Utils.Cache.disable();
});
Cryptpad.disableCache(true, cb);
return;
}
Utils.Cache.enable();
Cryptpad.disableCache(false, cb);
});
sframeChan.on('Q_CLEAR_CACHE', function (data, cb) {
Utils.Cache.clear(cb);
});
sframeChan.on('Q_PIN_GET_USAGE', function (teamId, cb) { sframeChan.on('Q_PIN_GET_USAGE', function (teamId, cb) {
Cryptpad.isOverPinLimit(teamId, function (err, overLimit, data) { Cryptpad.isOverPinLimit(teamId, function (err, overLimit, data) {
cb({ cb({

@ -758,7 +758,7 @@ define([
window.cryptpadStore._put(k, v, cb); window.cryptpadStore._put(k, v, cb);
var x = {}; var x = {};
x[k] = v; x[k] = v;
ctx.sframeChan.event('EV_LOCALSTORE_PUT', x); ctx.sframeChan.event('EV_LOCALSTORE_PUT', x, {raw:true});
}; };
}); });

@ -60,6 +60,7 @@ define([
'cp-settings-autostore', 'cp-settings-autostore',
'cp-settings-safe-links', 'cp-settings-safe-links',
'cp-settings-userfeedback', 'cp-settings-userfeedback',
'cp-settings-cache',
], ],
'drive': [ 'drive': [
'cp-settings-resettips', 'cp-settings-resettips',
@ -359,6 +360,59 @@ define([
return $div; return $div;
}; };
// XXX
Messages.settings_cacheTitle = "Cache";
Messages.settings_cacheHint = "CryptPad stores parts of your documents in your browser's memory in order to save network usage and improve loading times. The documents stored in cache can then be loaded faster the next time you visit them. You can disable the cache if your device doesn't have a lot of free storage space. For security reasons, the cache is always cleared when you log out, but you can clear it manually if you want to reclaim storage space on your machine.";
Messages.settings_cacheCheckbox = "Enable cache on this device";
Messages.settings_cacheButton = "Clear existing cache";
makeBlock('cache', function (cb, $div) {
var store = window.cryptpadStore;
var $cbox = $(UI.createCheckbox('cp-settings-cache',
Messages.settings_cacheCheckbox,
false, { label: { class: 'noTitle' } }));
var spinner = UI.makeSpinner($cbox);
// Checkbox: "Enable safe links"
var $checkbox = $cbox.find('input').on('change', function() {
spinner.spin();
var val = !$checkbox.is(':checked') ? '1' : undefined;
store.put('disableCache', val, function () {
sframeChan.query('Q_CACHE_DISABLE', {
disabled: Boolean(val)
}, function () {
spinner.done();
});
});
});
store.get('disableCache', function (val) {
if (!val) {
$checkbox.attr('checked', 'checked');
}
});
var button = h('button.btn.btn-danger', [
h('i.fa.fa-trash-o'),
h('span', Messages.settings_cacheButton)
]);
var buttonContainer = h('div.cp-settings-clear-cache', button);
var spinner2 = UI.makeSpinner($(buttonContainer));
UI.confirmButton(button, {
classes: 'btn-danger'
}, function () {
spinner.spin();
sframeChan.query('Q_CLEAR_CACHE', null, function() {
spinner.done();
});
});
cb([
$cbox[0],
buttonContainer
]);
}, true);
create['delete'] = function() { create['delete'] = function() {
if (!common.isLoggedIn()) { return; } if (!common.isLoggedIn()) { return; }
var $div = $('<div>', { 'class': 'cp-settings-delete cp-sidebarlayout-element' }); var $div = $('<div>', { 'class': 'cp-settings-delete cp-sidebarlayout-element' });

Loading…
Cancel
Save