You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

现有简单Firefox扩展是否可以改造为Greasemonkey脚本?

结论

你的这款扩展可以改造为Greasemonkey类用户脚本,不过因为底层API权限差异,无法100%复现原扩展的拦截时机和覆盖范围,优先推荐保留扩展形式使用,如果一定要转脚本可以参考下方的改造方案。


核心差异说明

原扩展的核心逻辑依赖Firefox扩展专属的browser.webRequest API,这个API可以在请求响应头返回的第一时间完成拦截、取消操作,拦截覆盖所有网页发起的请求,优先级很高。
而Greasemonkey类用户脚本的运行时机是在页面DOM加载前后,没有直接调用webRequest API的权限,只能通过页面层的拦截手段实现类似效果,拦截范围和及时性都弱于原生扩展。


改造后的用户脚本参考实现

// ==UserScript==
// @name         MIME类型下载拦截
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  拦截非页面类资源下载弹窗、跳转
// @match        *://*/*
// @exclude      *://somesite.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

'use strict';

// 拦截带download属性的a标签跳转下载
document.addEventListener('click', e => {
    const target = e.target.closest('a');
    if (target && target.hasAttribute('download')) {
        e.preventDefault();
        console.log('拦截到download属性的下载请求', target.href);
        return;
    }
}, true);

// 拦截window.open触发的跳转
const originalOpen = window.open;
window.open = function(url) {
    console.log('拦截到window.open请求', url);
    return null;
};

// 拦截fetch请求
const originalFetch = window.fetch;
window.fetch = async function(...args) {
    const response = await originalFetch.apply(this, args);
    const contentType = response.headers.get('content-type');
    const contentDisposition = response.headers.get('content-disposition');
    
    // 复用原扩展的MIME匹配规则
    const needBlock = () => {
        if (contentDisposition) return true;
        if (!contentType) return false;
        if (contentType.startsWith('image')) return false;
        if (contentType.startsWith('text')) return false;
        if (contentType.startsWith('font')) return false;
        if (contentType.startsWith('application/json')) return false;
        if (contentType.startsWith('application/javascript')) return false;
        return true;
    };
    
    if (needBlock()) {
        console.log('拦截到符合规则的fetch请求', args[0]);
        return new Response(null, {status: 204});
    }
    return response;
};

// 拦截XMLHttpRequest请求
const originalXHROpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
    this._url = url;
    this.addEventListener('readystatechange', () => {
        if (this.readyState === 2) {
            const contentType = this.getResponseHeader('content-type');
            const contentDisposition = this.getResponseHeader('content-disposition');
            
            const needBlock = () => {
                if (contentDisposition) return true;
                if (!contentType) return false;
                if (contentType.startsWith('image')) return false;
                if (contentType.startsWith('text')) return false;
                if (contentType.startsWith('font')) return false;
                if (contentType.startsWith('application/json')) return false;
                if (contentType.startsWith('application/javascript')) return false;
                return true;
            };
            
            if (needBlock()) {
                console.log('拦截到符合规则的XHR请求', this._url);
                this.abort();
            }
        }
    });
    return originalXHROpen.apply(this, arguments);
};

两种方案对比

  • 原扩展方案:拦截范围全覆盖、响应速度快、不会漏拦截,唯一缺点是需要单独安装扩展
  • 用户脚本方案:无法拦截浏览器直接跳转的非页面资源请求、部分特殊场景的请求无法覆盖,但是无需单独安装扩展,可以直接在油猴管理器中导入使用

内容的提问来源于stack exchange,提问作者Scorpys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 13:21:04