chrome.runtimeのsendMessageとonMessageでハマった

contentとbackgroundの通信でハマった

chrome拡張を開発していている中で content => background => native app => background => contentと通信を行おうとしていました

コードはこんな感じです↓

// content.js

document.addEventListener("fire", event => {
    chrome.runtime.sendMessage(
        {
            "msg": event.detail
        },
        response_from_background => {
            console.log(response_from_background);
        }
    )
});
// background.js

chrome.runtime.onMessage.addListener((message_from_content, sender, sendToContent) => {
    // content.jsから受け取ったmessage_from_contentをnative appに送り、response_from_nativeを受け取る
    chrome.runtime.sendNativeMessage("native-host", message_from_content, response_from_native => {
        sendToContent(response_from_native)
    });
});

content.jsでtype = "fire"のカスタムイベントをlistenして、sendMessageでbackground.jsへメッセージを送ります

background.jsではcontent.jsから送られてきたmessage_from_contentをそのままsendNativeMessageメソッドでネイティブアプリへ送ります

native appから返ってきたresponse_from_nativeをsendToContentでcontent.jsへ返します

content.jsでresponse_from_backgroundを受け取りconsoleへ出力します

以上がやりたかったことです

が、

response_from_backgroundがnullになる

何度やってもbackground.jsからの返り値がnullになってしまいました。

consoleでは以下のようなエラーがでていました

Unchecked runtime.lastError: The message port closed before a response was received.

portが閉じちゃってるっぽい?

解決方法

onMessageでtrueを返してあげるだけでした

// background.js

chrome.runtime.onMessage.addListener((message_from_content, sender, sendToContent) => {
    chrome.runtime.sendNativeMessage("native-host", message_from_content, response_from_native => {
        sendToContent(response_from_native)
    });
    return true  // <= これを追加した
});

理由はきちんと公式に書いてありました

developer.chrome.com

This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).

先にメッセージの送信元にtrueを返してあげないと非同期でメッセージを送ってくることをchromeがわかってくれないんですね

このtrueは非同期でメッセージ送るからsendResponseが呼ばれるまではport空けといてねーっていうtrueです

たった1行足すだけで解決しました。ちゃんと公式は最後まで読まないとダメだな。。。