chromeで拡張機能を作るその3(MessagingHostを使ってMessageBoxを出してみる)

# はじめに
業務の中で拡張機能を触ることが多いのですが、一から作ったことが無かったことと、V2とV3の違いがしっかり分かっていなかったため、復習がてら記事にまとめようと思います。

その2の続きです。
https://qiita.com/spc_knakano/private/6cde2a9b9a8a515d8801
その1
https://qiita.com/spc_knakano/private/8f518af2770cca13520a

## 今回のゴール
簡単にMessagingHost経由でMessageBoxを出す

## 目次
1. MessagingHostとは？
1. sampleapp.cpp
1. background.js
1. manifest.json
1. 結果
1. 参考文献

## 作成環境

OS: Windows 11 Pro 23H2
chrome: 133.0.6943.142
VSCode: 1.97.2

## 1. MessagingHostとは？
ブラウザの拡張機能がユーザーのデバイスにインストールされているネイティブアプリケーションと通信するための仕組みのことです。
Chrome拡張機能がネイティブアプリケーションと通信する際に、MessagingHostを使用してメッセージを送受信します。

## 2. sampleapp.cpp
```cpp
#include "stdafx.h"
#include <iostream>
#include <Windows.h>

using namespace std;

int _tmain(int argc, _TCHAR* argv[]) {
    string InputStr = "";
    unsigned int c, i, t = 0;
    bool BCommunicationEnds = false;
    try
    {
        do
        {
            // 初期化
            InputStr = "";
            t = 0;

            // データ読み込み
            cin.read(reinterpret_cast<char*>(&t), 4);
            for (i = 0; i < t; i++)
            {
                c = getchar();
                if (c == EOF)
                {
                    BCommunicationEnds = true;
                    i = t;
                }
                else
                {
                    InputStr += c;
                }
            }
            auto lpstr = InputStr.c_str();
            int len = MultiByteToWideChar(CP_UTF8, 0, lpstr, -1, NULL, 0);
            std::wstring wstr(len, L'\0');
            MultiByteToWideChar(CP_UTF8, 0, lpstr, -1, &wstr[0], len);
            MessageBoxW(NULL, wstr.c_str(), L"test", MB_OK);
        }
        while (!BCommunicationEnds);
    }
    catch (...)
    {
    }
}
```
拡張機能からメッセージを受け取ったらMessageBoxに表示するアプリケーションです。
MessageBoxAだと文字化けしてしまったため、MultiByteToWideCharを使用してMessageBoxWで表示しています。

## 3. background.js
```javascript
var path = "https://sciencepark.co.jp";

/// 通知のテンプレート作成
var opt = {
    type: "basic",
    title: "notification",
    iconUrl: "icon.png",
    message: "サイエンスパークのHPです",
};
var bool = true;

/// アプリケーションに接続
var port = chrome.runtime.connectNative('sampleapp');

function changeNotification(){
    chrome.storage.local.get((items) => {
        var option = !!items["option"];
        if (option) {
            bool = true;
            port.onMessage.addListener(function (msg) {
                console.log('Received' + msg);
            });
        } else {
            bool = false;
            port.onDisconnect.addListener(function () {
                console.log('Disconnected');
            });
        }
    });
}

chrome.tabs.onActivated.addListener(function (activeInfo) {
    chrome.tabs.get(activeInfo.tabId, tab => {
        var url = tab.url;
        changeNotification();
        if(bool){
            if(url.indexOf(path) === 0){
                chrome.notifications.create(opt);
                port.postMessage('サイエンスパークのHPです');
            }
        }
    });
});

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
    var url = tab.url;
    changeNotification();
    if(bool){
        if(url.indexOf(path) === 0){
            chrome.notifications.create(opt);
            port.postMessage('サイエンスパークのHPです');
        }
    }
});
```

chrome.runtime.connectNativeでアプリケーションに接続します。
port.postMessageで先ほど作成したアプリケーションにメッセージを送信しています。

## 4. manifest.json
```javascript
{
    "name": "sampleExtension",
    "version": "1.0",
    "manifest_version": 3,
    "description": "拡張機能のテスト",
    "background": {
        "service_worker" : "background.js"
    },
    "permissions": [
        "tabs",
        "notifications",
        "storage",
        "nativeMessaging"
    ],
    "options_page": "options.html"
}
```

今回は拡張機能からアプリにメッセージを送りたいので、permissionsに"nativeMessaging"を追加します。


## 5. 結果

サイエンスパークのHPを開いたときに以下のようなMessageBoxを表示させることができました。

<img width="300" alt="スクリーンショット 2025-03-17 194132.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871987/7d011fea-4bfa-4d1b-a001-d4eebbd1f51a.png">


## 6. 参考文献

https://developer.chrome.com/docs/extensions/develop/concepts/native-messaging?hl=ja