Rozszerzenia mogą wymieniać wiadomości z aplikacjami natywnymi za pomocą interfejsu API podobnego do innych interfejsów API do przekazywania wiadomości. Aplikacje natywne obsługujące tę funkcję muszą zarejestrować hosta natywnego przesyłania komunikatów, który może komunikować się z rozszerzeniem. Chrome uruchamia hosta w osobnym procesie i komunikuje się z nim za pomocą standardowych strumieni wejściowych i wyjściowych.
Host natywnego przesyłania komunikatów
Aby zarejestrować hosta natywnego przesyłania komunikatów, aplikacja musi zapisać plik, który definiuje konfigurację hosta natywnego przesyłania komunikatów.
Przykład pliku:
{
"name": "com.my_company.my_application",
"description": "My Application",
"path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
"type": "stdio",
"allowed_origins": ["chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"]
}
Plik manifestu hosta natywnego przesyłania komunikatów musi być prawidłowym plikiem JSON i zawierać te pola:
name- Nazwa hosta natywnego przesyłania komunikatów. Klienci przekazują ten ciąg do
runtime.connectNative()lubruntime.sendNativeMessage(). Nazwa może zawierać tylko małe znaki alfanumeryczne, podkreślenia i kropki. Nazwa nie może zaczynać się ani kończyć kropką, a po kropce nie może następować kolejna kropka. description- Krótki opis aplikacji.
path- Ścieżka do pliku binarnego hosta natywnego przesyłania komunikatów. W systemach Linux i macOS ścieżka musi być bezwzględna. W systemie Windows może być względna w stosunku do katalogu zawierającego plik manifestu. Proces hosta jest uruchamiany z bieżącym katalogiem ustawionym na katalog zawierający plik binarny hosta. Jeśli np. ten parametr ma wartość
C:\Application\nm_host.exe, zostanie uruchomiony w bieżącym katalogu „C:\Application”. type- Typ interfejsu używanego do komunikacji z hostem natywnego przesyłania komunikatów. Ten parametr ma jedną możliwą wartość:
stdio. Oznacza to, że Chrome powinien używać protokołówstdinistdoutdo komunikacji z hostem. allowed_origins- Lista rozszerzeń, które powinny mieć dostęp do hosta natywnego przesyłania komunikatów. Wartości
allowed-originsnie mogą zawierać symboli wieloznacznych.
Lokalizacja hosta natywnego przesyłania komunikatów
Lokalizacja pliku manifestu zależy od platformy.
W Windows plik manifestu może znajdować się w dowolnym miejscu w systemie plików. Instalator aplikacji musi utworzyć klucz rejestru, HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application lub HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application, i ustawić domyślną wartość tego klucza na pełną ścieżkę do pliku manifestu. Na przykład używając tego polecenia:
REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application" /ve /t REG_SZ /d "C:\path\to\nmh-manifest.json" /f
lub użyć tego pliku .reg:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application]
@="C:\\path\\to\\nmh-manifest.json"
Gdy Chrome szuka hostów wiadomości natywnych, najpierw wysyła zapytanie do rejestru 32-bitowego, a potem do rejestru 64-bitowego.
W systemach macOS i Linux lokalizacja pliku manifestu hosta natywnego przesyłania komunikatów różni się w zależności od przeglądarki (Google Chrome, Chrome for Testing lub Chromium). Hosty natywnych aplikacji do obsługi wiadomości na poziomie systemu są wyszukiwane w ustalonym miejscu, a hosty natywnych aplikacji do obsługi wiadomości na poziomie użytkownika są wyszukiwane w NativeMessagingHosts/podkatalogu katalogu profilu użytkownika.
- macOS (cały system)
- Google Chrome:
/Library/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json - Google Chrome for Testing:
/Library/Google/ChromeForTesting/NativeMessagingHosts/com.my_company.my_application.json - Chromium:
/Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json - macOS (ścieżka domyślna, specyficzna dla użytkownika)
- Google Chrome:
~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json - Google Chrome for Testing:
~/Library/Application Support/Google/ChromeForTesting/NativeMessagingHosts/com.my_company.my_application.json - Chromium:
~/Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json - Linux (w całym systemie)
- Google Chrome:
/etc/opt/chrome/native-messaging-hosts/com.my_company.my_application.json - Google Chrome for Testing:
/etc/opt/chrome_for_testing/native-messaging-hosts/com.my_company.my_application.json - Chromium:
/etc/chromium/native-messaging-hosts/com.my_company.my_application.json - Linux (ścieżka domyślna, specyficzna dla użytkownika)
- Google Chrome:
~/.config/google-chrome/NativeMessagingHosts/com.my_company.my_application.json - Google Chrome for Testing:
~/.config/google-chrome-for-testing/NativeMessagingHosts/com.my_company.my_application.json - Chromium:
~/.config/chromium/NativeMessagingHosts/com.my_company.my_application.json
Protokół natywnego przesyłania wiadomości
Chrome uruchamia każdy host natywnego przesyłania komunikatów w osobnym procesie i komunikuje się z nim za pomocą standardowego strumienia wejścia (stdin) i standardowego strumienia wyjścia (stdout). Ten sam format jest używany do wysyłania wiadomości w obu kierunkach. Każda wiadomość jest serializowana za pomocą JSON, kodowana w UTF-8 i poprzedzona 32-bitową długością wiadomości w natywnej kolejności bajtów. Maksymalny rozmiar pojedynczej wiadomości z hosta natywnego przesyłania komunikatów to 1 MB. Ma to na celu ochronę Chrome przed nieprawidłowo działającymi aplikacjami natywnymi. Maksymalny rozmiar wiadomości wysyłanej do hosta natywnego przesyłania komunikatów to 64 MiB.
Pierwszym argumentem hosta natywnego przesyłania komunikatów jest pochodzenie wywołującego, zwykle
chrome-extension://[ID of allowed extension]. Umożliwia to hostom natywnego przesyłania komunikatów identyfikowanie źródła wiadomości, gdy w allowed_origins w pliku manifestu hosta natywnego przesyłania komunikatów określono wiele rozszerzeń.
W systemie Windows do hosta natywnego przesyłania komunikatów przekazywany jest też argument wiersza poleceń z uchwytem do wywołującego okna natywnego Chrome: --parent-window=<decimal handle value>. Dzięki temu host natywnego przesyłania komunikatów może tworzyć okna natywnego interfejsu, które są prawidłowo powiązane z elementem nadrzędnym. Pamiętaj, że ta wartość będzie wynosić 0, jeśli kontekstem wywołania jest skrypt service worker.
Gdy port do przesyłania wiadomości zostanie utworzony za pomocą runtime.connectNative(), Chrome uruchamia proces hosta przesyłania wiadomości natywnych i utrzymuje go w działaniu do momentu zniszczenia portu. Z drugiej strony, gdy wiadomość jest wysyłana za pomocą runtime.sendNativeMessage() bez tworzenia portu do przesyłania wiadomości, Chrome uruchamia nowy proces hosta natywnego przesyłania komunikatów dla każdej wiadomości. W takim przypadku pierwsza wiadomość wygenerowana przez proces hosta jest traktowana jako odpowiedź na pierwotne żądanie, a Chrome przekazuje ją do funkcji zwrotnej odpowiedzi określonej podczas wywoływania funkcji runtime.sendNativeMessage(). W takim przypadku wszystkie inne wiadomości wygenerowane przez hosta natywnego przesyłania komunikatów są ignorowane.
Łączenie się z aplikacją natywną
Wysyłanie i odbieranie wiadomości do i z aplikacji natywnej jest bardzo podobne do przesyłania wiadomości między rozszerzeniami. Główna różnica polega na tym, że zamiast runtime.connect() używa się operatora runtime.connectNative(), a zamiast runtime.sendMessage() – operatora runtime.sendNativeMessage().
Aby używać tych metod, musisz zadeklarować uprawnienie „nativeMessaging” w pliku manifestu rozszerzenia.
Te metody nie są dostępne w skryptach treści, tylko na stronach rozszerzenia i w jego skrypcie service worker. Jeśli chcesz komunikować się ze skryptu treści z aplikacją natywną, wyślij wiadomość do skryptu service worker, aby przekazać ją do aplikacji natywnej.
W tym przykładzie tworzony jest obiekt runtime.Port, który jest połączony z hostem natywnego przesyłania komunikatów
com.my_company.my_application, rozpoczyna nasłuchiwanie wiadomości z tego portu i wysyła jedną wiadomość wychodzącą:
var port = chrome.runtime.connectNative('com.my_company.my_application');
port.onMessage.addListener(function (msg) {
console.log('Received' + msg);
});
port.onDisconnect.addListener(function () {
console.log('Disconnected');
});
port.postMessage({text: 'Hello, my_application'});
Użyj runtime.sendNativeMessage, aby wysłać wiadomość do aplikacji natywnej bez tworzenia portu, np.:
chrome.runtime.sendNativeMessage(
'com.my_company.my_application',
{text: 'Hello'},
function (response) {
console.log('Received ' + response);
}
);
Debugowanie natywnego przesyłania komunikatów
W przypadku niektórych błędów przesyłania wiadomości natywnych dane wyjściowe są zapisywane w dzienniku błędów Chrome. Obejmuje to sytuacje, w których host natywnych aplikacji do obsługi wiadomości nie uruchamia się, zapisuje dane w stderr lub narusza protokół komunikacyjny. W systemach Linux i macOS dostęp do tego dziennika można uzyskać, uruchamiając Chrome z wiersza poleceń i obserwując jego dane wyjściowe w terminalu. W systemie Windows użyj --enable-logging zgodnie z instrukcjami w artykule Jak włączyć logowanie.
Oto kilka typowych błędów i wskazówki dotyczące ich rozwiązywania:
Nie udało się uruchomić hosta natywnego przesyłania komunikatów.
Sprawdź, czy masz wystarczające uprawnienia do uruchomienia pliku hosta natywnego przesyłania komunikatów.
Podano nieprawidłową nazwę hosta natywnego przesyłania komunikatów.
Sprawdź, czy nazwa zawiera nieprawidłowe znaki. Dozwolone są tylko małe znaki alfanumeryczne, podkreślenia i kropki. Nazwa nie może zaczynać się ani kończyć kropką, a po kropce nie może występować kolejna kropka.
Host natywny został zamknięty.
Połączenie z hostem natywnego przesyłania komunikatów zostało przerwane, zanim Chrome odczytał wiadomość. Najprawdopodobniej jest to inicjowane przez hosta natywnego przesyłania komunikatów.
Nie znaleziono określonego hosta natywnego przesyłania komunikatów.
Sprawdź, czy:
- Czy nazwa jest poprawnie zapisana w rozszerzeniu i pliku manifestu?
- Czy plik manifestu znajduje się w odpowiednim katalogu i ma prawidłową nazwę? Oczekiwane formaty znajdziesz w sekcji host natywnego przesyłania komunikatów location.
- Czy plik manifestu ma prawidłowy format? W szczególności, czy plik JSON jest prawidłowy i dobrze sformatowany oraz czy wartości są zgodne z definicją pliku manifestu hosta natywnego przesyłania komunikatów?
- Czy plik określony w parametrze
pathistnieje? W systemie Windows ścieżki mogą być względne, ale w systemach macOS i Linux muszą być bezwzględne.
Host natywnego przesyłania komunikatów host name nie jest zarejestrowany. (tylko Windows)
Nie znaleziono hosta natywnego przesyłania komunikatów w rejestrze systemu Windows. Sprawdź za pomocą regedit, czy klucz został utworzony i czy jest zgodny z wymaganym formatem opisanym w sekcji Lokalizacja hosta wiadomości natywnych.
Dostęp do określonego hosta natywnego przesyłania komunikatów jest zabroniony.
Czy punkt początkowy rozszerzenia jest wymieniony w allowed_origins?
Błąd podczas komunikacji z hostem natywnego przesyłania komunikatów.
Oznacza to nieprawidłową implementację protokołu komunikacji w hoście natywnego przesyłania komunikatów.
- Upewnij się, że wszystkie dane wyjściowe w
stdoutsą zgodne z protokołem przesyłania wiadomości natywnych. Jeśli chcesz wydrukować niektóre dane na potrzeby debugowania, napisz na adresstderr. - Sprawdź, czy 32-bitowa długość wiadomości jest w natywnym formacie liczb całkowitych platformy (little-endian/big-endian).
- Długość wiadomości nie może przekraczać 1024*1024.
- Rozmiar wiadomości musi być równy liczbie bajtów w wiadomości. Może się to różnić od „długości” ciągu znaków, ponieważ znaki mogą być reprezentowane przez wiele bajtów.
- Tylko Windows: upewnij się, że tryb wejścia/wyjścia programu jest ustawiony na
O_BINARY. Domyślnie tryb wejścia/wyjścia toO_TEXT, co powoduje uszkodzenie formatu wiadomości, ponieważ znaki końca wiersza (\n=0A) są zastępowane znakami końca wiersza w stylu Windows (\r\n=0D 0A). Tryb wejścia/wyjścia można ustawić za pomocą polecenia__setmode.