Skip to content
大纲

NitaiPage 浏览扩展实现

浏览器扩展架构

NitaiPage 的浏览器扩展使用 Manifest V3 标准。其通过使用嵌套 NitaiPage 的 HTML 文件,来实现功能,再在此基础上增加缓存控制功能。

对于 Chromium 扩展

extension/
├── manifest.json          # 清单
├── newtab-ext.html        # 新标签页 HTML
├── newtab-ext.js          # 负责应用页面嵌套和 NitaiPage 与插件之间通信的实现
├── popup-ext.html         # Popup 弹窗 HTML
├── popup-ext.js           # Popup 弹窗脚本
└── content-script.js      # 页面嵌套相关脚本

清单 (manifest.json)

json
{
  "manifest_version": 3,
  "name": "__MSG_appName__",
  "version": "2.0.1",
  "description": "__MSG_appDesc__",
  "default_locale": "zh_CN",
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'; frame-src 'self' https://www.nitai.us.kg https://dev-www.nitai.us.kg"
  },
  "permissions": [
    "declarativeNetRequest",
    "storage",
    "tabs"
  ],
  "action": {
    "default_popup": "popup-ext.html",
    "default_icon": {
      "16": "./favicon.ico",
      "48": "./favicon.ico",
      "128": "./favicon.ico"
    },
    "default_title": "新标签页"
  },
  "chrome_url_overrides": {
    "newtab": "newtab-ext.html"
  },
  "web_accessible_resources": [
    {
      "resources": [
        "*.js"
      ],
      "matches": [
        "https://www.nitai.us.kg/*",
        "https://dev-www.nitai.us.kg/*",
        "https://nfdb.nitai.us.kg/*"
      ]
    }
  ],
  "icons": {
    "16": "./favicon.ico",
    "48": "./favicon.ico",
    "128": "./favicon.ico"
  }
}

对于 Firefox 扩展

与 Chrome 扩展的主要差异

Firefox 扩展在 Chrome 扩展的基础上增加了 FireFox 相关的特定配置:

json
{  "minimum_chrome_version": "88",
  "chrome_settings_overrides": {
    "homepage": "https://www.nitai.us.kg"
  },
  "browser_specific_settings": {
    "gecko": {
      "id": "{XXXXXX}"
    }
  }
}

插件通信

请求

类型: getExtensionUrl

javascript
window.parent.postMessage({
    type: 'getExtensionUrl'
}, '*');

响应

类型: extensionUrlResponse

javascript
{
    type: 'extensionUrlResponse',
    url: 'chrome-extension://[extension-id]/'
}

完整使用示例

javascript
function getExtensionUrl() {
    return new Promise((resolve) => {
        const handler = (event) => {
            if (event.data.type === 'extensionUrlResponse') {
                window.removeEventListener('message', handler);
                resolve(event.data.url);
            }
        };

        window.addEventListener('message', handler);
        window.parent.postMessage({ type: 'getExtensionUrl' }, '*');

        // 超时
        setTimeout(() => {
            window.removeEventListener('message', handler);
            resolve(null);
        }, 1000);
    });
}

(async () => {
    const extensionUrl = await getExtensionUrl();
    const isExtension = extensionUrl !== null;
    
    if (isExtension === true) {
      console.log('当前处于浏览器扩展环境');
      console.log('浏览器扩展 URL:'+ extensionUrl);
    }
})();

Released under the Apache-2.0 License.