Webページが背景ページの関数を呼び出すことが可能である前に、次のような問題を解決する必要があります
- は、Webページから
hello();
を使用することができます。これは、コンテンツスクリプトを使用してhello
を定義するスクリプトinjectingによって行われます。注入された機能は、カスタムイベントまたはpostMessage
を使用してコンテンツスクリプトと通信します。
- コンテンツスクリプトは、背景と通信する必要があります。これは
chrome.runtime.sendMessage
によって実装されています。
Webページは、同様の回答を受信する必要がある場合:
- は、背景ページからの応答を送信します(
sendMessage
/onMessage
、以下を参照してください)。
- コンテンツスクリプトでカスタムイベントを作成するか、
postMessage
を使用してWebページにメッセージを送信します。
- Webページで、このメッセージを処理します。
これらのメソッドはすべて非同期であり、コールバック関数を使用して実装する必要があります。
これらの手順は慎重に設計する必要があります。上記のすべての手順を実装する一般的な実装です。コード・ツー・-注入することで
- を、コンテンツスクリプトを接触させる必要があるとき
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);
}
});
A 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"
}]
}
この拡張は、質問で見たようにhello();
を含むhttp://jsfiddle.net/jRaPj/show/でテストされ、 "Background said:null"というダイアログが表示されます。
背景ページを開き、localStorage.setItem('whatever', 'Hello!');
を使用して、メッセージが正しく変更されていることを確認します。
いいえ、あなたがCA明らかなセキュリティ上の理由からではありません。拡張機能でAPIを公開する必要があります – Bergi