搜索

首页  >  问答  >  正文

重新注入内容脚本:Chrome扩展程序升级或安装后的必要步骤

<p>在安装或升级我正在开发的Chrome扩展程序后,内容脚本(在清单中指定)不会被重新注入,因此需要刷新页面才能使扩展程序正常工作。有没有办法强制重新注入脚本?</p> <p>我相信我可以通过以编程方式将它们从清单中移除,然后在后台页面处理要注入的页面来再次注入它们,但这不是一个好的解决方案。</p> <p>我不想自动刷新用户的标签页,因为这可能会丢失一些数据。Safari在安装或升级扩展程序时会自动刷新所有页面。</p>
P粉066224086P粉066224086460 天前573

全部回复(2)我来回复

  • P粉807239416

    P粉8072394162023-08-25 11:24:31

    唯一的方法强制注入内容脚本而不刷新页面是通过编程注入。

    您可以使用Chrome浏览器的标签API获取所有标签,并向它们注入代码。 例如,您可以将一个版本号存储在本地存储中,并在每次检查背景页中的版本号是否过旧时(如果是),您可以获取所有活动标签并通过编程方式注入您的代码,或者任何其他可以确保扩展程序已更新的解决方案。

    使用以下代码获取所有标签:
    chrome.tabs.query

    并向所有页面注入您的代码
    chrome.tabs.executeScript(tabId, {file: "content_script.js"});

    回复
    0
  • P粉158473780

    P粉1584737802023-08-25 00:54:45

    有一种方法可以在升级后使内容脚本重的扩展继续正常工作,并在安装后立即使其生效。

    安装/升级

    安装的方法是简单地遍历所有窗口中的所有标签,并在具有匹配URL的标签中以编程方式注入一些脚本。

    ManifestV3

    manifest.json:

    "background": {"service_worker": "background.js"},
    "permissions": ["scripting"],
    "host_permissions": ["<all_urls>"],
    

    这些host_permissions应与内容脚本的matches相同。

    background.js:

    chrome.runtime.onInstalled.addListener(async () => {
      for (const cs of chrome.runtime.getManifest().content_scripts) {
        for (const tab of await chrome.tabs.query({url: cs.matches})) {
          chrome.scripting.executeScript({
            target: {tabId: tab.id},
            files: cs.js,
          });
        }
      }
    });
    

    这是一个简化的示例,不处理框架。您可以使用getAllFrames API并自己匹配URL,参见匹配模式的文档。

    ManifestV2

    显然,您必须在manifest.json中声明的background pageevent page脚本中执行此操作:

    "background": {
        "scripts": ["background.js"]
    },
    

    background.js:

    // Add a `manifest` property to the `chrome` object.
    chrome.manifest = chrome.runtime.getManifest();
    
    var injectIntoTab = function (tab) {
        // You could iterate through the content scripts here
        var scripts = chrome.manifest.content_scripts[0].js;
        var i = 0, s = scripts.length;
        for( ; i < s; i++ ) {
            chrome.tabs.executeScript(tab.id, {
                file: scripts[i]
            });
        }
    }
    
    // Get all windows
    chrome.windows.getAll({
        populate: true
    }, function (windows) {
        var i = 0, w = windows.length, currentWindow;
        for( ; i < w; i++ ) {
            currentWindow = windows[i];
            var j = 0, t = currentWindow.tabs.length, currentTab;
            for( ; j < t; j++ ) {
                currentTab = currentWindow.tabs[j];
                // Skip chrome:// and https:// pages
                if( ! currentTab.url.match(/(chrome|https):\/\//gi) ) {
                    injectIntoTab(currentTab);
                }
            }
        }
    });
    

    历史趣闻

    在古老的Chrome 26及更早版本中,内容脚本可以恢复与后台脚本的连接。这在2013年被修复http://crbug.com/168263。您可以在此答案的早期版本中看到此技巧的示例。

    回复
    0
  • 取消回复