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

Chrome扩展activeTab权限跨域页面onUpdate执行脚本时失效问题

问题:跨域名导航后activeTab权限失效导致tabCapture失败

我的背景脚本通过chrome.tabs.onUpdated监听页面加载完成(changeInfo.status === 'complete'),从local storage检查录制状态,若为true则注入reloaded.js。reloaded.js会打开包含test.js的test.html iframe,test.js直接调用tabCapture进行屏幕录制。

当用户在https://example.com启动扩展后导航到https://example.com/foo时一切正常,但跳转到https://chromium.org时权限被收回,触发报错:

Unchecked runtime.lastError: Extension has not been invoked for the current page (see activeTab permission). Chrome pages cannot be captured

调研后发现:当URL从原域名变更到其他域名且用户未在新页面触发扩展操作时,activeTab权限无法生效。请问该如何解决?


附带代码

manifest.json

{
    "manifest_version": 3,
    "name": "Appoq",
    "version": "1.0",
    "description": "Description of my extension",
    "permissions": ["scripting", "activeTab", "tabs", "tabCapture", "storage"],
    "action": {
      "default_popup": "popup.html",
      "default_title": "Click Me"
       
    },
    "background": {
        "service_worker": "background.js"
    },
    "host_permissions": ["<all_urls>"],
    "web_accessible_resources": [
        {
          "resources": [ "tabcapture.html", "/reload/test.html" ],
          "matches": [ "<all_urls>" ]
        }
    ]
}

background.js

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status === 'complete') {
        chrome.storage.local.get('sharingEnabled', function(result) {
            if (result.sharingEnabled == 'recording') {
                chrome.scripting.executeScript({
                    target: {
                        tabId: tabId
                    },
                    files: ['reloaded.js'],
                }, () => {});
            }
        })
    }
})

test.js

chrome.tabs.query({ active: true, currentWindow: true }, function(tabsw) {
    const currentTabId = tabsw[0].id;
    console.log("Current tab ID is: " + currentTabId);
    chrome.tabCapture.getMediaStreamId({ consumerTabId: currentTabId }, (streamId) => {
        console.log(streamId)
        chrome.scripting.executeScript({
            files: ["content.js"],
            target: {tabId: currentTabId}
        }, function () {
            chrome.tabs.sendMessage(currentTabId, {reloadStreamId: streamId, hello: "getReloadStreamId"});
        });
    });
});

解决方案

方法1:请求全局页面权限(简单但不推荐)

将activeTab权限替换为<all_urls>,添加到permissions数组中。这样扩展对所有页面拥有持久权限,无需用户触发即可操作。但缺点是权限范围过大,不符合最小权限原则,可能导致审核不通过。

方法2:通过用户交互重新获取activeTab权限

当检测到跨域名跳转且录制状态为开启时,引导用户主动触发扩展操作以重新获取权限:

  1. 在background.js中,对比当前页面域名与上次存储的域名,判断是否跨域名跳转。如果是,设置扩展图标徽章提示用户点击。
  2. 在popup.js中监听用户点击事件,此时因用户主动交互,activeTab权限会被授予当前页面,重新执行录制逻辑。

修改后的background.js示例:

chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
    if (changeInfo.status === 'complete') {
        const { sharingEnabled } = await chrome.storage.local.get('sharingEnabled');
        if (sharingEnabled === 'recording') {
            const { lastDomain } = await chrome.storage.local.get('lastDomain');
            const currentDomain = new URL(tab.url).hostname;
            
            if (lastDomain && lastDomain !== currentDomain) {
                chrome.action.setBadgeText({ tabId, text: '!' });
                chrome.action.setTitle({ tabId, title: '点击重新激活录制' });
            } else {
                await chrome.scripting.executeScript({
                    target: { tabId },
                    files: ['reloaded.js'],
                });
            }
            await chrome.storage.local.set({ lastDomain: currentDomain });
        }
    }
});

popup.js示例:

document.addEventListener('DOMContentLoaded', async () => {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    const { sharingEnabled } = await chrome.storage.local.get('sharingEnabled');
    
    if (sharingEnabled === 'recording') {
        await chrome.scripting.executeScript({
            target: { tabId: tab.id },
            files: ['reloaded.js'],
        });
        chrome.action.setBadgeText({ tabId: tab.id, text: '' });
    }
});

方法3:改用桌面捕获API(推荐)

使用chrome.desktopCapture.chooseDesktopMedia替代tabCapture,该API无需activeTab权限,只需添加desktopCapture权限。用户需要手动选择录制目标,但可彻底避免跨域名权限问题。

修改manifest.json添加权限:

"permissions": ["scripting", "tabs", "desktopCapture", "storage"],

修改test.js逻辑:

chrome.tabs.query({ active: true, currentWindow: true }, function(tabsw) {
    const currentTabId = tabsw[0].id;
    chrome.desktopCapture.chooseDesktopMedia(['tab'], (streamId) => {
        if (!streamId) return;
        chrome.scripting.executeScript({
            files: ["content.js"],
            target: { tabId: currentTabId }
        }, () => {
            chrome.tabs.sendMessage(currentTabId, { reloadStreamId: streamId, hello: "getReloadStreamId" });
        });
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:53:21