From 181a4efd8b32021f287b5267bf700a1b18d42fca Mon Sep 17 00:00:00 2001 From: yflory Date: Fri, 8 Jan 2021 15:13:45 +0100 Subject: [PATCH] Fix race conditions and multiple tabs on the same worker --- www/common/outer/async-store.js | 24 ++++++++++++++++----- www/common/outer/sharedworker.js | 35 ++++++++++++++++++------------- www/common/sframe-common-outer.js | 5 ----- www/common/sframe-common.js | 4 ---- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 0e9fbedd9..41a1d00aa 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -35,6 +35,7 @@ define([ Crypto, ChainPad, CpNetflux, Listmap, nThen, Saferphore) { var onReadyEvt = Util.mkEvent(true); + var onCacheReadyEvt = Util.mkEvent(true); // Default settings for new users var NEW_USER_SETTINGS = { @@ -2651,7 +2652,8 @@ define([ Feedback.init(returned.feedback); // "cb" may have already been called by onCacheReady - if (typeof(cb) === 'function') { cb(returned); } + store.returned = returned; + if (typeof(cb) === 'function') { cb(); } store.offline = false; sendDriveEvent('NETWORK_RECONNECT'); // Tell inner that we're now online @@ -2766,6 +2768,7 @@ define([ // Check if we can connect var to = setTimeout(function () { console.error('TO'); + store.networkTimeout = true; broadcast([], "LOADING_DRIVE", { type: "offline" }); @@ -2785,8 +2788,10 @@ define([ onCacheReady(clientId, function () { if (typeof(cb) === "function") { cb(returned); } + onCacheReadyEvt.fire(); }); }).on('ready', function (info) { + delete store.networkTimeout; if (store.ready) { return; } // the store is already ready, it is a reconnection store.driveMetadata = info.metadata; if (!rt.proxy.drive || typeof(rt.proxy.drive) !== 'object') { rt.proxy.drive = {}; } @@ -2875,15 +2880,26 @@ define([ Store.init = function (clientId, data, _callback) { var callback = Util.once(_callback); - if (!store.returned && data.cache && store.cacheReturned) { - return void onCacheReady(clientId, function () { + + // If this is not the first tab and we're offline, callback only if the app + // supports offline mode + if (initialized && !store.returned && data.cache) { + return void onCacheReadyEvt.reg(function () { callback({ state: 'ALREADY_INIT', returned: store.cacheReturned }); }); } + + // If this is not the first tab (initialized is true), it means either we don't + // support offline or we're already online if (initialized) { + if (store.networkTimeout) { + postMessage(clientId, "LOADING_DRIVE", { + type: "offline" + }); + } return void whenReady(function () { callback({ state: 'ALREADY_INIT', @@ -2906,8 +2922,6 @@ define([ } if (ret && ret.error) { initialized = false; - } else { - store.returned = ret; } callback(ret); diff --git a/www/common/outer/sharedworker.js b/www/common/outer/sharedworker.js index a89376407..825deb383 100644 --- a/www/common/outer/sharedworker.js +++ b/www/common/outer/sharedworker.js @@ -73,6 +73,7 @@ var init = function (client, cb) { }); chan.on('CONNECT', function (cfg, cb) { debug('SharedW connecting to store...'); + /* if (self.store) { debug('Store already exists!'); if (cfg.driveEvents) { @@ -80,31 +81,35 @@ var init = function (client, cb) { } return void cb(self.store); } + */ - debug('Loading new async store'); - // One-time initialization (init async-store) - cfg.query = function (cId, cmd, data, cb) { - cb = cb || function () {}; - self.tabs[cId].chan.query(cmd, data, function (err, data2) { - if (err) { return void cb({error: err}); } - cb(data2); - }); - }; - cfg.broadcast = function (excludes, cmd, data, cb) { - cb = cb || function () {}; - Object.keys(self.tabs).forEach(function (cId) { - if (excludes.indexOf(cId) !== -1) { return; } + if (!self.store) { + debug('Loading new async store'); + // One-time initialization (init async-store) + cfg.query = function (cId, cmd, data, cb) { + cb = cb || function () {}; self.tabs[cId].chan.query(cmd, data, function (err, data2) { if (err) { return void cb({error: err}); } cb(data2); }); - }); - }; + }; + cfg.broadcast = function (excludes, cmd, data, cb) { + cb = cb || function () {}; + Object.keys(self.tabs).forEach(function (cId) { + if (excludes.indexOf(cId) !== -1) { return; } + self.tabs[cId].chan.query(cmd, data, function (err, data2) { + if (err) { return void cb({error: err}); } + cb(data2); + }); + }); + }; + } Rpc.queries['CONNECT'](clientId, cfg, function (data) { if (cfg.driveEvents) { Rpc._subscribeToDrive(clientId); } if (data && data.state === "ALREADY_INIT") { + debug('Store already exists!'); self.store = data.returned; return void cb(data.returned); } diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index e2bb8077c..1d5597ab2 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -498,11 +498,6 @@ define([ // We've received a link without /p/ and it doesn't work without a password: abort return void todo(); } - if (e === "ANON_RPC_NOT_READY") { - // We're currently offline and the pad is not in our cache - w.abort(); - return void sframeChan.event('EV_OFFLINE'); - } // Wrong password or deleted file? askPassword(true, passwordCfg); })); diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js index 7fa303422..8a3328d8a 100644 --- a/www/common/sframe-common.js +++ b/www/common/sframe-common.js @@ -772,10 +772,6 @@ define([ UI.errorLoadingScreen(Messages.restrictedError); }); - ctx.sframeChan.on("EV_OFFLINE", function () { - UI.errorLoadingScreen(Messages.offlineNoCacheError); - }); - ctx.sframeChan.on("EV_PAD_PASSWORD_ERROR", function () { UI.errorLoadingScreen(Messages.password_error_seed); });