【问题标题】:Undefined response from content script in chrome extension来自 chrome 扩展中内容脚本的未定义响应
【发布时间】:2013-11-07 14:15:22
【问题描述】:

我无法从我的内容脚本中获得响应以显示在我的 popup.html 中。当此代码运行并单击查找按钮时,“Hello from response!”打印,但变量响应打印为未定义。最终目标是将当前选项卡的 DOM 放入我的脚本文件中,以便我可以解析它。我正在使用单个时间消息到内容脚本来获取 DOM,但它没有被返回并且显示为未定义。我正在寻找任何可能的帮助。谢谢。

popup.html:

<!DOCTYPE html>
<html>
    <body>
        <head>
        <script src="script.js"></script>
        </head>

        <form >
            Find: <input id="find" type="text"> </input>
        </form>
        <button id="find_button"> Find </button>
    </body>
</html>

manifest.json:

{
    "name": "Enhanced Find",
    "version": "1.0",
    "manifest_version": 2,
    "description": "Ctrl+F, but better",
    "browser_action": {
        "default_icon": "icon.png", 
        "default_popup": "popup.html"
    },
    "permissions": [
        "tabs",
        "*://*/*"
    ],

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

    "content_scripts":[
        {
            "matches": ["http://*/*", "https://*/*"],
            "js": ["content_script.js"],
            "run_at": "document_end"
        }
   ]
}

script.js:

var bkg = chrome.extension.getBackgroundPage();


function eventHandler(){
    var input = document.getElementById("find");
    var text = input.value;
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
        var tab = tabs[0];
        var url = tab.url;
        chrome.tabs.sendMessage(tab.id, {method: "getDocuments"}, function(response){
            bkg.console.log("Hello from response!");
            bkg.console.log(response);
        });

    });
}

content_script.js:

var bkg = chrome.extension.getBackgroundPage();

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
    if(request.method == "getDOM"){
        sendResponse({data : bkg.document});
    }else{
        sendResponse({});
    }
});

【问题讨论】:

  • 对初学者的几点说明: 1.您正在发送消息{method: "getDocuments"},但收听{method: "getDOM"}。 2. 即使消息匹配,您也会将背景页面的文档发回。 3. 您正在运行script.js 的两个独立实例:一个在您的背景页面中,一个在您的弹出窗口中。 4. 你似乎需要把一些术语(如背景页面、弹出窗口、内容脚本)弄清楚。 5. 您正在使用持久性背景页面,而事件页面(非持久性背景页面)同样有效,但明显更加“资源友好”。
  • (也就是说,是的,我会尽快给出一个实际的答案:))
  • 您尝试过我下面提出的解决方案吗?它对你有用吗?

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


【解决方案1】:

您的代码存在很多问题(请参阅我上面的评论)。


先提出一些建议/考虑:

  • 不要将您的内容脚本注入到所有网页中。 Inject programmatically 并且仅在用户想要搜索时。

  • 在内容脚本中直接进行“搜索”可能是一个更好的主意,您可以直接访问 DOM 并对其进行操作(例如,突出显示搜索结果等)。如果您采用这种方法,您可能需要调整您的权限,但始终尽量将它们保持在最低限度(例如,不要使用 tabs,而 activeTab 就足够了,等等)。

  • 请记住,一旦关闭/隐藏弹出窗口(例如,选项卡获得焦点),在弹出窗口上下文中执行的所有 JS 都会中止。

  • 如果您想要某种持久性(甚至是临时性的),例如记住最近的结果或上一个搜索词,您可以使用 chrome.storagelocalStorage 之类的内容。


最后,来自我的扩展演示版的示例代码:

扩展文件组织:

          extension-root-directory/
           |
           |_____fg/
           |      |_____content.js
           |
           |_____popup/
           |      |_____popup.html
           |      |_____popup.js
           |
           |_____manifest.json

ma​​nifest.json:

{
    "manifest_version": 2,
    "name":    "Test Extension",
    "version": "0.0",
    "offline_enabled": true,

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

    "browser_action": {
        "default_title": "Test Extension",
        "default_popup": "popup/popup.html"
    }
}

content.js:

// Listen for message...
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    // If the request asks for the DOM content...
    if (request.method && (request.method === "getDOM")) {
        // ...send back the content of the <html> element
        // (Note: You can't send back the current '#document',
        //  because it is recognised as a circular object and 
        //  cannot be converted to a JSON string.)
        var html = document.all[0];
        sendResponse({ "htmlContent": html.innerHTML });
    }
});

popup.html:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="popup.js"></script>
    </head>
    <body>
        Search:
        <input type="text" id="search" />
        <input type="button" id="searchBtn" value=" Find "
               style="width:100%;" />
    </body>
</html>

popup.js:

window.addEventListener("DOMContentLoaded", function() {
    var inp = document.getElementById("search");
    var btn = document.getElementById("searchBtn");

    btn.addEventListener("click", function() {
        var searchTerm = inp.value;
        if (!inp.value) {
            alert("Please, enter a term to search for !");
        } else {
            // Get the active tab
            chrome.tabs.query({
                active: true,
                currentWindow: true
            }, function(tabs) {
                // If there is an active tab...
                if (tabs.length > 0) {
                    // ...send a message requesting the DOM...
                    chrome.tabs.sendMessage(tabs[0].id, {
                        method: "getDOM"
                    }, function(response) {
                        if (chrome.runtime.lastError) {
                            // An error occurred :(
                            console.log("ERROR: ", chrome.runtime.lastError);
                        } else {
                            // Do something useful with the HTML content
                            console.log([
                                "<html>", 
                                response.htmlContent, 
                                "</html>"
                            ].join("\n"));
                        }
                    });
                }
            });
        }
    });
});

【讨论】:

  • 这个回复中有这么多好的信息,我希望我能投票两次。一个很好的资源是 extensionizr.com,它将构建一个设计正确的扩展框架。
猜你喜欢
  • 2016-01-02
  • 1970-01-01
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-05
  • 2013-03-08
相关资源
最近更新 更多