diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json
index fb9446a..5ac5b93 100644
--- a/src/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
@@ -35,6 +35,10 @@
"message": "Hosts files",
"description": "a tab in dashboard"
},
+ "rawSettingsPageName": {
+ "message": "More",
+ "description": "a tab in dashboard"
+ },
"aboutPageName": {
"message": "About",
"description": "a tab in dashboard"
@@ -528,6 +532,10 @@
"description":""
},
+ "rawSettingsWarning" : {
+ "message": "Warning! Change these raw configuration settings at your own risk.",
+ "description": ""
+ },
"aboutChangelog" : {
"message": "Change log",
@@ -727,5 +735,10 @@
"errorCantConnectTo":{
"message":"Network error: Unable to connect to {{url}}",
"description":""
+ },
+
+ "genericApplyChanges": {
+ "message": "Apply changes",
+ "description": "for generic 'Apply changes' buttons"
}
}
diff --git a/src/css/dashboard.css b/src/css/dashboard.css
new file mode 100644
index 0000000..0b728ca
--- /dev/null
+++ b/src/css/dashboard.css
@@ -0,0 +1,67 @@
+body {
+ margin: 0;
+ border: 0;
+ padding: 0;
+ font: 15px sans-serif;
+ position: relative;
+ width: 100vw;
+ height: 100vh;
+ overflow: hidden;
+ }
+#dashboard-nav {
+ margin: 0;
+ border: 0;
+ padding: 0;
+ position: absolute;
+ top: 0;
+ width: 100vw;
+ height: 50px;
+ z-index: 10;
+ }
+#dashboard-nav-widgets {
+ margin: 0;
+ border-bottom: 1px solid #ccc;
+ padding: 4px 0 0 0;
+ white-space: nowrap;
+ background-color: white;
+ }
+#dashboard-nav-widgets span {
+ padding: 0 0.5em;
+ font-size: larger;
+ }
+.tabButton {
+ margin: 0;
+ border: 1px solid #ccc;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ padding: 4px;
+ display: inline-block;
+ position: relative;
+ top: 1px;
+ color: black;
+ background-color: #eee;
+ font: inherit;
+ cursor: pointer;
+ text-decoration: none;
+ }
+.tabButton:focus {
+ outline: 0;
+ }
+.tabButton:active,.tabButton:visited {
+ color: inherited;
+ }
+.tabButton.selected {
+ border-bottom: 1px solid white;
+ background-color: white;
+ }
+iframe {
+ margin: 0;
+ border: 0;
+ padding: 0;
+ background-color: transparent;
+ overflow: auto;
+ position: absolute;
+ top: 50px;
+ width: 100%;
+ height: calc(100% - 50px);
+ }
diff --git a/src/css/raw-settings.css b/src/css/raw-settings.css
new file mode 100644
index 0000000..4d9e49d
--- /dev/null
+++ b/src/css/raw-settings.css
@@ -0,0 +1,18 @@
+body {
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ justify-content: space-between;
+ }
+p {
+ margin: 0.5em 0;
+ }
+textarea {
+ box-sizing: border-box;
+ flex-grow: 1;
+ resize: none;
+ text-align: left;
+ white-space: pre;
+ width: 100%;
+ word-wrap: normal;
+ }
diff --git a/src/dashboard.html b/src/dashboard.html
index 629cb35..752fecf 100644
--- a/src/dashboard.html
+++ b/src/dashboard.html
@@ -1,79 +1,11 @@
-
+
-
+
@@ -84,6 +16,7 @@ iframe {
+
diff --git a/src/js/background.js b/src/js/background.js
index 5ac3651..4f58062 100644
--- a/src/js/background.js
+++ b/src/js/background.js
@@ -1,7 +1,7 @@
/*******************************************************************************
uMatrix - a browser extension to black/white list requests.
- Copyright (C) 2014-2017 Raymond Hill
+ Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -79,7 +79,84 @@ var requestStatsFactory = function() {
return new RequestStats();
};
-/******************************************************************************/
+/*******************************************************************************
+
+ SVG-based icons below were extracted from
+ fontawesome-webfont.svg v4.7. Excerpt of copyright notice at
+ the top of the file:
+
+ > Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
+ > By ,,,
+ > Copyright Dave Gandy 2016. All rights reserved.
+
+ Excerpt of the license information in the fontawesome CSS
+ file bundled with the package:
+
+ > Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ > License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+
+ Font icons:
+ - glyph-name: "external_link"
+
+*/
+
+var rawSettingsDefault = {
+ placeholderBackground:
+ [
+ 'url("data:image/png;base64,',
+ 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAK',
+ 'CAAAAACoWZBhAAAABGdBTUEAALGPC/xh',
+ 'BQAAAAJiS0dEAP+Hj8y/AAAAB3RJTUUH',
+ '3wwIAAgyL/YaPAAAACJJREFUCFtjfMbO',
+ 'AAQ/gZiFnQPEBAEmGIMIJgtIL8QEgtoA',
+ 'In4D/96X1KAAAAAldEVYdGRhdGU6Y3Jl',
+ 'YXRlADIwMTUtMTItMDhUMDA6MDg6NTAr',
+ 'MDM6MDAasuuJAAAAJXRFWHRkYXRlOm1v',
+ 'ZGlmeQAyMDE1LTEyLTA4VDAwOjA4OjUw',
+ 'KzAzOjAwa+9TNQAAAABJRU5ErkJggg==',
+ '") ',
+ 'repeat scroll #fff'
+ ].join(''),
+ placeholderBorder: '1px solid rgba(0, 0, 0, 0.1)',
+ imagePlaceholder: true,
+ imagePlaceholderBackground: 'default',
+ imagePlaceholderBorder: 'default',
+ framePlaceholder: true,
+ framePlaceholderDocument:
+ [
+ '',
+ '',
+ '',
+ '',
+ '',
+ '{{url}}',
+ ''
+ ].join(''),
+ framePlaceholderBackground: 'default',
+};
+
/******************************************************************************/
return {
@@ -109,6 +186,10 @@ return {
processReferer: false
},
+ rawSettingsDefault: rawSettingsDefault,
+ rawSettings: Object.assign({}, rawSettingsDefault),
+ rawSettingsWriteTime: 0,
+
clearBrowserCacheCycle: 0,
cspNoInlineScript: "script-src 'unsafe-eval' blob: *",
cspNoWorker: undefined,
diff --git a/src/js/contentscript.js b/src/js/contentscript.js
index 438a47a..f278a6a 100644
--- a/src/js/contentscript.js
+++ b/src/js/contentscript.js
@@ -1,7 +1,7 @@
/*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests.
- Copyright (C) 2014-2017 Raymond Hill
+ Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -187,11 +187,16 @@ var collapser = (function() {
target.hidden = true;
continue;
}
- if ( tag === 'iframe' ) {
+ switch ( tag ) {
+ case 'iframe':
+ if ( placeholders.frame !== true ) { break; }
docurl =
'data:text/html,' +
encodeURIComponent(
- placeholders.iframe.replace(reURLPlaceholder, src)
+ placeholders.frameDocument.replace(
+ reURLPlaceholder,
+ src
+ )
);
replaced = false;
// Using contentWindow.location prevent tainting browser
@@ -206,14 +211,24 @@ var collapser = (function() {
if ( !replaced ) {
target.setAttribute('src', docurl);
}
- continue;
+ break;
+ case 'img':
+ if ( placeholders.image !== true ) { break; }
+ target.style.setProperty('display', 'inline-block');
+ target.style.setProperty('min-width', '20px', 'important');
+ target.style.setProperty('min-height', '20px', 'important');
+ target.style.setProperty(
+ 'border',
+ placeholders.imageBorder,
+ 'important'
+ );
+ target.style.setProperty(
+ 'background',
+ placeholders.imageBackground,
+ 'important'
+ );
+ break;
}
- target.setAttribute(src1stProps[tag], placeholders[tag]);
- target.style.setProperty('display', 'inline-block');
- target.style.setProperty('min-width', '20px', 'important');
- target.style.setProperty('min-height', '20px', 'important');
- target.style.setProperty('border', placeholders.border, 'important');
- target.style.setProperty('background', placeholders.background, 'important');
}
};
diff --git a/src/js/dashboard.js b/src/js/dashboard.js
index 3c1bff0..9c488f2 100644
--- a/src/js/dashboard.js
+++ b/src/js/dashboard.js
@@ -1,7 +1,7 @@
/*******************************************************************************
- µMatrix - a Chromium browser extension to black/white list requests.
- Copyright (C) 2014 Raymond Hill
+ uMatrix - a Chromium browser extension to black/white list requests.
+ Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,40 +21,35 @@
/* global uDom */
-/******************************************************************************/
-
-(function() {
-
'use strict';
/******************************************************************************/
-var loadDashboardPanel = function(hash) {
- var button = uDom(hash);
- var url = button.attr('data-dashboard-panel-url');
- uDom('iframe').attr('src', url);
- uDom('.tabButton').forEach(function(button){
- button.toggleClass('selected', button.attr('data-dashboard-panel-url') === url);
- });
-};
-
-/******************************************************************************/
-
-var onTabClickHandler = function() {
- loadDashboardPanel(window.location.hash);
-};
-
-/******************************************************************************/
-
-uDom.onLoad(function() {
- window.addEventListener('hashchange', onTabClickHandler);
- var hash = window.location.hash;
- if ( hash.length < 2 ) {
- hash = '#settings';
- }
- loadDashboardPanel(hash);
-});
+(function() {
-/******************************************************************************/
+ var loadDashboardPanel = function(hash) {
+ var button = uDom(hash);
+ var url = button.attr('data-dashboard-panel-url');
+ uDom('iframe').attr('src', url);
+ uDom('.tabButton').forEach(function(button){
+ button.toggleClass(
+ 'selected',
+ button.attr('data-dashboard-panel-url') === url
+ );
+ });
+ };
+
+ var onTabClickHandler = function() {
+ loadDashboardPanel(window.location.hash);
+ };
+
+ uDom.onLoad(function() {
+ window.addEventListener('hashchange', onTabClickHandler);
+ var hash = window.location.hash;
+ if ( hash.length < 2 ) {
+ hash = '#settings';
+ }
+ loadDashboardPanel(hash);
+ });
})();
diff --git a/src/js/messaging.js b/src/js/messaging.js
index 70c5ed3..c888a9b 100644
--- a/src/js/messaging.js
+++ b/src/js/messaging.js
@@ -1,7 +1,7 @@
/*******************************************************************************
uMatrix - a Chromium browser extension to black/white list requests.
- Copyright (C) 2014-2017 Raymond Hill
+ Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -89,6 +89,10 @@ function onMessage(request, sender, callback) {
);
break;
+ case 'readRawSettings':
+ response = µm.stringFromRawSettings();
+ break;
+
case 'reloadHostsFiles':
µm.reloadHostsFiles();
break;
@@ -107,6 +111,10 @@ function onMessage(request, sender, callback) {
response = µm.changeUserSettings(request.name, request.value);
break;
+ case 'writeRawSettings':
+ µm.rawSettingsFromString(request.content);
+ break;
+
default:
return vAPI.messaging.UNHANDLED;
}
@@ -447,6 +455,37 @@ var contentScriptLocalStorageHandler = function(tabId, originURL) {
// Evaluate many URLs against the matrix.
var lookupBlockedCollapsibles = function(tabId, requests) {
+ if ( placeholdersReadTime < µm.rawSettingsWriteTime ) {
+ placeholders = undefined;
+ }
+
+ if ( placeholders === undefined ) {
+ placeholders = {
+ frame: µm.rawSettings.framePlaceholder,
+ image: µm.rawSettings.imagePlaceholder
+ };
+ if ( placeholders.frame ) {
+ placeholders.frameDocument =
+ µm.rawSettings.framePlaceholderDocument.replace(
+ '{{bg}}',
+ µm.rawSettings.framePlaceholderBackground !== 'default' ?
+ µm.rawSettings.framePlaceholderBackground :
+ µm.rawSettings.placeholderBackground
+ );
+ }
+ if ( placeholders.image ) {
+ placeholders.imageBorder =
+ µm.rawSettings.imagePlaceholderBorder !== 'default' ?
+ µm.rawSettings.imagePlaceholderBorder :
+ µm.rawSettings.placeholderBorder;
+ placeholders.imageBackground =
+ µm.rawSettings.imagePlaceholderBackground !== 'default' ?
+ µm.rawSettings.imagePlaceholderBackground :
+ µm.rawSettings.placeholderBackground;
+ }
+ placeholdersReadTime = Date.now();
+ }
+
var response = {
blockedResources: [],
hash: requests.hash,
@@ -464,35 +503,11 @@ var lookupBlockedCollapsibles = function(tabId, requests) {
pageStore.lookupBlockedCollapsibles(requests, response);
}
- // TODO: evaluate whether the issue reported below still exists.
- // https://github.com/gorhill/uMatrix/issues/205
- // If blocked, the URL must be recorded by the page store, so as to
- // ensure they are properly reflected in the matrix.
-
- if ( response.placeholders === null ) {
- placeholders = {
- background:
- vAPI.localStorage.getItem('placeholderBackground') ||
- µm.defaultLocalUserSettings.placeholderBackground,
- border:
- vAPI.localStorage.getItem('placeholderBorder') ||
- µm.defaultLocalUserSettings.placeholderBorder,
- iframe:
- vAPI.localStorage.getItem('placeholderDocument') ||
- µm.defaultLocalUserSettings.placeholderDocument,
- img:
- vAPI.localStorage.getItem('placeholderImage') ||
- µm.defaultLocalUserSettings.placeholderImage
- };
- placeholders.iframe =
- placeholders.iframe.replace('{{bg}}', placeholders.background);
- response.placeholders = placeholders;
- }
-
return response;
};
-var placeholders = null;
+var placeholders,
+ placeholdersReadTime = 0;
/******************************************************************************/
@@ -788,7 +803,7 @@ var µm = µMatrix;
/******************************************************************************/
var restoreUserData = function(userData) {
- var countdown = 3;
+ var countdown = 4;
var onCountdown = function() {
countdown -= 1;
if ( countdown === 0 ) {
@@ -797,10 +812,12 @@ var restoreUserData = function(userData) {
};
var onAllRemoved = function() {
- // Be sure to adjust `countdown` if adding/removing anything below
- µm.XAL.keyvalSetMany(userData.settings, onCountdown);
- µm.XAL.keyvalSetOne('userMatrix', userData.rules, onCountdown);
- µm.XAL.keyvalSetOne('liveHostsFiles', userData.hostsFiles, onCountdown);
+ vAPI.storage.set(userData.settings, onCountdown);
+ vAPI.storage.set({ userMatrix: userData.rules }, onCountdown);
+ vAPI.storage.set({ liveHostsFiles: userData.hostsFiles }, onCountdown);
+ if ( userData.rawSettings instanceof Object ) {
+ µMatrix.saveRawSettings(userData.rawSettings, onCountdown);
+ }
};
// If we are going to restore all, might as well wipe out clean local
@@ -837,7 +854,8 @@ var onMessage = function(request, sender, callback) {
when: Date.now(),
settings: µm.userSettings,
rules: µm.pMatrix.toString(),
- hostsFiles: µm.liveHostsFiles
+ hostsFiles: µm.liveHostsFiles,
+ rawSettings: µm.rawSettings
};
break;
diff --git a/src/js/raw-settings.js b/src/js/raw-settings.js
new file mode 100644
index 0000000..ae99d57
--- /dev/null
+++ b/src/js/raw-settings.js
@@ -0,0 +1,115 @@
+/*******************************************************************************
+
+ uMatrix - a browser extension to block requests.
+ Copyright (C) 2018 Raymond Hill
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see {http://www.gnu.org/licenses/}.
+
+ Home: https://github.com/gorhill/uBlock
+*/
+
+/* global uDom */
+
+'use strict';
+
+/******************************************************************************/
+
+(function() {
+
+/******************************************************************************/
+
+var messaging = vAPI.messaging;
+var cachedData = '';
+var rawSettingsInput = uDom.nodeFromId('rawSettings');
+
+/******************************************************************************/
+
+var hashFromRawSettings = function(raw) {
+ return raw.trim().replace(/\s+/g, '|');
+};
+
+/******************************************************************************/
+
+// This is to give a visual hint that the content of user blacklist has changed.
+
+var rawSettingsChanged = (function () {
+ var timer = null;
+
+ var handler = function() {
+ timer = null;
+ var changed =
+ hashFromRawSettings(rawSettingsInput.value) !== cachedData;
+ uDom.nodeFromId('rawSettingsApply').disabled = !changed;
+ };
+
+ return function() {
+ if ( timer !== null ) {
+ clearTimeout(timer);
+ }
+ timer = vAPI.setTimeout(handler, 100);
+ };
+})();
+
+/******************************************************************************/
+
+function renderRawSettings() {
+ var onRead = function(raw) {
+ cachedData = hashFromRawSettings(raw);
+ var pretty = [],
+ whitespaces = ' ',
+ lines = raw.split('\n'),
+ max = 0,
+ pos,
+ i, n = lines.length;
+ for ( i = 0; i < n; i++ ) {
+ pos = lines[i].indexOf(' ');
+ if ( pos > max ) {
+ max = pos;
+ }
+ }
+ for ( i = 0; i < n; i++ ) {
+ pos = lines[i].indexOf(' ');
+ pretty.push(whitespaces.slice(0, max - pos) + lines[i]);
+ }
+ rawSettingsInput.value = pretty.join('\n') + '\n';
+ rawSettingsChanged();
+ rawSettingsInput.focus();
+ };
+ messaging.send('dashboard', { what: 'readRawSettings' }, onRead);
+}
+
+/******************************************************************************/
+
+var applyChanges = function() {
+ messaging.send(
+ 'dashboard',
+ {
+ what: 'writeRawSettings',
+ content: rawSettingsInput.value
+ },
+ renderRawSettings
+ );
+};
+
+/******************************************************************************/
+
+// Handle user interaction
+uDom('#rawSettings').on('input', rawSettingsChanged);
+uDom('#rawSettingsApply').on('click', applyChanges);
+
+renderRawSettings();
+
+/******************************************************************************/
+
+})();
diff --git a/src/js/start.js b/src/js/start.js
index 7095489..c7388b0 100644
--- a/src/js/start.js
+++ b/src/js/start.js
@@ -33,86 +33,6 @@
var µm = µMatrix;
-/*******************************************************************************
-
- SVG-based icons below were extracted from
- fontawesome-webfont.svg v4.7. Excerpt of copyright notice at
- the top of the file:
-
- > Created by FontForge 20120731 at Mon Oct 24 17:37:40 2016
- > By ,,,
- > Copyright Dave Gandy 2016. All rights reserved.
-
- Excerpt of the license information in the fontawesome CSS
- file bundled with the package:
-
- > Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
- > License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
-
- Font icons:
- - glyph-name: "external_link"
-
-*/
-
-µm.defaultLocalUserSettings = {
- // data-URI background courtesy of https://github.com/dev-random
- // https://github.com/gorhill/uMatrix/issues/429#issuecomment-194548243
- placeholderBackground: [
- 'url("data:image/png;base64,',
- 'iVBORw0KGgoAAAANSUhEUgAAAAoAAAAK',
- 'CAAAAACoWZBhAAAABGdBTUEAALGPC/xh',
- 'BQAAAAJiS0dEAP+Hj8y/AAAAB3RJTUUH',
- '3wwIAAgyL/YaPAAAACJJREFUCFtjfMbO',
- 'AAQ/gZiFnQPEBAEmGIMIJgtIL8QEgtoA',
- 'In4D/96X1KAAAAAldEVYdGRhdGU6Y3Jl',
- 'YXRlADIwMTUtMTItMDhUMDA6MDg6NTAr',
- 'MDM6MDAasuuJAAAAJXRFWHRkYXRlOm1v',
- 'ZGlmeQAyMDE1LTEyLTA4VDAwOjA4OjUw',
- 'KzAzOjAwa+9TNQAAAABJRU5ErkJggg==',
- '") ',
- 'repeat scroll #fff'
- ].join(''),
- placeholderBorder: '1px solid rgba(0, 0, 0, 0.1)',
- placeholderDocument: [
- '',
- '',
- '',
- '',
- '',
- '{{url}}',
- ''
- ].join('')
-};
-µm.defaultLocalUserSettings.placeholderImage = µm.defaultLocalUserSettings.placeholderBackground;
-
-var rwLocalUserSettings = {
- placeholderBackground: true,
- placeholderBorder: true,
- placeholderImage: true
-};
-
/******************************************************************************/
var processCallbackQueue = function(queue, callback) {
@@ -135,21 +55,11 @@ var onAllDone = function() {
µm.assets.addObserver(µm.assetObserver.bind(µm));
µm.scheduleAssetUpdater(µm.userSettings.autoUpdate ? 7 * 60 * 1000 : 0);
- for ( var key in µm.defaultLocalUserSettings ) {
- if (µm. defaultLocalUserSettings.hasOwnProperty(key) === false ) {
- continue;
- }
- if (
- vAPI.localStorage.getItem(key) === null ||
- rwLocalUserSettings.hasOwnProperty(key) === false
- ) {
- vAPI.localStorage.setItem(key, µm.defaultLocalUserSettings[key]);
- }
- }
-
vAPI.cloud.start([ 'myRulesPane' ]);
};
+/******************************************************************************/
+
var onTabsReady = function(tabs) {
var tab;
var i = tabs.length;
@@ -162,12 +72,17 @@ var onTabsReady = function(tabs) {
onAllDone();
};
+/******************************************************************************/
+
var onUserSettingsLoaded = function() {
µm.loadHostsFiles();
};
+/******************************************************************************/
+
var onPSLReady = function() {
µm.loadUserSettings(onUserSettingsLoaded);
+ µm.loadRawSettings();
µm.loadMatrix();
// rhill 2013-11-24: bind behind-the-scene virtual tab/url manually, since the
@@ -179,6 +94,8 @@ var onPSLReady = function() {
vAPI.tabs.getAll(onTabsReady);
};
+/******************************************************************************/
+
processCallbackQueue(µm.onBeforeStartQueue, function() {
µm.loadPublicSuffixList(onPSLReady);
});
diff --git a/src/js/storage.js b/src/js/storage.js
index c8b0036..674d059 100644
--- a/src/js/storage.js
+++ b/src/js/storage.js
@@ -1,7 +1,7 @@
/*******************************************************************************
- µMatrix - a Chromium browser extension to black/white list requests.
- Copyright (C) 2014 Raymond Hill
+ uMatrix - a Chromium browser extension to black/white list requests.
+ Copyright (C) 2014-2018 Raymond Hill
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -47,8 +47,6 @@
);
};
-/******************************************************************************/
-
µMatrix.loadUserSettings = function(callback) {
var µm = this;
@@ -69,6 +67,98 @@
/******************************************************************************/
+µMatrix.loadRawSettings = function() {
+ var µm = this;
+
+ var onLoaded = function(bin) {
+ if ( !bin || bin.rawSettings instanceof Object === false ) { return; }
+ for ( var key of Object.keys(bin.rawSettings) ) {
+ if (
+ µm.rawSettings.hasOwnProperty(key) === false ||
+ typeof bin.rawSettings[key] !== typeof µm.rawSettings[key]
+ ) {
+ continue;
+ }
+ µm.rawSettings[key] = bin.rawSettings[key];
+ }
+ µm.rawSettingsWriteTime = Date.now();
+ };
+
+ vAPI.storage.get('rawSettings', onLoaded);
+};
+
+µMatrix.saveRawSettings = function(rawSettings, callback) {
+ var keys = Object.keys(rawSettings);
+ if ( keys.length === 0 ) {
+ if ( typeof callback === 'function' ) {
+ callback();
+ }
+ return;
+ }
+ for ( var key of keys ) {
+ if (
+ this.rawSettingsDefault.hasOwnProperty(key) &&
+ typeof rawSettings[key] === typeof this.rawSettingsDefault[key]
+ ) {
+ this.rawSettings[key] = rawSettings[key];
+ }
+ }
+ vAPI.storage.set({ rawSettings: this.rawSettings }, callback);
+ this.rawSettingsWriteTime = Date.now();
+};
+
+µMatrix.rawSettingsFromString = function(raw) {
+ var result = {},
+ lineIter = new this.LineIterator(raw),
+ line, matches, name, value;
+ while ( lineIter.eot() === false ) {
+ line = lineIter.next().trim();
+ matches = /^(\S+)(\s+(.+))?$/.exec(line);
+ if ( matches === null ) { continue; }
+ name = matches[1];
+ if ( this.rawSettingsDefault.hasOwnProperty(name) === false ) {
+ continue;
+ }
+ value = (matches[2] || '').trim();
+ switch ( typeof this.rawSettingsDefault[name] ) {
+ case 'boolean':
+ if ( value === 'true' ) {
+ value = true;
+ } else if ( value === 'false' ) {
+ value = false;
+ }
+ break;
+ case 'string':
+ if ( value === '' ) {
+ value = this.rawSettingsDefault[name];
+ }
+ break;
+ case 'number':
+ value = parseInt(value, 10);
+ if ( isNaN(value) ) {
+ value = this.rawSettingsDefault[name];
+ }
+ break;
+ default:
+ break;
+ }
+ if ( this.rawSettings[name] !== value ) {
+ result[name] = value;
+ }
+ }
+ this.saveRawSettings(result);
+};
+
+µMatrix.stringFromRawSettings = function() {
+ var out = [];
+ for ( var key of Object.keys(this.rawSettings).sort() ) {
+ out.push(key + ' ' + this.rawSettings[key]);
+ }
+ return out.join('\n');
+};
+
+/******************************************************************************/
+
// save white/blacklist
µMatrix.saveMatrix = function() {
µMatrix.XAL.keyvalSetOne('userMatrix', this.pMatrix.toString());
diff --git a/src/raw-settings.html b/src/raw-settings.html
new file mode 100644
index 0000000..48c60fa
--- /dev/null
+++ b/src/raw-settings.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+