diff --git a/1p-filters.html b/1p-filters.html index 034321a8d..402231678 100644 --- a/1p-filters.html +++ b/1p-filters.html @@ -5,20 +5,7 @@ µBlock — Your filters - + diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 1019ad893..d0330215b 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -279,6 +279,26 @@ "message":"Mitwirkende", "description":"English: Contributors" }, + "aboutBackupDataButton" : { + "message": "Backup to file...", + "description": "English: Backup to file..." + }, + "aboutRestoreDataButton" : { + "message": "Restore from file...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton" : { + "message": "Start from scratch...", + "description": "English: Start from scratch..." + }, + "aboutRestoreDataConfirm" : { + "message": "All your settings will be overwritten using data backed up on {{time}}, and µBlock will restart.\n\nOverwrite all existing settings using backed up data?", + "description": "Message asking user to confirm restore" + }, + "aboutResetDataConfirm" : { + "message": "All your settings will be erased, and µBlock will restart.\n\nReset µBlock to factory settings?", + "description": "Message asking user to confirm restore" + }, "errorCantConnectTo":{ "message":"Netzwerkfehler: Verbindung zu {{url}} nicht möglich", "description":"English: Network error: unable to connect to {{url}}" diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3794e1511..06c1fe69a 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -279,6 +279,26 @@ "message":"Contributors", "description":"English: Contributors" }, + "aboutBackupDataButton" : { + "message": "Backup to file...", + "description": "English: Backup to file..." + }, + "aboutRestoreDataButton" : { + "message": "Restore from file...", + "description": "English: Restore from file..." + }, + "aboutResetDataButton" : { + "message": "Start from scratch...", + "description": "English: Start from scratch..." + }, + "aboutRestoreDataConfirm" : { + "message": "All your settings will be overwritten using data backed up on {{time}}, and µBlock will restart.\n\nOverwrite all existing settings using backed up data?", + "description": "Message asking user to confirm restore" + }, + "aboutResetDataConfirm" : { + "message": "All your settings will be erased, and µBlock will restart.\n\nReset µBlock to factory settings?", + "description": "Message asking user to confirm restore" + }, "errorCantConnectTo":{ "message":"Unable to connect to {{url}}", "description":"English: Network error: unable to connect to {{url}}" diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 0f8b18bcc..c30b44766 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -279,6 +279,26 @@ "message":"Contributeurs", "description":"English: Contributors" }, + "aboutBackupDataButton" : { + "message": "Exporter vers un fichier", + "description": "English: Backup to file..." + }, + "aboutRestoreDataButton" : { + "message": "Importer depuis un fichier", + "description": "English: Restore from file..." + }, + "aboutResetDataButton" : { + "message": "Repartir à zéro", + "description": "English: Start from scratch..." + }, + "aboutRestoreDataConfirm" : { + "message": "Vos paramètres seront remplacés par les données sauvegardées le {{time}}, puis µBlock redémarrera.\n\nProcéder à l'importation ?", + "description": "Message asking user to confirm restore" + }, + "aboutResetDataConfirm" : { + "message": "Vos paramètres seront effacés, puis µBlock redémarrera.\n\nProcéder à la remise à zéro ?", + "description": "Message asking user to confirm restore" + }, "errorCantConnectTo":{ "message":"Erreur de connexion : {{url}}", "description":"English: Network error: unable to connect to {{url}}" diff --git a/about.html b/about.html index eaa3883ef..3f98263b4 100644 --- a/about.html +++ b/about.html @@ -5,18 +5,13 @@ µBlock — About - +

µBlock

- +
+ +
+

+ +

+

+

+ + diff --git a/css/1p-filters.css b/css/1p-filters.css new file mode 100644 index 000000000..54117a2cc --- /dev/null +++ b/css/1p-filters.css @@ -0,0 +1,13 @@ +div > p:first-child { + margin-top: 0; + } +div > p:last-child { + margin-bottom: 0; + } +.userFilters { + font-size: smaller; + width: 48em; + height: 40em; + white-space: nowrap; + text-align: left; + } diff --git a/css/about.css b/css/about.css new file mode 100644 index 000000000..1d682b225 --- /dev/null +++ b/css/about.css @@ -0,0 +1,4 @@ +ul { + padding-__MSG_@@bidi_start_edge__: 1em; + margin-__MSG_@@bidi_start_edge__: 1em; + } diff --git a/css/dashboard-common.css b/css/dashboard-common.css index c00f4dbff..db2dca118 100644 --- a/css/dashboard-common.css +++ b/css/dashboard-common.css @@ -25,7 +25,9 @@ h2 + * { a { text-decoration: none; } - +button { + padding: 0.33em; + } div > p:first-child { margin-top: 0; } @@ -36,18 +38,6 @@ div > p:last-child { .para { width: 40em; } - -.userFilters { - text-align: left; - } -#whitelist { - text-align: left; - } -ul#AboutUL { - padding-__MSG_@@bidi_start_edge__: 1em; - margin-__MSG_@@bidi_start_edge__: 1em; - } - .whatisthis { margin: 0 0 0 8px; border: 0; diff --git a/css/whitelist.css b/css/whitelist.css new file mode 100644 index 000000000..96030cdc3 --- /dev/null +++ b/css/whitelist.css @@ -0,0 +1,16 @@ +div > p:first-child { + margin-top: 0; + } +div > p:last-child { + margin-bottom: 0; + } +#whitelist { + font-size: smaller; + width: 48em; + height: 40em; + white-space: nowrap; + text-align: left; + } +#whitelist.bad { + background-color: #fee; + } diff --git a/js/about.js b/js/about.js index 3203b98bc..ca41d3022 100644 --- a/js/about.js +++ b/js/about.js @@ -27,7 +27,83 @@ uDom.onLoad(function() { /******************************************************************************/ +messaging.start('about.js'); + +/******************************************************************************/ + +var exportToFile = function() { + var onUserDataReady = function(userData) { + chrome.downloads.download({ + 'url': 'data:text/plain,' + encodeURIComponent(JSON.stringify(userData)), + 'filename': 'ublock-backup.txt', + 'saveAs': true + }); + }; + + messaging.ask({ what: 'getUserData' }, onUserDataReady); +}; + +/******************************************************************************/ + +var importFromFile = function() { + var input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'text/plain'); + + var fileReaderOnLoadHandler = function() { + var userData; + try { + userData = JSON.parse(this.result); + } + catch (e) { + } + if ( userData === undefined ) { + return; + } + var time = new Date(userData.timeStamp); + var msg = chrome.i18n + .getMessage('aboutRestoreDataConfirm') + .replace('{{time}}', time.toLocaleString()); + var proceed = window.confirm(msg); + if ( proceed ) { + messaging.tell({ what: 'restoreUserData', userData: userData }); + } + }; + + var filePickerOnChangeHandler = function() { + input.removeEventListener('change', filePickerOnChangeHandler); + var file = this.files[0]; + if ( !file ) { + return; + } + if ( file.type.indexOf('text') !== 0 ) { + return; + } + var fr = new FileReader(); + fr.onload = fileReaderOnLoadHandler; + fr.readAsText(file); + }; + + input.addEventListener('change', filePickerOnChangeHandler); + input.click(); +}; + +/******************************************************************************/ + +var resetUserData = function() { + var msg = chrome.i18n.getMessage('aboutResetDataConfirm'); + var proceed = window.confirm(msg); + if ( proceed ) { + messaging.tell({ what: 'resetUserData' }); + } +}; + +/******************************************************************************/ + uDom('#aboutVersion').html(chrome.runtime.getManifest().version); +uDom('#export').on('click', exportToFile); +uDom('#import').on('click', importFromFile); +uDom('#reset').on('click', resetUserData); /******************************************************************************/ diff --git a/js/messaging-handlers.js b/js/messaging-handlers.js index 9d557ec57..7085b431f 100644 --- a/js/messaging-handlers.js +++ b/js/messaging-handlers.js @@ -633,9 +633,53 @@ var µb = µBlock; /******************************************************************************/ +var getUserData = function(callback) { + var onUserFiltersReady = function(details) { + callback({ + 'timeStamp': Date.now(), + 'version': µb.manifest.version, + 'userSettings': µb.userSettings, + 'filterLists': µb.remoteBlacklists, + 'netWhitelist': µb.stringFromWhitelist(µb.netWhitelist), + 'userFilters': details.content + }); + }; + µb.assets.get('assets/user/filters.txt', onUserFiltersReady); +}; + +/******************************************************************************/ + +var restoreUserData = function(userData) { + var onUserFiltersSaved = function() { + µb.XAL.restart(); + }; + µb.destroySelfie(); + µb.XAL.keyvalSetMany(userData.userSettings); + µb.XAL.keyvalSetOne('remoteBlacklists', userData.filterLists); + µb.XAL.keyvalSetOne('netWhitelist', userData.netWhitelist); + µb.assets.put('assets/user/filters.txt', userData.userFilters, onUserFiltersSaved); +}; + +/******************************************************************************/ + +var resetUserData = function() { + var onAllDone = function() { + µb.XAL.restart(); + }; + // Keep global counts, people can become quite attached to numbers + var onAllRemoved = function() { + µBlock.saveLocalSettings(onAllDone); + }; + µb.XAL.keyvalRemoveAll(onAllRemoved); +}; + +/******************************************************************************/ + var onMessage = function(request, sender, callback) { // Async switch ( request.what ) { + case 'getUserData': + return getUserData(callback); default: break; @@ -645,6 +689,13 @@ var onMessage = function(request, sender, callback) { var response; switch ( request.what ) { + case 'restoreUserData': + restoreUserData(request.userData); + break; + + case 'resetUserData': + resetUserData(); + break; default: return µb.messaging.defaultHandler(request, sender, callback); diff --git a/js/storage.js b/js/storage.js index 1d27e3c39..a66a11007 100644 --- a/js/storage.js +++ b/js/storage.js @@ -32,10 +32,11 @@ /******************************************************************************/ -µBlock.saveLocalSettings = function() { - chrome.storage.local.set(this.localSettings, function() { - µBlock.getBytesInUse(); - }); +µBlock.saveLocalSettings = function(callback) { + if ( typeof callback !== 'function' ) { + callback = this.noopFunc; + } + chrome.storage.local.set(this.localSettings, callback); }; /******************************************************************************/ diff --git a/js/ublock.js b/js/ublock.js index 4a74c0b3a..186eb97f9 100644 --- a/js/ublock.js +++ b/js/ublock.js @@ -265,6 +265,6 @@ } if ( changed ) { this.userSettings.dynamicFilteringSelfie = this.netFilteringEngine.selfieFromDynamicFilters(); - this.XAL.keyValSetOne('dynamicFilteringSelfie', this.userSettings.dynamicFilteringSelfie); + this.XAL.keyvalSetOne('dynamicFilteringSelfie', this.userSettings.dynamicFilteringSelfie); } }; diff --git a/js/xal.js b/js/xal.js index 1a1ef1837..fa9727979 100644 --- a/js/xal.js +++ b/js/xal.js @@ -59,7 +59,7 @@ exports.injectScript = function(id, details) { /******************************************************************************/ -exports.keyValSetOne = function(key, val) { +exports.keyvalSetOne = function(key, val) { var bin = {}; bin[key] = val; chrome.storage.local.set(bin); @@ -67,6 +67,24 @@ exports.keyValSetOne = function(key, val) { /******************************************************************************/ +exports.keyvalSetMany = function(dict) { + chrome.storage.local.set(dict); +}; + +/******************************************************************************/ + +exports.keyvalRemoveAll = function(callback) { + chrome.storage.local.clear(callback); +}; + +/******************************************************************************/ + +exports.restart = function() { + chrome.runtime.reload(); +}; + +/******************************************************************************/ + return exports; /******************************************************************************/ diff --git a/whitelist.html b/whitelist.html index e1ca1b7fc..ce97b1bca 100644 --- a/whitelist.html +++ b/whitelist.html @@ -5,23 +5,7 @@ µBlock — Whitelist - +