From f1e67ad0e6acf5b4f355f9c41e8619f2062d6726 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 21 Jun 2016 11:17:42 -0300 Subject: [PATCH 1/2] add writelock to file operations --- src/js/controllers/index.js | 8 +++----- src/js/services/fileStorage.js | 24 ++++++++++++++++++++--- src/js/services/profileService.js | 32 +++++++++++++++++++++---------- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/js/controllers/index.js b/src/js/controllers/index.js index 77dc106aa..1afccdd38 100644 --- a/src/js/controllers/index.js +++ b/src/js/controllers/index.js @@ -1407,16 +1407,14 @@ angular.module('copayApp.controllers').controller('indexController', function($r }); $rootScope.$on('Local/ValidatingWallet', function(ev, walletId) { - if (self.isInFocus(walletId)) { - ongoingProcess.set('validatingWallet', true); - } + ongoingProcess.set('validatingWallet', true); }); $rootScope.$on('Local/ValidatingWalletEnded', function(ev, walletId, isOK) { - profileService.storeProfileIfDirty(); + ongoingProcess.set('validatingWallet', false); + if (self.isInFocus(walletId)) { // NOTE: If the user changed the wallet, the flag is already turn off. - ongoingProcess.set('validatingWallet', false); self.incorrectDerivation = isOK === false; } }); diff --git a/src/js/services/fileStorage.js b/src/js/services/fileStorage.js index 0e619cbb2..b93bde832 100644 --- a/src/js/services/fileStorage.js +++ b/src/js/services/fileStorage.js @@ -52,9 +52,25 @@ angular.module('copayApp.services') }) }; - root.set = function(k, v, cb) { + var writelock = {}; + + root.set = function(k, v, cb, delay) { + + delay = delay || 100; + + if (writelock[k]) { + return setTimeout(function() { + console.log('## Writelock for:' + k + ' Retrying in ' + delay); + return root.set(k, v, cb, delay + 100); + }, delay); + } + + writelock[k] = true; root.init(function(err, fs, dir) { - if (err) return cb(err); + if (err) { + writelock[k] = false; + return cb(err); + } dir.getFile(k, { create: true, }, function(fileEntry) { @@ -62,13 +78,15 @@ angular.module('copayApp.services') fileEntry.createWriter(function(fileWriter) { fileWriter.onwriteend = function(e) { - console.log('Write completed.'); + console.log('Write completed:' + k); + writelock[k] = false; return cb(); }; fileWriter.onerror = function(e) { var err = e.error ? e.error : JSON.stringify(e); console.log('Write failed: ' + err); + writelock[k] = false; return cb('Fail to write:' + err); }; diff --git a/src/js/services/profileService.js b/src/js/services/profileService.js index 0327d71a3..fc3295114 100644 --- a/src/js/services/profileService.js +++ b/src/js/services/profileService.js @@ -117,20 +117,32 @@ angular.module('copayApp.services') return true; }; - root.runValidation = function(client) { + var validationLock = false; + + root.runValidation = function(client, delay, retryDelay) { + delay = delay || 500; + retryDelay = retryDelay || 50; + + if (validationLock) { + return $timeout(function() { + $log.debug('ValidatingWallet Locked: Retrying in: ' + retryDelay); + return root.runValidation(client, delay, retryDelay); + }, retryDelay); + } + validationLock = true; // IOS devices are already checked var skipDeviceValidation = isIOS || root.profile.isDeviceChecked(platformInfo.ua); var walletId = client.credentials.walletId; + $log.debug('ValidatingWallet: ' + walletId + ' skip Device:' + skipDeviceValidation); + $rootScope.$emit('Local/ValidatingWallet', walletId); $timeout(function() { - - $log.debug('ValidatingWallet: ' + walletId + ' skip Device:' + skipDeviceValidation); - $rootScope.$emit('Local/ValidatingWallet', walletId); - client.validateKeyDerivation({ skipDeviceValidation: skipDeviceValidation, }, function(err, isOK) { + validationLock = false; + $log.debug('ValidatingWallet End: ' + walletId + ' isOK:' + isOK); if (isOK) { root.profile.setChecked(platformInfo.ua, walletId); @@ -138,9 +150,10 @@ angular.module('copayApp.services') $log.warn('Key Derivation failed for wallet:' + walletId); storageService.clearLastAddress(walletId, function() {}); } + root.storeProfileIfDirty(); $rootScope.$emit('Local/ValidatingWalletEnded', walletId, isOK); }); - }, 5000); + }, delay); }; // Used when reading wallets from the profile @@ -163,7 +176,7 @@ angular.module('copayApp.services') var skipKeyValidation = root.profile.isChecked(platformInfo.ua, credentials.walletId); if (!skipKeyValidation) - root.runValidation(client); + root.runValidation(client, 500); $log.info('Binding wallet:' + credentials.walletId + ' Validating?:' + !skipKeyValidation); return cb(null, root.bindWalletClient(client)); @@ -390,8 +403,8 @@ angular.module('copayApp.services') // check if exist if (lodash.find(root.profile.credentials, { - 'walletId': walletData.walletId - })) { + 'walletId': walletData.walletId + })) { return cb(gettext('Cannot join the same wallet more that once')); } } catch (ex) { @@ -512,7 +525,6 @@ angular.module('copayApp.services') saveBwsUrl(function() { root.setAndStoreFocus(walletId, function() { storageService.storeProfile(root.profile, function(err) { - var config = configService.getSync(); if (config.pushNotifications.enabled) pushNotificationsService.enableNotifications(root.walletClients); From f2444622509a6be21b7ba54e0a2d590652706c44 Mon Sep 17 00:00:00 2001 From: Matias Alejo Garcia Date: Tue, 21 Jun 2016 11:47:42 -0300 Subject: [PATCH 2/2] fix opening corrupt profiles --- src/js/services/storageService.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index 62eb71f2c..1de5ec21e 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -28,7 +28,23 @@ angular.module('copayApp.services') var json; try { json = JSON.parse(text); - } catch (e) {}; + } catch (e) { + $log.warn('Could not open profile:' + text); + + var i = text.lastIndexOf('}{'); + if (i > 0) { + text = text.substr(i + 1); + $log.warn('trying last part only:' + text); + try { + json = JSON.parse(text); + $log.warn('Worked... saving.'); + storage.set('profile', text, function() {}); + } catch (e) { + $log.warn('Could not open profile (2nd try):' + e); + }; + }; + + }; if (!json) return cb('Could not access storage')