diff --git a/app-template/config-template.xml b/app-template/config-template.xml index 32440782c..39b67d212 100644 --- a/app-template/config-template.xml +++ b/app-template/config-template.xml @@ -72,7 +72,8 @@ - + + diff --git a/src/js/services/desktopSecureStorageService.js b/src/js/services/desktopSecureStorageService.js new file mode 100644 index 000000000..6e148da2c --- /dev/null +++ b/src/js/services/desktopSecureStorageService.js @@ -0,0 +1,6 @@ +'use strict'; + +angular.module('copayApp.services').factory('desktopSecureStorageService', function($log) { + // Placeholder + return {}; +}); \ No newline at end of file diff --git a/src/js/services/mobileSecureStorageService.js b/src/js/services/mobileSecureStorageService.js new file mode 100644 index 000000000..f9994fdf8 --- /dev/null +++ b/src/js/services/mobileSecureStorageService.js @@ -0,0 +1,88 @@ +'use strict'; + +angular.module('copayApp.services').factory('mobileSecureStorageService', function($log, appConfigService, platformInfo) { + var root = {}; + + var isReady = false; + var initialisationFailed = false; + var pending = []; + + var storage = null; + + if (platformInfo.isCordova) { + storage = new cordova.plugins.SecureStorage( + function () { + isReady = true; + for (var i = 0; i < pending.length; i++) { + pending[i](); + } + pending = []; + }, + function (error) { + initialisationFailed = true; + }, + appConfigService.packageNameId); + } + + root.get = function(key, cb) { + + if (!platformInfo.isMobile) { + cb(new Error('mobileSecureStorageService is only available on mobile.')); + return; + } + + if (!isReady) { + if (initialisationFailed) { + cb(new Error('mobileSecureStorageService initialisation failed.')); + } else { + pending.push(function(){ root.get(key, cb); }); + } + return; + } + + storage.get( + function (value) { + cb(null, value); + }, + function (error) { + $log.debug('mss get failed. ' + error); + if (error.message === 'Failure in SecureStorage.get() - The specified item could not be found in the keychain' || // iOS + error.message === 'Key [_SS_profile] not found.') { // Android + // The callback expects no error, but also no value, if it cannot be found. + cb(null, null); + } else { + cb(new Error(error)); + } + }, + key); + }; + + root.set = function(key, value, cb) { + + if (!platformInfo.isMobile) { + cb(new Error('mobileSecureStorageService is only available on mobile.')); + } + + if (!isReady) { + if (initialisationFailed) { + cb(new Error('mobileSecureStorageService initialisation failed.')); + } else { + pending.push(function(){ root.set(key, value, cb); }); + } + return; + } + + storage.set( + function (value) { + cb(); + }, + function (error) { + cb(new Error(error)); + }, + key, value); + + }; + + return root; +}); + diff --git a/src/js/services/secureStorageService.js b/src/js/services/secureStorageService.js new file mode 100644 index 000000000..c066109c2 --- /dev/null +++ b/src/js/services/secureStorageService.js @@ -0,0 +1,32 @@ +'use strict'; + +angular.module('copayApp.services').factory('secureStorageService', function(desktopSecureStorageService, localStorageService, $log, mobileSecureStorageService, platformInfo) { + var root = {}; + + // To make wrong code look wrong + function alteredKeyIndicatingDesireForSecureStorage(key) { + return key + ":desiredSecure"; + } + + root.get = function(k, cb) { + if (platformInfo.isMobile) { + mobileSecureStorageService.get(k, cb); + } else if (platformInfo.isNW) { + desktopSecureStorageService.get(k, cb); + } else { // Browser + localStorageService.get(alteredKeyIndicatingDesireForSecureStorage(k), cb); + } + } + + root.set = function(k, v, cb) { + if (platformInfo.isMobile) { + mobileSecureStorageService.set(k, v, cb); + } else if (platformInfo.isNW) { + desktopSecureStorageService.set(k, v, cb); + } else { // Browser + localStorageService.set(alteredKeyIndicatingDesireForSecureStorage(k), v, cb); + } + } + + return root; +}); \ No newline at end of file diff --git a/src/js/services/storageService.js b/src/js/services/storageService.js index ea0a975c0..7c4ad0a60 100644 --- a/src/js/services/storageService.js +++ b/src/js/services/storageService.js @@ -1,6 +1,6 @@ 'use strict'; angular.module('copayApp.services') - .factory('storageService', function(logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, $timeout) { + .factory('storageService', function(logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, secureStorageService, $timeout) { var root = {}; var storage; @@ -116,60 +116,20 @@ angular.module('copayApp.services') }; root.storeNewProfile = function(profile, cb) { - console.log('storeNewProfile() 6'); - - SecureStorage.set('profile', profile.toObj(), function success(){ cb(); }, function error(err){ cb(err); }); - - //storage.create('profile', profile.toObj(), cb); + secureStorageService.set('profile', profile.toObj(), cb); }; root.storeProfile = function(profile, cb) { - console.log('storeProfile() 6'); - SecureStorage.set('profile', profile.toObj(), function success(){ cb(); }, function error(err){ cb(err); }); - //storage.set('profile', profile.toObj(), cb); + secureStorageService.set('profile', profile.toObj(), cb); }; root.getProfile = function(cb) { - console.log("getProfile() 6"); + secureStorageService.get('profile', function(err, str) { - - SecureStorage.get( - 'profile', - function success(str) { - $log.debug('get profile returned success.'); - decryptOnMobile(str, function(err, str) { - if (err) return cb(err); - var p, err; - try { - p = Profile.fromString(str); - } catch (e) { - $log.debug('Could not read profile:', e); - err = new Error('Could not read profile:' + p); - } - return cb(err, p); - }); - }, - function error(err) { - $log.debug('get profile returned error.'); - $log.debug('returning error.'); - // Callback requires no error and no profile for creation of new profiles - return cb(); - } - ); - - - - /* - storage.get('profile', function(err, str) { - $log.debug('get profile returned.'); - if (err || !str) { - $log.debug('get profile returned error: ' + err + ' with string: ' + str); + if (err || !str) return cb(err); - } - $log.debug('calling decrypt'); decryptOnMobile(str, function(err, str) { - $log.debug('decrypt returned.'); if (err) return cb(err); var p, err; try { @@ -181,14 +141,6 @@ angular.module('copayApp.services') return cb(err, p); }); }); - */ - - - }; - - // Is this ever used? - root.deleteProfile = function(cb) { - storage.remove('profile', cb); }; root.setFeedbackInfo = function(feedbackValues, cb) {