从网站调用Chrome扩展程序的后台功能

时间:2012-12-08 13:26:18

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

我正在寻找网页内的功能,以激活Chrome扩展程序。

想象一下http://www.example.com/test.html包含:

<script>
hello();
</script>

我的背景页面包含hello函数的定义:

function hello() {
    alert("test");
}

如何在hello致电test.html时确保调用Chrome扩展程序的背景页hello();

3 个答案:

答案 0 :(得分:11)

在网页能够调用后台页面的功能之前,需要解决以下问题:

  1. 能够从网页中使用hello();。这是通过injecting使用内容脚本定义hello的脚本完成的。注入的函数使用自定义事件或postMessage
  2. 与内容脚本进行通信
  3. 内容脚本需要与后台通信。这是通过chrome.runtime.sendMessage实施的 如果网页也需要收到回复:
  4. 从背景页面发送回复(sendMessage / onMessage,见下文)。
  5. 在内容脚本中,创建自定义事件或使用postMessage向网页发送消息。
  6. 在网页中,处理此消息。
  7. 所有这些方法都是异步的,必须通过回调函数来实现。

    这些步骤需要仔细设计。这是一个实现上述所有步骤的通用实现。您需要了解的有关实施的内容:

    • 在要注入的代码中,只要需要联系内容脚本,就使用sendMessage方法。
      用法:sendMessage(<mixed message> [, <function callback>])

    contentscript.js

    // Random unique name, to be used to minimize conflicts:
    var EVENT_FROM_PAGE = '__rw_chrome_ext_' + new Date().getTime();
    var EVENT_REPLY = '__rw_chrome_ext_reply_' + new Date().getTime();
    
    var s = document.createElement('script');
    s.textContent = '(' + function(send_event_name, reply_event_name) {
        // NOTE: This function is serialized and runs in the page's context
        // Begin of the page's functionality
        window.hello = function(string) {
            sendMessage({
                type: 'sayhello',
                data: string
            }, function(response) {
                alert('Background said: ' + response);
            });
        };
    
        // End of your logic, begin of messaging implementation:
        function sendMessage(message, callback) {
            var transporter = document.createElement('dummy');
            // Handles reply:
            transporter.addEventListener(reply_event_name, function(event) {
                var result = this.getAttribute('result');
                if (this.parentNode) this.parentNode.removeChild(this);
                // After having cleaned up, send callback if needed:
                if (typeof callback == 'function') {
                    result = JSON.parse(result);
                    callback(result);
                }
            });
            // Functionality to notify content script
            var event = document.createEvent('Events');
            event.initEvent(send_event_name, true, false);
            transporter.setAttribute('data', JSON.stringify(message));
            (document.body||document.documentElement).appendChild(transporter);
            transporter.dispatchEvent(event);
        }
    } + ')(' + JSON.stringify(/*string*/EVENT_FROM_PAGE) + ', ' +
               JSON.stringify(/*string*/EVENT_REPLY) + ');';
    document.documentElement.appendChild(s);
    s.parentNode.removeChild(s);
    
    
    // Handle messages from/to page:
    document.addEventListener(EVENT_FROM_PAGE, function(e) {
        var transporter = e.target;
        if (transporter) {
            var request = JSON.parse(transporter.getAttribute('data'));
            // Example of handling: Send message to background and await reply
            chrome.runtime.sendMessage({
                type: 'page',
                request: request
            }, function(data) {
                // Received message from background, pass to page
                var event = document.createEvent('Events');
                event.initEvent(EVENT_REPLY, false, false);
                transporter.setAttribute('result', JSON.stringify(data));
                transporter.dispatchEvent(event);
            });
        }
    });
    

    background.js

    chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
        if (message && message.type == 'page') {
            var page_message = message.message;
            // Simple example: Get data from extension's local storage
            var result = localStorage.getItem('whatever');
            // Reply result to content script
            sendResponse(result);
        }
    });
    

    如果没有清单文件,Chrome扩展程序就不完整了,所以这里是我用来测试答案的manifest.json文件:

    {
        "name": "Page to background and back again",
        "version": "1",
        "manifest_version": 2,
        "background": {
            "scripts": ["background.js"]
        },
        "content_scripts": [{
            "matches": ["http://jsfiddle.net/jRaPj/show/*"],
            "js": ["contentscript.js"],
            "all_frames": true,
            "run_at": "document_start"
        }]
    }
    

    此扩展程序在http://jsfiddle.net/jRaPj/show/(包含问题中显示的hello();)进行了测试,并显示了一个对话框,显示“背景说:null”。
    打开背景页面,使用localStorage.setItem('whatever', 'Hello!');查看邮件是否已正确更改。

答案 1 :(得分:2)

扩展

Send messages from web pages内置解决方案

M-x repeat-complex-command

mainfest.json

网页:

"externally_connectable": {
  "matches": ["*://*.example.com/*"]
}

Extension的后台脚本:

// The ID of the extension we want to talk to.
var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";

// Make a simple request:
chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
  function(response) {
    if (!response.success)
      handleError(url);
  });

答案 2 :(得分:1)

不,由于background page(s) architecture

而使用您的上述代码

content scripts

使用内容脚本演示

的manifest.json

注册内容脚本myscripts.js

{
"name": "NFC",
"description": "NFC Liken",
"version": "0.1",
"manifest_version": 2,
"permissions": ["tabs", "http://*/", "https://*/"],
"content_scripts": {
    "matches": "http://www.example.com/*",
    "js": [ "myscript.js"]
  },
"browser_action": {
"default_icon": "sync-icon.png",
"default_title": "I Like I Tag"
}
}

如果您需要更多信息,请与我们联系。