Chrome扩展程序:何时读取标记

时间:2015-11-05 22:39:24

标签: events google-chrome-extension html-head

我正在编写一个Google Chrome扩展程序,我在其中解析所加载的任何页面的<head>标记,并查找特定的<meta>标记。内容脚本用于与站点通信,然后在后台脚本中完成实际逻辑。

问题是后台脚本应该要求内容脚本检查<meta>标记。 chrome.webNavigation.onDOMContentLoaded似乎是安全的,但我发现通常在加载页面时会多次触发此事件。此外,<head>可能在chrome.webNavigation.onDOMContentLoaded点击之前可用。这一切都让我想到了这个问题:

如何最好地检查页面的<head>部分何时加载?

1 个答案:

答案 0 :(得分:0)

由于您无论如何都要将内容脚本注入所有页面,因此可以在其中完成任务,而不是总是等待页面完全加载(可能需要很长时间,具体取决于连接速度和其他因素)

在文档加载开始时注入内容脚本,并使用document.head附加的MutationObserver在页面加载过程中立即获取结果,因为它已插入DOM 。观察者只会看到HEAD元素的直接子元素,因此不会影响性能。

某些网站可能会在加载页面后添加meta个元素 - 这将被观察者捕获。

  • 的manifest.json:

     "content_scripts": [{
        "matches": ["<all_urls>"],
        "js": ["content.js"],
        "run_at": "document_start"
    }],
    
  • content.js:

    如果存在HEAD,请查找所需的meta元素,否则请等待HEAD插入。

    if (document.head) {
        examineHead();
    } else {
        new MutationObserver(function(mutations) {
            if (document.head) {
                this.disconnect();
                examineHead();
            }
        }).observe(document.documentElement, {childList: true});
    }
    
    function examineHead() {
        var nodes = document.head.getElementsByTagName('meta');
        for (var i = 0; i < nodes.length; i++) {
            var n = nodes[i];
            if (reportMetaNode(n)) {
                return;
            }
        }
        observeHead();
    }
    

    观察document.head并检查每个新元素是否属于那个元素。

    function observeHead() {
        new MutationObserver(function(mutations) {
            for (var i = 0; i < mutations.length; i++) {
                var nodes = mutations[i].addedNodes;
                for (var j = 0; j < nodes.length; j++) {
                    var n = nodes[j];
                    if (n.localName == 'meta') {
                        if (reportMetaNode(n)) {
                            this.disconnect();
                            return;
                        }
                    }
                }
            }
        }).observe(document.head, {childList: true});
    }
    

    例如,让我们查找<meta name="twitter:app:id:googleplay" content="......">并向后台脚本发送一条消息,其值为content

    function reportMetaNode(n) {
        console.log(n, n.outerHTML);
        if (n.name == "twitter:app:id:googleplay") {
            chrome.runtime.sendMessage({gotMeta: n.content});
            return true;
        }
        return false;
    }
    

    您可能还希望处理其他类型的突变,例如characterDataattributes,因为某些网站可能会在单独的步骤中更改或添加元素(createElement,setAttribute,附加子文本节点等等) ),在这种情况下,观察者回调会更复杂,subtree: true参数中需要observe()