◆ chrome.runtime.sendMessage で送信
◆ chrome.runtime.onMessage.addListener で受信
◆ content script 送る場合は chrome.tabs.sendMessage 

拡張機能を作ってると background のページと browser action や page action の popup ページと 各ページに埋め込んだ content script の JavaScript 間でデータを受け渡ししたいことがあります

そんなときの メッセージ通信の説明です

extension 内部で通信

まずは単純に background ページと popup ページで通信します
popup を開くとメッセージを送って background からのレスポンスを受け取ります

送る側 (popup.js)
chrome.runtime.sendMessage("めっせぇじ", function (response){
console.log("受け取ったデータ:", response)
})

受け取る側 (background.js)
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
console.log(message)
setTimeout(function(){
sendResponse({a:1,b:2})
}, 5000)
return true
})

console (popup.js)
(5秒後)
Object {a:1, b:2}

console (popup.js)
めっせぇじ

こんな感じです

popup.js に書いた関数は popup が開かれると実行されてメッセージを送ります
background.js は拡張機能がロードされた時に実行されてずっと存在するので リスナはずっとメッセージを監視してくれます

addListener で登録した関数の第一引数が送られてくるデータで 3つ目の引数がデータを返すためのコールバックです
ポイントは 非同期の場合は return true しないといけないところ

この関数が終わるまでに sendResponse を実行するかレスポンスを返さないのなら返り値は気にしないでいいですが 非同期処理が入って 関数の実行が終わったあとに sendResponse が実行される可能性があるなら true を返してそのことを伝えないとダメです

それと sendResponse は引数を 1 つしか渡せません
好きなだけ渡せそうなのですがリファレンスでも
function(any response) {...};
と書かれてます

いっぱい渡してみたのですが sendMessage で登録したコールバック関数の 2 つめ以降の引数は undefined にされてました

メッセージの行き先

メッセージは拡張機能全体に送られます
なので 今回みたいな文字列で送るのではなくて オブジェクトにして type プロパティに目的を書いて必要ないところで受け取ったら何もしないようにします
type じゃなくてもいいのですが 何のためのメッセージですー って目印をつけておかないと複雑にたくさん通信するときに困ります

他の拡張機能にも送れる

chrome.runtime.sendMessage の引数の最初に 文字列で拡張機能の ID を入れるとその拡張機能にメッセージを送ることもできます
ただ 送ったところで 送られた拡張機能に受け取る設定がされてないと意味無いんですけど

メッセージ通信機能のある拡張機能にだと 本来のフォーマットに合わせたメッセージを送って何か処理してもらうという使い方できそうかなーと思ってるけど試してないです

content script と通信

content script からメッセージを送るのなら chrome.runtime.sendMessage でいいのですが content script へメッセージを送るときは chrome.tabs.sendMessage を使うことになります

違いはメッセージの前にタブの ID を入れるだけです
他の拡張機能に送る ID がタブになったものです