从站点调用 Chrome 扩展的后台功能 [英] Call background function of Chrome extension from a site

查看:16
本文介绍了从站点调用 Chrome 扩展的后台功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在网页中寻找一个功能来激活 chrome 扩展.

I am looking for a function inside a webpage te activate a chrome extension.

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

<script>
hello();
</script>

而我的后台页面包含了hello函数的定义:

And my background page contains the definition of the hello function:

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

如何确保在 test.html 调用 hello(); 时,Chrome 扩展程序的后台页面的 hello 被调用?>

How can I make sure that the Chrome extension's background page's hello is called when test.html calls hello();?

推荐答案

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

Before a web page is able to call a background page's function, the following problems need to be solved:

  1. 能够从网页中使用 hello();.这是由 注入 使用内容脚本定义 hello 的脚本.注入的函数使用自定义事件或 postMessage 与内容脚本通信.
  2. 内容脚本需要与后台通信.这是通过 chrome.runtime.sendMessage 实现的.
    如果网页也需要接收回复:
  3. 从后台页面发送回复(sendMessage/onMessage,见下文).
  4. 在内容脚本中,创建自定义事件或使用 postMessage 向网页发送消息.
  5. 在网页中,处理此消息.
  1. Be able to use hello(); from a web page. This is done by injecting a script defining hello using Content scripts. The injected function communicates with the content script using a custom event or postMessage.
  2. The content script needs to communicate with the background. This is implemented through chrome.runtime.sendMessage.
    If the web page needs to receive a reply as well:
  3. Send a reply from the background page (sendMessage / onMessage, see below).
  4. In the content script, create a custom event or use postMessage to send a message to the web page.
  5. In the web page, handle this message.

所有这些方法都是异步的,必须通过回调函数来实现.

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

These steps need to be designed carefully. Here's a generic implementation which implements all of the above steps. What you need to know about the implementation:

  • 在要注入的代码中,只要需要联系内容脚本,就使用 sendMessage 方法.
    用法:sendMessage(<混合消息>[,<函数回调>])

contentscript.js

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);
        });
    }
});

背景.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 文件:

A Chrome extension is not complete without a manifest file, so here's the manifest.json file which I used to test the answer:

{
    "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(); 如问题中所见),并显示一个对话框,上面写着背景说:空".
打开后台页面,使用localStorage.setItem('whatever', 'Hello!');查看消息是否正确修改.

This extension was tested at http://jsfiddle.net/jRaPj/show/ (containing hello(); as seen in the question), and shows a dialog saying "Background said: null".
Open the background page, use localStorage.setItem('whatever', 'Hello!'); to see that the message is correctly changed.

这篇关于从站点调用 Chrome 扩展的后台功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆