内容脚本的动态加载(Chrome扩展)

7
我有一个Chrome扩展程序,其中包含两个由清单注入的内容脚本和一个后台脚本。
{
    "manifest_version": 2,
    "name": "Test",
    "permissions": [
        "tabs", "<all_urls>", "activeTab", "storage" 
    ],

    "content_scripts": [
        {
            "matches": ["http://*/*", "https://*/*"],
            "js": [
                   "content/autofill/lib_generic.js",
                   "content/autofill/lib.js"],
            "run_at": "document_end"
        }
    ],

  "web_accessible_resources": [
        "content/specific_scripts/*"
    ],

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

}

lib_generic.js包含一个名为apply_forms(...)的函数(它的描述不重要)。该函数从lib.js文件调用。但是,这个过程在几个页面上无法正常工作,因此对于每个这样的页面,我都有一个特殊的脚本 - 也只有一个名为apply_forms(...)的函数。

我有一个函数,它以当前域作为输入并返回所需特定脚本的名称,或者如果应使用通用脚本,则返回false

由于文件太多且逻辑更加复杂,因此我不能仅列出所有(url, script)对于"content_scripts"指令(我也不想将所有特定文件注入为内容脚本)。

我尝试在后台执行以下操作(请注意,这仅用于演示):

var url = ""; //url of current tab

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if(changeInfo.status == "complete") {
        var filename = getSpecificFilename(url);
        chrome.tabs.executeScript(tabId, {file: filename}, function() {
            //script injected
        });
    }
});

注意:getSpecificFilename(...)将始终返回一个名称。

但是在第5行我得到了Unchecked runtime.lastError while running tabs.executeScript: Cannot access a chrome:// URL

有人能帮我解决这个问题吗?这是动态“覆盖”函数定义的好方法,还是应该走另一条路(那么哪条)。

谢谢。


在运行tabs.executeScript时出现未经检查的runtime.lastError:无法访问chrome:// URL。请参考https://dev59.com/rGMk5IYBdhLWcg3wtQBd。 - kol
1个回答

6
这可能意味着你正在扩展程序/内部页面(弹出窗口?选项页面?分离式开发工具?)上收到了一个“onUpdated”事件。其中一种选择是按URL进行过滤:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if(changeInfo.status == "complete") {
        if(!tab.url.match(/^http/)) { return; } // Wrong scheme
        var filename = getSpecificFilename(url);
        chrome.tabs.executeScript(tabId, {file: filename}, function() {
            //script injected
        });
    }
});

另一种(也许更好的)选择是使您的内容脚本请求此注入:
// content script
chrome.runtime.sendMessage({injectSpecific : true}, function(response) {
  // Script injected, we can proceed
  if(response.done) { apply_forms(/*...*/); }
  else { /* error handling */ }
});

// background script
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
  if(message.injectSpecific){
    var filename = getSpecificFilename(sender.url);
    chrome.tabs.executeScript(sender.tab.id, {file: filename}, function() {
      sendResponse({ done: true });
    });
    return true; // Required for async sendResponse()
  }
});

这样你就知道内容脚本被注入和启动了。

1
chrome.tabs.executeScript调用中,传递sender.tab.id而不是tabId。我认为你也可以尝试不传递任何参数。 - benmccallum
@Xan,chrome.tabs.executeScript是添加内容脚本的唯一函数吗?还有其他解决方案吗? - Pacerier
是否可以注入一个内容脚本,该脚本是从数据库调用的文本块,而不是从文件中获取的?具体来说,通过1)类似于调用本地托管的php脚本,从MySQL中提取;或2)通过直接连接到本地或远程数据库连接。 - There

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接