创建一个选项卡并在其中注入content-script会产生权限错误

时间:2013-08-04 17:02:35

标签: google-chrome-extension content-script

在我的Chrome扩展程序的后台页面中,我需要执行以下操作:

  1. 创建一个带有html页的标签,该标签位于我的扩展文件夹中或由后台页面动态生成;
  2. 加载新标签后,在其中注入内容脚本以使用消息传递;
  3. 注入脚本后,使用一些数据向新选项卡发送消息。
  4. 这总是变成错误:
    tabs.executeScript:无法访问网址“”的内容。扩展清单必须请求访问此主机的权限。
    或者,如果页面或脚本存储在我的扩展文件夹中的.html和.js专用文件中:
    tabs.executeScript:无法访问网址“chrome-extension://ehdjfh.../page.html”的内容。扩展程序清单必须请求访问此主机的权限。

    执行chrome.tabs.executeScript()并阻止内容脚本注入时会生成错误。 (我需要这个结构将一些大数据传递给选项卡,如果直接作为字符串传递给编码的html网址,它将被截断)

    以下是一个代码示例,可用于测试工作扩展中的行为,只需复制粘贴并在Chrome中加载扩展程序:

    background.js

    chrome.browserAction.onClicked.addListener(function() {
        var getSampleHTML = function() {
            return 'javascript:\'<!doctype html><html>' +
                '<head></head>' +
                '<body>' +
                '<p id="myId">page created...</p>' +
                '</body>' +
                '</html>\'';
        };
    
        // create a new tab with an html page that resides in extension domain:
        chrome.tabs.create({'url': getSampleHTML(), 'active': false}, function(tab){
            var getSampleScript = function() {
                return 'chrome.extension.onRequest.addListener(' +
                    'function(request, sender, sendResponse) {' +
                        'if(request.action == "print_data" && sender.tab.id == ' + tab.id + '){' +
                            'var p = document.getElementById("myId");' +
                            'p += "<br>data received: " + request.data;' +
                        '}' +
                    '});'
                    'document.getElementById("myId").innerHTML += "<br>content-script loaded...";'
            };
            // inject the content-script in the page created:
            chrome.tabs.executeScript(tab.id, {code: getSampleScript()}, function(){
                // send the data to the content-script:
                chrome.tabs.sendRequest(tab.id, {action: "print_data",
                                                 data: "some long data"});
            });
        });
    });
    

    的manifest.json

    {
      "name": "ContentScript Injection Sample",
      "description": "",
      "version": "0.1",
      "permissions": ["tabs"],
      "background": {
        "persistent": false,
        "scripts": ["background.js"]
      },
      "browser_action": {
        "default_title": "open a new tab and inject contentscript"
      },
      "manifest_version": 2
    }
    

1 个答案:

答案 0 :(得分:5)

好吧,这是一个可能的解决方案,感谢@RobW和@方觉指出我的错误(我的错误是考虑将本地网页打开到新创建的标签中作为普通网页,而不是直接访问到chrome.extension API,例如弹出窗口):

<强> background.js

chrome.browserAction.onClicked.addListener(function() {
    // create a new tab with an html page that resides in extension domain:
    chrome.tabs.create({'url': chrome.extension.getURL("page.html"), 
                        'active': false}, function(tab){
        var selfTabId = tab.id;
        chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
            if (changeInfo.status == "complete" && tabId == selfTabId){
                // send the data to the page's script:
                var tabs = chrome.extension.getViews({type: "tab"});
                tabs[0].doSomething("some long data");
            }
        });
    });
});

<强> page.html中

<!doctype html>
<html>
    <head>
    </head>
    <body>
        <p id="myId">page created...</p>
        <script src="page.js" type="text/javascript"></script>
    </body>
</html>

<强> page.js

var alreadyRun = false;
function doSomething(data){
    if (!alreadyRun) {
        var p = document.getElementById("myId");
        p.innerHTML += "<br>data received: " + data;
        // needed because opening eg. DevTools to inpect the page
        // will trigger both the "complete" state and the tabId conditions
        // in background.js:
        alreadyRun = true; 
    }
}
document.getElementById("myId").innerHTML += "<br>script loaded...";

我不喜欢这个解决方案的原因是使用chrome.tabs.onUpdated.addListener()检查创建的选项卡是否已完全加载,并且以这种方式触发任何打开的选项卡状态的任何更改(它是无用的...只是为感兴趣的标签运行检查的方法很棒