ハマって調べてたらあまり言及されてなかったようなのでメモ。
やりたかったこと
content scriptとevent pageでやり取りしたかったので、chrome.runtime.sendMessageとかchrome.runtime.onMessageとか使ってみたけどうまくいかなかった。
やったこと
まずやってみたのは、sendMessageのリファレンスでは同じExtension内ならidが不要とあったので、id無しでやりとりしてみた。
chrome.runtime.sendMessage({method: 'greeting', body: 'hello'}, function(response) {
console.log(response);
});
console.log('test'); //test
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request.body);
sendResponse('Hello!');
});
この場合、Developer ToolsのConsoleを見るとエラーが出た。悲しい。
Uncaught Error: chrome.runtime.connect() called from a webpage must specify an Extension ID (string) for its first argument(…)
この時点でなんかおかしいよな~とは思ってたけど、とりあえずExtensionのidを指定してみることに。
var id = 'abcdefghijklmnopqrstuvwxyz';
chrome.runtime.sendMessage(id, {method: 'greeting', body: 'hello'}, function(response) {
console.log(response); //undefined
});
console.log('test'); //test
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request.body); //呼ばれない
sendResponse('Hello!'); //勿論呼ばれない
});
この場合は上記のような結果になりました。ちゃんとidも指定したし、そもそもonMessageが働いてないのはどういうことか……と思い完全に頭を抱えていました。
結果
ググった結果、stackoverflowにそれっぽい回答がいくつかありました。
Gmail Chrome Extension “chrome.extension” undefined
Why is chrome.runtime undefined?
Building a Chrome Extension - Inject code in a page using a Content script
だいたい「Chrome API使わない時はInjectした方がいいけど、使いたいならInjectしないかちょっとしたハックしないとダメだよ」みたいなことが書いてある気がします(英語力……)。
そこまで追加したい機能でもなかったので実際には試していませんが、困っている人が簡単に辿り着ければ……と思い書き留めておきます。
蛇足
onMessageは動いてるけどresponseがundefinedになる!という方は、onMessage.addListener内で非同期処理を行っている場合が考えられます。
その場合は、return true;
してやれば良いみたいなのでお試しあれ。
公式リファレンスに一応太文字で書いてあります。