【问题标题】:Call background function of Chrome extension from a site从站点调用 Chrome 扩展的后台功能
【发布时间】:2012-11-26 12:07:12
【问题描述】:

我正在寻找网页内的功能以激活 chrome 扩展。

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

<script>
hello();
</script>

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

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

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

【问题讨论】:

  • 不,出于明显的安全原因,您不能这样做。扩展需要有意公开其 API

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


【解决方案1】:

不,因为background page(s) architecture而使用上面的代码

是的,content scripts

使用内容脚本的演示

ma​​nifest.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"
}
}

如果您需要更多信息,请告诉我。

【讨论】:

  • 感谢您的回答。但没有交易.. 我也可以在 myscript.js 函数 clearhist () { var millisecondsPerWeek = 1000 * 60 * 60 * 24 * 7; var oneWeekAgo = (new Date()).getTime() - millisecondsPerWeek; chrome.browsingData.remove({ "since": oneWeekAgo }, { "appcache": true, "cache": true, "cookies": true, "downloads": true, "fileSystems": true, "formData": true ,“历史”:真,“indexedDB”:真,“localStorage”:真,“pluginData”:真,“密码”:真,“webSQL”:真},回调); }
  • @WoutervanReeven:不,您不能将此代码直接放在myscript.js 中,但是您可以通过将其放在background 页面中并通过消息通信间接调用代码来实现这一点。参考THIS如果您需要更多信息,请告诉我
  • 所以需要在后台js脚本中调用javascript函数。在页面example.com/test.html 的html 中做一些事情来调用chrome 扩展里面的脚本。背景 html myscript.js hello();
  • @WoutervanReeven: 是的,把browsing data API 的代码放在background js 中,并通过消息通信从内容脚本中调用函数;更多信息请参考THIS
  • @WoutervanReeven:你不能直接用 hello() 拨打电话;它必须通过消息通信来调用。
【解决方案2】:

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

  1. 能够从网页使用hello();。这是由injecting 使用内容脚本定义hello 的脚本完成的。注入的函数使用自定义事件或postMessage 与内容脚本通信。
  2. 内容脚本需要与后台通信。这是通过chrome.runtime.sendMessage 实现的。
    如果网页也需要接收回复:
  3. 从后台页面发送回复(sendMessage / onMessage,见下文)。
  4. 在内容脚本中,创建自定义事件或使用postMessage 向网页发送消息。
  5. 在网页中,处理此消息。

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

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

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

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!');查看消息是否正确更改。

【讨论】:

  • @Xan chrome.extension.sendMessagechrome.runtime.sendMessage 的别名。您可能对chrome.extension.sendRequest 感到困惑吗?
  • 我并不困惑;但是该功能已完全退役(文档中未提及),但由于旧示例代码挥之不去,因此不断弹出新代码。请参阅this issue 将其标记为已弃用。
【解决方案3】:

Send messages from web pages 的扩展有一个内置解决方案

mainfest.json

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

网页:

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

扩展的后台脚本:

chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    if (sender.url == blacklistedWebsite)
      return;  // don't allow this web page access
    if (request.openUrlInEditor)
      openUrl(request.openUrlInEditor);
  });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-09
    • 2015-03-31
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    相关资源
    最近更新 更多