Quellcode durchsuchen

feat: make exposing via window.external optional

tophf vor 6 Jahren
Ursprung
Commit
ee1a86ab3d

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

@@ -290,6 +290,9 @@ labelExcludeMatch:
 labelExportScriptData:
   description: Option to export script data along with scripts.
   message: Export script data
+labelExposeStatus:
+  description: Option in advanced settings.
+  message: 'Expose installed version on userscript catalog sites: $1'
 labelFeedback:
   description: Label of link to feedback page.
   message: Feedback

+ 29 - 5
src/background/index.js

@@ -1,5 +1,6 @@
 import { sendCmd } from '#/common';
 import { TIMEOUT_24HOURS, TIMEOUT_MAX } from '#/common/consts';
+import { forEachEntry, objectSet } from '#/common/object';
 import ua from '#/common/ua';
 import * as sync from './sync';
 import { commands } from './utils';
@@ -21,11 +22,32 @@ import './utils/tester';
 import './utils/update';
 
 let isApplied;
+const expose = {};
+
+const optionHandlers = {
+  autoUpdate,
+  expose(val) {
+    val::forEachEntry(([site, isExposed]) => {
+      expose[decodeURIComponent(site)] = isExposed;
+    });
+  },
+  isApplied(val) {
+    isApplied = val;
+  },
+  [SCRIPT_TEMPLATE](val, changes) {
+    resetScriptTemplate(changes);
+  },
+};
 
 hookOptions((changes) => {
-  if ('autoUpdate' in changes) autoUpdate();
-  if ('isApplied' in changes) isApplied = changes.isApplied;
-  if (SCRIPT_TEMPLATE in changes) resetScriptTemplate(changes);
+  changes::forEachEntry(function processChange([key, value]) {
+    const handler = optionHandlers[key];
+    if (handler) {
+      handler(value, changes);
+    } else if (key.includes('.')) {
+      objectSet({}, key, value)::forEachEntry(processChange);
+    }
+  });
   sendCmd('UpdateOptions', changes);
 });
 
@@ -40,7 +62,9 @@ Object.assign(commands, {
   async GetInjected(_, src) {
     const { frameId, tab, url } = src;
     if (!frameId) resetValueOpener(tab.id);
-    const res = {};
+    const res = {
+      expose: !frameId && url.startsWith('https://') && expose[url.split('/', 3)[2]],
+    };
     if (isApplied) {
       const data = await getInjectedScripts(url, tab.id, frameId);
       addValueOpener(tab.id, frameId, data.withValueIds);
@@ -111,7 +135,7 @@ function autoUpdate() {
 
 initialize(() => {
   browser.runtime.onMessage.addListener(handleCommandMessage);
-  isApplied = getOption('isApplied');
+  ['expose', 'isApplied'].forEach(key => optionHandlers[key](getOption(key)));
   setTimeout(autoUpdate, 2e4);
   sync.initialize();
   checkRemove();

+ 4 - 0
src/common/options-defaults.js

@@ -9,6 +9,10 @@ export default {
   /** @type 'unique' | 'total' | '' */
   showBadge: 'unique',
   exportValues: true,
+  expose: { // use percent-encoding for '.'
+    'greasyfork%2Eorg': true,
+    'sleazyfork%2Eorg': false,
+  },
   closeAfterInstall: false,
   trackLocalFile: false,
   autoReload: false,

+ 1 - 0
src/injected/content/index.js

@@ -38,6 +38,7 @@ const { split } = String.prototype;
   bridge.post = bindEvents(contentId, webId, bridge.onHandle, global.cloneInto);
   bridge.isFirefox = data.isFirefox;
   if (data.scripts) injectScripts(contentId, webId, data, isXml);
+  if (data.expose) bridge.post('Expose');
   isPopupShown = data.isPopupShown;
   sendSetPopup();
 })().catch(IS_FIREFOX && console.error); // Firefox can't show exceptions in content scripts

+ 12 - 16
src/injected/web/index.js

@@ -35,9 +35,6 @@ export default function initialize(
         bridge.post('Pong');
       },
     });
-    if (window.location.host === 'greasyfork.org' || window.location.host === 'sleazyfork.org') {
-      exposeVM();
-    }
   }
   bridge.load = new Promise(resolve => {
     // waiting for the page handlers to run first
@@ -68,6 +65,18 @@ bridge.addHandlers({
       }
     }
   },
+  Expose() {
+    const Violentmonkey = {};
+    defineProperty(Violentmonkey, 'version', {
+      value: process.env.VM_VER,
+    });
+    defineProperty(Violentmonkey, 'isInstalled', {
+      value: (name, namespace) => bridge.send('CheckScript', { name, namespace }),
+    });
+    defineProperty(window.external, 'Violentmonkey', {
+      value: Violentmonkey,
+    });
+  },
 });
 
 function createScriptData(item) {
@@ -97,16 +106,3 @@ async function onCodeSet(item, fn) {
   }
   wrapGM(item)::fn(logging.error);
 }
-
-function exposeVM() {
-  const Violentmonkey = {};
-  defineProperty(Violentmonkey, 'version', {
-    value: process.env.VM_VER,
-  });
-  defineProperty(Violentmonkey, 'isInstalled', {
-    value: (name, namespace) => bridge.send('CheckScript', { name, namespace }),
-  });
-  defineProperty(window.external, 'Violentmonkey', {
-    value: Violentmonkey,
-  });
-}

+ 14 - 0
src/options/views/tab-settings/index.vue

@@ -84,6 +84,15 @@
             <a class="ml-1" href="https://violentmonkey.github.io/posts/inject-into-context/" target="_blank" rel="noopener noreferrer" v-text="i18n('learnInjectionMode')"></a>
           </label>
         </div>
+        <div class="mb-1">
+          <locale-group i18n-key="labelExposeStatus">
+            <label v-for="([key, host]) in expose" :key="host" class="mr-1 valign-tb">
+              <setting-check :name="`expose.${key}`"/>
+              <span v-text="host" class="mr-1"/>
+              <a :href="`https://${host}`" target="_blank" rel="noopener noreferrer">&nearr;</a>
+            </label>
+          </locale-group>
+        </div>
       </section>
       <vm-editor />
       <vm-template />
@@ -162,6 +171,7 @@ export default {
   data() {
     return {
       showAdvanced: false,
+      expose: null,
       settings,
       injectIntoOptions,
     };
@@ -183,6 +193,7 @@ export default {
       this.revokers.push(hookSetting(name, val => { settings[name] = normalize(val); }));
       this.$watch(() => settings[name], debounce(this.getUpdater(item), 300));
     });
+    this.expose = Object.keys(options.get('expose')).map(k => [k, decodeURIComponent(k)]);
   },
   beforeDestroy() {
     this.revokers.forEach((revoke) => { revoke(); });
@@ -198,6 +209,9 @@ export default {
     > * {
       vertical-align: middle;
     }
+    &.valign-tb * {
+      vertical-align: text-bottom;
+    }
   }
   textarea {
     height: 10em;