Browse Source

feat: add blacklist

close violentmonkey/violentmonkey#81
Gerald 8 years ago
parent
commit
9f8e4333f6

+ 16 - 0
src/_locales/cs/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Skripty k zálohování
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Zálohovat data skriptu
@@ -390,3 +391,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 16 - 0
src/_locales/de/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Skripte
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Skriptdaten exportieren
@@ -386,3 +387,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 18 - 0
src/_locales/en/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Scripts to export
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Export script data
@@ -386,3 +387,20 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: 'Line no.: '
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: Blacklist updated.
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: Blacklist
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: >-
+    URL matched in this list will not be injected by scripts. Each line is an
+    <code>@exclude</code> rule but globally applied.
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: Save
+labelGeneral:
+  description: Label for general settings.
+  message: General

+ 16 - 0
src/_locales/id/messages.yml

@@ -143,6 +143,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Script untuk ekspor
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Ekspor data script
@@ -392,3 +393,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 16 - 0
src/_locales/pl/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Skrypty do eksportu
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Eksportuj dane skryptu
@@ -388,3 +389,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 16 - 0
src/_locales/ro/messages.yml

@@ -143,6 +143,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Scripturi de exportat
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Exportă datele scripturilor
@@ -392,3 +393,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 16 - 0
src/_locales/ru/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Скрипты для экспорта
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Настройки скрипта
@@ -388,3 +389,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 16 - 0
src/_locales/sr/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Скрипте за извоз
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Извези податке скрипти
@@ -390,3 +391,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 16 - 0
src/_locales/vi/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: Script để xuất
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Xuất dữ liệu script
@@ -388,3 +389,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: ''
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: ''
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: ''
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: ''
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: ''
+labelGeneral:
+  description: Label for general settings.
+  message: ''

+ 16 - 0
src/_locales/zh/messages.yml

@@ -141,6 +141,7 @@ labelDataExport:
 labelScriptsToExport:
   description: Label shown on top of the script list for export.
   message: 要导出的脚本
+  touched: false
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: 导出脚本数据
@@ -388,3 +389,18 @@ labelShowBadge:
 labelLineNumber:
   description: Label for line number jumper.
   message: 行号:
+msgSavedSecurity:
+  description: Message shown when settings of security section are saved.
+  message: 黑名单已更新。
+labelBlacklist:
+  description: Label for global blacklist settings in security section.
+  message: 黑名单
+descBlacklist:
+  description: HTML Description for the global blacklist.
+  message: 此列表匹配的URL将不会被注入脚本。每行都是一条<code>@exclude</code>规则但是将用于全局。
+buttonSaveBlacklist:
+  description: Button to save global blacklist.
+  message: 保存
+labelGeneral:
+  description: Label for general settings.
+  message: 通用

+ 1 - 1
src/background/db.js

@@ -126,7 +126,7 @@ VMDB.prototype.getScriptsByURL = function (url) {
       var require = {};
       var cache = {};
       data.scripts = scripts.filter(function (script) {
-        if (tester.testURL(url, script)) {
+        if (!tester.testBlacklist(url) && tester.testScript(url, script)) {
           data.uris.push(script.uri);
           script.meta.require.forEach(function (key) {
             require[key] = 1;

+ 45 - 16
src/background/utils/tester.js

@@ -1,4 +1,6 @@
-function testURL(url, script) {
+var options = require('../options');
+
+function testScript(url, script) {
   var custom = script.custom;
   var meta = script.meta;
   var inc = [], exc = [], mat = [];
@@ -10,29 +12,35 @@ function testURL(url, script) {
   if (custom.exclude) exc = exc.concat(custom.exclude);
   var ok = !mat.length && !inc.length;
   // @match
-  ok = ok || mat.length && function (test) {
-    return mat.some(test);
-  }(matchTester(url));
+  ok = ok || testMatches(url, mat);
   // @include
-  ok = ok || inc.some(function (str) {
-    return autoReg(str).test(url);
-  });
-  // exclude
-  ok = ok && !exc.some(function (str) {
-    return autoReg(str).test(url);
-  });
+  ok = ok || testRules(url, inc);
+  // @exclude
+  ok = ok && !testRules(url, exc);
   return ok;
 }
 
+function testRules(url, rules) {
+  return rules.some(function (rule) {
+    return autoReg(rule).test(url);
+  });
+}
+function testMatches(url, rules) {
+  if (rules.length) {
+    var test = matchTester(url);
+    return rules.some(test);
+  }
+  return false;
+}
+
 function str2RE(str) {
   return RegExp('^' + str.replace(/([.?\/])/g, '\\$1').replace(/\*/g, '.*?') + '$');
 }
 
 function autoReg(str) {
-  if (/^\/.*\/$/.test(str))
-    return RegExp(str.slice(1, -1));  // Regular-expression
-  else
-    return str2RE(str); // String with wildcards
+  return str.length > 1 && str.charAt(0) === '/' && str.charAt(str.length - 1) === '/'
+    ? RegExp(str.slice(1, -1))  // Regular-expression
+    : str2RE(str);              // String with wildcards
 }
 
 function matchTester(url) {
@@ -72,4 +80,25 @@ function matchTester(url) {
   };
 }
 
-exports.testURL = testURL;
+var testBlacklist = function () {
+  function testBlacklist(url) {
+    return blacklistRE.some(function (re) {
+      return re.test(url);
+    });
+  }
+  function reset(list) {
+    blacklistRE = (list || []).map(function (rule) {
+      return autoReg(rule);
+    });
+  }
+  var blacklistRE = [];
+  reset(options.get('blacklist'));
+  options.hook(function (changes) {
+    var blacklist = changes.blacklist;
+    blacklist && reset(blacklist);
+  });
+  return testBlacklist;
+}();
+
+exports.testScript = testScript;
+exports.testBlacklist = testBlacklist;

+ 30 - 4
src/options/style.css

@@ -21,6 +21,7 @@ h1, h2 {
 }
 button {
   padding: 0 .5rem;
+  font-size: 1rem;
 }
 a {
   color: dodgerblue;
@@ -36,6 +37,7 @@ hr {
   border: none;
   border-top: 1px solid darkgray;
 }
+
 .pull-left {
   float: left;
 }
@@ -59,7 +61,10 @@ hr {
   position: relative;
 }
 .mr-1 {
-  margin-right: 1em;
+  margin-right: .5em;
+}
+.mb-1 {
+  margin-bottom: .5em;
 }
 .h-100 {
   height: 100%;
@@ -196,11 +201,28 @@ aside img {
 .no-pad {
   padding: 0;
 }
-fieldset.title {
-  margin-top: 1rem;
-  padding: .8rem;
+section {
+  position: relative;
+  margin-top: 2rem;
+  padding: 1.2rem .8rem .8rem;
   border: none;
   border-top: 1px solid silver;
+  > h3 {
+    position: absolute;
+    padding: 0 .2rem;
+    top: -.6em;
+    left: .8rem;
+    background: white;
+  }
+  > h4 {
+    margin-bottom: .3rem;
+  }
+  > p {
+    margin-bottom: .3rem;
+  }
+}
+code {
+  background: #F7E999;
 }
 .export-list {
   display: block;
@@ -356,3 +378,7 @@ fieldset.title {
 svg path {
   fill: currentColor;
 }
+
+.text-list {
+  height: 10em;
+}

+ 28 - 16
src/options/views/tab-settings/index.html

@@ -1,22 +1,34 @@
 <div class="content">
   <h1 v-text="i18n('labelSettings')"></h1>
-  <label class="line">
-    <input type=checkbox v-setting="'autoUpdate'" @change="updateAutoUpdate">
-    <span v-text="i18n('labelAutoUpdate')"></span>
-  </label>
-  <label class="line">
-    <input type=checkbox v-setting="'showBadge'">
-    <span v-text="i18n('labelShowBadge')"></span>
-  </label>
-  <label class="line">
-    <input type=checkbox v-setting="'ignoreGrant'">
-    <span v-text="i18n('labelIgnoreGrant')"></span>
-  </label>
-  <label class="line">
-    <input type=checkbox v-setting="'autoReload'">
-    <span v-text="i18n('labelAutoReloadCurrentTab')"></span>
-  </label>
+  <section>
+    <h3 v-text="i18n('labelGeneral')"></h3>
+    <div class="mb-1">
+      <label>
+        <input type=checkbox v-setting="'autoUpdate'" @change="updateAutoUpdate">
+        <span v-text="i18n('labelAutoUpdate')"></span>
+      </label>
+    </div>
+    <div class="mb-1">
+      <label>
+        <input type=checkbox v-setting="'showBadge'">
+        <span v-text="i18n('labelShowBadge')"></span>
+      </label>
+    </div>
+    <div class="mb-1">
+      <label>
+        <input type=checkbox v-setting="'ignoreGrant'">
+        <span v-text="i18n('labelIgnoreGrant')"></span>
+      </label>
+    </div>
+    <div class="mb-1">
+      <label>
+        <input type=checkbox v-setting="'autoReload'">
+        <span v-text="i18n('labelAutoReloadCurrentTab')"></span>
+      </label>
+    </div>
+  </section>
   <vm-import></vm-import>
   <vm-export></vm-export>
   <vm-sync></vm-sync>
+  <vm-blacklist></vm-blacklist>
 </div>

+ 2 - 0
src/options/views/tab-settings/index.js

@@ -3,6 +3,7 @@ var cache = require('src/cache');
 var VmImport = require('./vm-import');
 var VmExport = require('./vm-export');
 var VmSync = require('./vm-sync');
+var VmBlacklist = require('./vm-blacklist');
 
 module.exports = {
   template: cache.get('./index.html'),
@@ -10,6 +11,7 @@ module.exports = {
     VmImport: VmImport,
     VmExport: VmExport,
     VmSync: VmSync,
+    VmBlacklist: VmBlacklist,
   },
   methods: {
     updateAutoUpdate: function () {

+ 8 - 0
src/options/views/tab-settings/vm-blacklist/index.html

@@ -0,0 +1,8 @@
+<section v-feature="'blacklist'">
+  <h3 v-text="i18n('labelBlacklist')">
+    <span class="feature-text"></span>
+  </h3>
+  <p v-html="i18n('descBlacklist')"></p>
+  <textarea class="text-list" v-model="rules"></textarea>
+  <button v-text="i18n('buttonSaveBlacklist')" @click="onSave"></button>
+</section>

+ 25 - 0
src/options/views/tab-settings/vm-blacklist/index.js

@@ -0,0 +1,25 @@
+var _ = require('src/common');
+var cache = require('src/cache');
+var Message = require('src/options/views/message');
+
+module.exports = {
+  template: cache.get('./index.html'),
+  data: function () {
+    var rules = _.options.get('blacklist') || [];
+    return {
+      rules: rules.join('\n'),
+    };
+  },
+  methods: {
+    onSave: function () {
+      var rules = this.rules.split('\n')
+      .map(function (item) {return item.trim();})
+      .filter(Boolean);
+      _.options.set('blacklist', rules);
+      Message.open({
+        text: _.i18n('msgSavedSecurity'),
+      });
+      _.sendMessage({cmd: 'BlacklistReset'});
+    },
+  },
+};

+ 7 - 8
src/options/views/tab-settings/vm-export/index.html

@@ -1,14 +1,13 @@
-<fieldset class=title>
-  <legend v-text="i18n('labelDataExport')"></legend>
-  <strong v-text="i18n('labelScriptsToExport')"></strong>
-  <label>
-    <input type=checkbox v-setting="'exportValues'">
-    <span v-text="i18n('labelExportScriptData')"></span>
-  </label>
+<section>
+  <h3 v-text="i18n('labelDataExport')"></h3>
   <select class=export-list multiple v-model="selectedIds">
     <option class="ellipsis" v-for="script in store.scripts"
       :value="script.id" v-text="script.custom.name||script.meta.name"></option>
   </select>
   <button v-text="i18n('buttonAllNone')" @click="updateSelection()"></button>
   <button v-text="i18n('buttonExportData')" @click="exportData" :disabled="exporting"></button>
-</fieldset>
+  <label>
+    <input type=checkbox v-setting="'exportValues'">
+    <span v-text="i18n('labelExportScriptData')"></span>
+  </label>
+</section>

+ 3 - 3
src/options/views/tab-settings/vm-import/index.html

@@ -1,5 +1,5 @@
-<fieldset class=title>
-  <legend v-text="i18n('labelDataImport')"></legend>
+<section>
+  <h3 v-text="i18n('labelDataImport')"></h3>
   <button v-text="i18n('buttonImportData')" @click="importFile"></button>
   <button :title="i18n('hintVacuum')" @click="vacuum" :disabled="vacuuming" v-text="labelVacuum"></button>
-</fieldset>
+</section>

+ 5 - 3
src/options/views/tab-settings/vm-sync/index.html

@@ -1,6 +1,8 @@
-<fieldset class=title v-feature="'sync'">
-  <legend v-text="i18n('labelSync')" class="feature-text"></legend>
+<section v-feature="'sync'">
+  <h3 v-text="i18n('labelSync')">
+    <span class="feature-text"></span>
+  </h3>
   <div class="sync-services">
     <sync-service v-for="service in store.sync" :service="service" @service-checked="onEnableService"></sync-service>
   </div>
-</fieldset>
+</section>

+ 17 - 17
test/test_background.js

@@ -12,8 +12,8 @@ describe('tester', () => {
           ],
         }
       };
-      assert.ok(tester.testURL('https://www.google.com/', script), 'should match `http | https`');
-      assert.ok(!tester.testURL('file:///Users/Gerald/file', script), 'should not match `file`');
+      assert.ok(tester.testScript('https://www.google.com/', script), 'should match `http | https`');
+      assert.ok(!tester.testScript('file:///Users/Gerald/file', script), 'should not match `file`');
     });
 
     it('should match exact', () => {
@@ -27,10 +27,10 @@ describe('tester', () => {
           ],
         },
       };
-      assert.ok(tester.testURL('http://www.google.com/', script), 'should match `http`');
-      assert.ok(!tester.testURL('https://www.google.com/', script), 'should not match `https`');
-      assert.ok(tester.testURL('file:///Users/Gerald/file', script), 'should match `file`');
-      assert.ok(tester.testURL('ftp://example.com/file', script), 'should match `ftp`');
+      assert.ok(tester.testScript('http://www.google.com/', script), 'should match `http`');
+      assert.ok(!tester.testScript('https://www.google.com/', script), 'should not match `https`');
+      assert.ok(tester.testScript('file:///Users/Gerald/file', script), 'should match `file`');
+      assert.ok(tester.testScript('ftp://example.com/file', script), 'should match `ftp`');
     });
   });
 
@@ -44,9 +44,9 @@ describe('tester', () => {
           ],
         },
       };
-      assert.ok(tester.testURL('https://docs.google.com/', script), 'should match exact domain name');
-      assert.ok(!tester.testURL('https://sub.docs.google.com/', script), 'should not match subdomains');
-      assert.ok(!tester.testURL('https://docs.google.com.cn/', script), 'should not match suffixed domains');
+      assert.ok(tester.testScript('https://docs.google.com/', script), 'should match exact domain name');
+      assert.ok(!tester.testScript('https://sub.docs.google.com/', script), 'should not match subdomains');
+      assert.ok(!tester.testScript('https://docs.google.com.cn/', script), 'should not match suffixed domains');
     });
 
     it('should match subdomains', () => {
@@ -58,10 +58,10 @@ describe('tester', () => {
           ],
         },
       };
-      assert.ok(tester.testURL('https://www.google.com/', script), 'should match subdomains');
-      assert.ok(tester.testURL('https://a.b.google.com/', script), 'should match subdomains');
-      assert.ok(tester.testURL('https://google.com/', script), 'should match specified domain');
-      assert.ok(!tester.testURL('https://www.google.com.hk/', script), 'should not match suffixed domains');
+      assert.ok(tester.testScript('https://www.google.com/', script), 'should match subdomains');
+      assert.ok(tester.testScript('https://a.b.google.com/', script), 'should match subdomains');
+      assert.ok(tester.testScript('https://google.com/', script), 'should match specified domain');
+      assert.ok(!tester.testScript('https://www.google.com.hk/', script), 'should not match suffixed domains');
     });
   });
 
@@ -75,8 +75,8 @@ describe('tester', () => {
           ],
         },
       };
-      assert.ok(tester.testURL('https://www.google.com/', script), 'should match `/`');
-      assert.ok(tester.testURL('https://www.google.com/hello/world', script), 'should match any');
+      assert.ok(tester.testScript('https://www.google.com/', script), 'should match `/`');
+      assert.ok(tester.testScript('https://www.google.com/hello/world', script), 'should match any');
     });
 
     it('should match exact', () => {
@@ -88,8 +88,8 @@ describe('tester', () => {
           ],
         },
       };
-      assert.ok(tester.testURL('https://www.google.com/a/b/c', script), 'should match exact');
-      assert.ok(!tester.testURL('https://www.google.com/a/b/c/d', script), 'should match exact');
+      assert.ok(tester.testScript('https://www.google.com/a/b/c', script), 'should match exact');
+      assert.ok(!tester.testScript('https://www.google.com/a/b/c/d', script), 'should match exact');
     });
   });
 });