【问题标题】:Content script code is not being executed内容脚本代码未执行
【发布时间】:2019-04-06 01:18:33
【问题描述】:

我查看了其他相关的 SO 帖子,但解决方案没有帮助解决我的问题。这是我的第一个 chrome 扩展,所以请多多包涵!

我正在编写一个简单的 chrome 扩展程序,用于在网页上搜索用户提供的关键字。我无法获取返回要运行的 DOM 内容的内容脚本。一些代码,我取自另一个 SO 帖子中的答案,但我似乎无法让它为我工作。

我在文件顶部放了一个console.log("hello world"),但是没有显示出来,所以我想可能是我项目的结构。

ma​​nifest.json

{
    "name": "keyword search",
    "version": "0.0.1",
    "manifest_version": 2,
    "permissions": [ "tabs" , "storage", "activeTab", "<all_urls>"],
    "browser_action": {
        "default_popup": "html/form.html"
    },
    "content_scripts": [{
        "matches": [ "<all_urls>" ],
        "js": [ "js/jquery.min.js", "content_scripts/content_script.js" ]
    }],
    "homepage_url": "http://google.com/"
}

js/popup.js

function run() {
    running = true;
    console.log('running');

    var url = "https://www.stackoverflow.com/"

    // Get KW & category for search
    chrome.storage.local.get(["kw"],
        function (data) {
            kw = data.kw;

            console.log("redirecting to find kw: " + kw);

            // Send current tab to url
            chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
                chrome.tabs.update(tabs[0].id, {url: url});

                chrome.tabs.sendMessage(tabs[0].id, {type: 'DOM_request'}, searchDOM);
            });
        }
    );
}

function searchDOM(domContent) {
    console.log("beginning dom search \n" + domContent);
}

content_scripts/content_script.js

// Listen for messages
console.log("hello world")
chrome.runtime.onMessageExternal.addListener(function (msg, sender, sendResponse) {
    // If the received message has the expected format...
    if (msg.type === 'DOM_request') {
        // Call the specified callback, passing
        // the web-page's DOM content as argument
        sendResponse(document.all[0].outerHTML);
    }
});

控制台

running
redirecting to find kw: TestKeyword
beginning dom search 
undefined

【问题讨论】:

    标签: google-chrome google-chrome-extension


    【解决方案1】:

    首先,onMessageExternal 是错误的事件(它是针对external messaging):
    你应该使用标准的onMessage

    其次,chrome 扩展 API 是异步的,因此它只注册一个作业,立即返回以继续代码中的下一条语句,而无需等待作业完成:

    1. chrome.tabs.update 将导航加入到新 URL 的队列中
    2. chrome.tabs.sendMessage 将消息发送作业排入队列
    3. 选项卡中的当前页面上下文与正在运行的内容脚本一起被破坏
    4. 标签开始加载新网址
    5. 消息已传递到选项卡,但没有侦听器,
      但是根据各种因素,此步骤可能会在第 2 步之后立即运行,因此在旧页面中运行的内容脚本将收到它,这不是您想要的
    6. 标签加载提供的 HTML 并发出 DOMContentLoaded 事件
    7. 由于默认的"run_at": "document_idle",您的内容脚本会在此之后不久运行

    至少有三种方法可以正确计时:

    • 让您的内容脚本发出一条消息并在弹出窗口中添加一个 onMessage 侦听器
    • 使用 chrome.tabs.onUpdated 等待标签加载
    • 使用 chrome.tabs.onUpdated + chrome.tabs.executeScript 来简化整个事情

    让我们采用 executeScript 方法。

    1. 从 manifest.json 中删除 "content_scripts"
    2. 使用以下代码代替 chrome.tabs.query(不需要):

      chrome.tabs.update({url}, tab => {
        chrome.tabs.onUpdated.addListener(function onUpdated(tabId, change, updatedTab) {
          if (tabId === tab.id && change.status === 'complete') {
            chrome.tabs.onUpdated.removeListener(onUpdated);
            chrome.tabs.executeScript(tab.id, {
              code: 'document.documentElement.innerHTML',
            }, results => {
              searchDOM(results[0]);
            });
          }
        });
      });
      

    【讨论】:

    • 非常感谢!我整天都被困在这上面,你的解决方案奏效了!我对解决方案有点迷茫,但我会更多地研究文档。此外,关于 messageExternal,这是为了解决我在发布之前忘记更正的问题的尝试。我从您对另一篇帖子的回答中获取了解决方案,因此希望您能看到这个问题并做出回应。
    • 我已经更详细地研究了您的解决方案并且现在更清楚地理解它。如果我想将此解决方案扩展为现在让脚本在包含关键字的网站中返回某个链接或 a-tag,我是否必须使用您列出的方法 #1?
    • 这行得通,只需确保code 字符串(或file 参数)以简单表达式结尾,这样它就会被executeScript、example 1example 2 拾取,等等。
    猜你喜欢
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-20
    • 2018-03-21
    • 1970-01-01
    • 2023-03-12
    相关资源
    最近更新 更多