Wiadomości natywne

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.

Oto przykład takiego 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ć w prawidłowym formacie JSON i zawierać te pola:

name
Nazwa hosta natywnego przesyłania komunikatów. Klienci przekazują ten ciąg do runtime.connectNative() lub runtime.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ć stdinstdout do komunikacji z hostem.
allowed_origins
Lista rozszerzeń, które powinny mieć dostęp do hosta natywnego przesyłania komunikatów. Wartości allowed_origins nie mogą zawierać symboli wieloznacznych.

Lokalizacja hosta natywnego przesyłania komunikatów

Lokalizacja pliku manifestu zależy od platformy.

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 za pomocą 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 macOSLinux 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 (dla konkretnego użytkownika, domyślna ścieżka)
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 komunikatów

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 wiadomości natywnych 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 elementu wywołującego, zwyklechrome-extension://[ID of allowed extension]. Umożliwia to hostom natywnego przesyłania komunikatów identyfikowanie źródła wiadomości, gdy w kluczu allowed_originspliku 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 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 ruchu, dopóki port nie zostanie zniszczony. Z drugiej strony, gdy wiadomość jest wysyłana za pomocą runtime.sendNativeMessage() bez tworzenia portu, 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 korzystać z tych metod, w pliku manifestu rozszerzenia musi być zadeklarowane uprawnienie „nativeMessaging”.

Te metody nie są dostępne w skryptach treści, tylko na stronach rozszerzenia i w jego skrypcie service worker. Aby komunikować się ze skryptu treści z aplikacją natywną, wyślij wiadomość do skryptu service worker, który przekaże 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ą:

const port = chrome.runtime.connectNative('com.my_company.my_application');
port.onMessage.addListener((msg) => {
  console.log('Received', msg);
});
port.onDisconnect.addListener(() => {
  if (chrome.runtime.lastError) {
    console.error(
      'Disconnected due to error:',
      chrome.runtime.lastError.message
    );
  } else {
    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'},
  (response) => {
    if (chrome.runtime.lastError) {
      console.error(
        'Error sending native message:',
        chrome.runtime.lastError.message
      );
      return;
    }
    console.log('Received', response);
  }
);

Debugowanie natywnego przesyłania komunikatów

W przypadku błędów w komunikacji natywnej dane diagnostyczne są zapisywane w dzienniku błędów Chrome.

Linux i macOS

# Linux
google-chrome --enable-logging=stderr --log-level=1 2>&1 | \
  grep -E "native_messag|launch_context"

# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
  --enable-logging=stderr --log-level=1 2>&1 | \
  grep -E "native_messag|launch_context"

Windows

Uruchom Chrome z włączonym rejestrowaniem:

chrome.exe --enable-logging --log-level=1

Przekaż --user-data-dir="%TEMP%\nm-debug", aby uruchomić oddzielne wystąpienie bez dołączania go do istniejącego procesu Chrome.

Aby wyświetlić dane wyjściowe, przesyłaj strumieniowo chrome_debug.log za pomocą PowerShell:

$log = "$env:LOCALAPPDATA\Google\Chrome\User Data\chrome_debug.log"
Get-Content -Wait $log | Select-String "native_messag|launch_context"

Możesz też otworzyć plik chrome_debug.log w edytorze tekstu i wyszukać w nim ciągi znaków launch_context.cc lub native_message_process_host.cc.

Szczegóły logowania klucza

  • Błędy wyszukiwania i analizowania pliku manifestu w launch_context.cc są rejestrowane jako ostrzeżenia. Używaj --log-level=1 zamiast 2 (ERROR), co spowoduje pominięcie tych diagnostyk uruchamiania.
  • Wyszukaj launch_context, aby znaleźć błędy uruchamiania manifestu i pliku binarnego, oraz native_messag, aby znaleźć błędy rozmiaru ładunku i komunikacji potokowej.

Typowe błędy

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 wiadomości natywnych zostało przerwane, zanim Chrome odczytał wiadomość. Najprawdopodobniej jest to inicjowane przez hosta natywnego przesyłania komunikatów.

Nie znaleziono wskazanego hosta natywnego przesyłania komunikatów.

Sprawdź, czy:

  • Czy nazwa jest poprawnie zapisana w rozszerzeniu i pliku manifestu?
  • Czy w systemie Windows klucz rejestru istnieje w lokalizacji HKEY_CURRENT_USER lub HKEY_LOCAL_MACHINE, a jego wartość domyślna wskazuje pełną ścieżkę do pliku manifestu? Chrome najpierw wysyła zapytanie do 32-bitowego widoku rejestru, a potem do 64-bitowego. Użyj regedit, aby zweryfikować klucz. Zobacz lokalizację hosta natywnego przesyłania komunikatów.
  • Czy w systemach macOS i Linux plik manifestu znajduje się w odpowiednim katalogu i ma nazwę hosta (np. com.my_company.my_application.json)? Więcej informacji znajdziesz w sekcji Lokalizacja hosta natywnego przesyłania komunikatów.
  • 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 path istnieje? W systemie Windows ścieżki mogą być względne, ale w systemach macOS i Linux muszą być bezwzględne.

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 na hoście natywnego przesyłania komunikatów.

  • Upewnij się, że wszystkie dane wyjściowe w stdout są zgodne z protokołem przesyłania wiadomości natywnych. Jeśli chcesz wydrukować niektóre dane na potrzeby debugowania, napisz na adres stderr.
  • 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 to O_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.