【问题标题】:Dynamic loading of content script (chrome extension)内容脚本的动态加载(chrome扩展)
【发布时间】:2014-11-01 18:47:56
【问题描述】:

我有一个 chrome 扩展,有 2 个由清单注入的内容脚本和一个后台脚本。

{
    "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(如果应该使用泛型)。

文件太多,逻辑更复杂,所以我不能在"content_scripts"指令中列出所有(url, script)对(我也不想将所有特定文件作为内容脚本注入)。

我在后台尝试过这样的事情(请注意,它仅用于演示):

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

谁能帮我解决这个问题?这是动态“覆盖”函数定义的好方法,还是我应该采用不同的方式(然后是哪一种)。

谢谢。

【问题讨论】:

标签: javascript google-chrome google-chrome-extension content-script


【解决方案1】:

这可能意味着您在扩展/内部页面(弹出?选项页面?分离的开发工具?)上收到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()
  }
});

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

【讨论】:

  • chrome.tabs.executeScript 调用中,传递 sender.tab.id 而不是 tabId。我认为你也可以不传递任何内容。
  • @Xan,chrome.tabs.executeScript 是添加内容脚本的唯一功能吗?还有其他解决方案吗?
  • 是否可以从数据库调用而不是文件中注入作为文本块的内容脚本?具体来说,通过 1) 调用本地托管的 php 脚本,该脚本将从 MySQL 中提取;或 2) 通过直接连接到本地或远程数据库连接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-25
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多