区块链钱包开发(二)—— 创建manifest文件

111 阅读4分钟

配置文件解析

我们来看一下metamask中manifest文件的定义:

{
  // 浏览器工具栏按钮配置
  "action": {
    // 不同尺寸的图标路径(单位:像素),这是为了适配不同设备和环境
    "default_icon": {
      "16": "images/icon-16.png", 
      "19": "images/icon-19.png", 
      "32": "images/icon-32.png",  
      "38": "images/icon-38.png",   
      "64": "images/icon-64.png",    
      "128": "images/icon-128.png",  
      "512": "images/icon-512.png"   
    },
    "default_title": "MetaMask",     // 鼠标悬停提示文本
    "default_popup": "popup-init.html" // 点击按钮弹出的页面
  },

  // 开发者信息(通常留官网链接)
  "author": "https://metamask.io",

  // 后台服务配置(MV3必须使用Service Worker)
  "background": {
    "service_worker": "scripts/app-init.js" // 后台入口文件
  },

  // 键盘快捷键配置
  "commands": {
    // 旧版API兼容(为了兼容firefox,这里的兼容代码是本人贡献的o(* ̄▽ ̄*)o
    "_execute_browser_action": {
      "suggested_key": {
        "windows": "Alt+Shift+M",
        "mac": "Alt+Shift+M",
        "chromeos": "Alt+Shift+M",
        "linux": "Alt+Shift+M"
      }
    },
    // MV3标准快捷键
    "_execute_action": {             
      "suggested_key": {
        "default": "Alt+Shift+M",
        "windows": "Alt+Shift+M",
        "mac": "Alt+Shift+M",
        "chromeos": "Alt+Shift+M",
        "linux": "Alt+Shift+M"
      }
    }
  },

  // 内容脚本配置(注入到网页的JS)
  "content_scripts": [
    {
      "matches": ["file://*/*", "http://*/*", "https://*/*"], // 注入目标URL模式
      "js": [                                                 // 按顺序注入的脚本,脚本的详细作用后续会讲
        "scripts/disable-console.js",    // 禁用危险API
        "scripts/lockdown-install.js",   // 安全沙箱初始化
        "scripts/lockdown-run.js",       // 执行环境隔离
        "scripts/lockdown-more.js",      // 增强安全策略
        "scripts/contentscript.js"       // 主业务逻辑
      ],
      "run_at": "document_start",  // 注入时机:DOM加载前
      "all_frames": true           // 注入所有iframe
    },
    {  // 特殊处理Trezor硬件钱包,不需要了解
      "matches": ["*://connect.trezor.io/*/popup.html*"],
      "js": ["vendor/trezor/content-script.js"] 
    }
  ],

  // 国际化配置
  "default_locale": "en",         // 默认语言
  "description": "__MSG_appDescription__", // 从_locales目录读取翻译

  // 需要访问的域名白名单(重要!钱包必须包含RPC节点域名)
  "host_permissions": [
    "http://localhost:8545/",     // 本地开发节点
    "file://*/*",                 // 本地文件协议
    "http://*/*",                 // 所有HTTP网站(慎用)
    "https://*/*",                // 所有HTTPS网站
    "ws://*/*",                   // WebSocket连接
    "wss://*/*"                   // 加密WebSocket
  ],

  // 应用图标(用途同action.default_icon但独立配置)
  "icons": {
    "16": "images/icon-16.png",
    "19": "images/icon-19.png", 
    "32": "images/icon-32.png",
    "38": "images/icon-38.png", 
    "48": "images/icon-48.png",
    "64": "images/icon-64.png", 
    "128": "images/icon-128.png",
    "512": "images/icon-512.png" 
  },

  "manifest_version": 3,          // 必须显式声明使用MV3
  "name": "__MSG_appName__",      // 国际化应用名称

  // 可选权限(运行时请求)
  "optional_permissions": ["clipboardRead"], // 读取剪贴板

  // 必须声明的权限(安装时请求)
  "permissions": [
    "activeTab",         // 获取当前标签页权限
    "alarms",           // 定时任务(替代setTimeout)
    "clipboardWrite",    // 写入剪贴板(复制地址)
    "notifications",    // 桌面通知(交易状态提醒)
    "scripting",        // 动态执行脚本(DApp交互)
    "storage",          // 本地存储(用户配置)
    "unlimitedStorage", // 突破5MB存储限制(交易记录)
    "webRequest",       // 网络请求拦截(API签名)
    "offscreen"         // 后台渲染(复杂计算隔离)
  ],

  // 沙箱页面配置(安全隔离)
  "sandbox": {
    "pages": ["snaps/index.html"]  // 高风险功能隔离执行
  },

  // 应用短名称(菜单栏显示)
  "short_name": "__MSG_appName__",

  // 内容安全策略(关键安全配置)
  "content_security_policy": {
    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-ancestors 'none'; font-src 'self';", // 主页面策略
    "sandbox": "sandbox allow-scripts; script-src 'self' 'unsafe-inline' 'unsafe-eval'; object-src 'none'; default-src 'none'; connect-src *; font-src 'self';" // 沙箱页面特殊策略
  },

  // 允许外部网页通信(DApp连接必须)
  "externally_connectable": {
    "matches": ["http://*/*", "https://*/*"],  // 允许连接的网站
    "ids": ["*"]                              // 允许所有扩展ID(钱包互操作)
  },

  // 最低Chrome版本要求(基于API兼容性)
  "minimum_chrome_version": "115"  // 需要Chrome 115+支持wasm等特性
}

以下是 Chrome 扩展中 content_security_policy 配置的详细解析,特别针对区块链钱包开发场景的安全设计:


主扩展页面策略 (extension_pages)

"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'none'; frame-ancestors 'none'; font-src 'self';"

1. script-src 'self' 'wasm-unsafe-eval'

  • 'self'
    只允许加载扩展包内的脚本(如 popup.js, background.js),禁止:

    • 内联脚本(如 <script>alert(1)</script>
    • 远程 CDN 脚本(如 <script src="https://code.jquery.com/jquery.min.js">
  • 'wasm-unsafe-eval'
    允许 WebAssembly 执行(区块链钱包必需):

    // 例如加密库使用 WASM
    const wasmModule = await WebAssembly.compile(wasmBinary);
    

2. object-src 'none'

  • 禁止加载插件内容(如 Flash、Java Applet):
    <!-- 以下内容会被拦截 -->
    <object data="flash.swf"></object>
    <embed src="malicious.pdf">
    

3. frame-ancestors 'none'

  • 防止点击劫持(Clickjacking):
    • 禁止其他网站通过 <iframe> 嵌入你的扩展页面
    • 避免恶意网站诱导用户误操作扩展界面

4. font-src 'self'

  • 仅允许加载扩展包内的字体文件(如 .woff2):
    @font-face {
      src: url(chrome-extension://__EXT_ID__/fonts/main.woff2); /* 允许 */
      src: url(https://fonts.com/risk.woff2); /* 被拦截 */
    }
    

沙箱页面策略 (sandbox)

主要针对Metamask的扩展程序snap做权限限制,这里不做讲解

学习交流请添加vx: gh313061

下期预告:钱包的初始化(入口文件加载)