Собственный обмен сообщениями

Расширения могут обмениваться сообщениями с собственными приложениями, используя API, аналогичный другим API передачи сообщений . Собственные приложения, поддерживающие эту функцию, должны зарегистрировать собственный узел обмена сообщениями , который может взаимодействовать с расширением. Chrome запускает хост в отдельном процессе и взаимодействует с ним, используя потоки стандартного ввода и стандартного вывода.

Собственный хост обмена сообщениями

Чтобы зарегистрировать собственный хост обмена сообщениями, приложение должно сохранить файл, который определяет конфигурацию собственного хоста обмена сообщениями.

Пример файла следующий:

{
  "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/"]
}

Файл манифеста узла собственной системы обмена сообщениями должен иметь действительный формат JSON и содержать следующие поля:

name
Имя собственного узла обмена сообщениями. Клиенты передают эту строку в runtime.connectNative() или runtime.sendNativeMessage() . Это имя может содержать только строчные буквы, цифры, символы подчеркивания и точки. Имя не может начинаться или заканчиваться точкой, а за точкой не может следовать другая точка.
description
Краткое описание приложения.
path
Путь к двоичному файлу узла обмена сообщениями. В Linux и macOS путь должен быть абсолютным. В Windows это может быть относительно каталога, содержащего файл манифеста. Хост-процесс запускается с текущим каталогом, установленным в каталог, содержащий двоичный файл хоста. Например, если для этого параметра установлено значение C:\Application\nm_host.exe , то он будет запущен с текущего каталога `C:\Application`.
type
Тип интерфейса, используемого для связи с собственным узлом обмена сообщениями. Этот параметр имеет одно возможное значение: stdio . Это указывает на то, что Chrome должен использовать stdin и stdout для связи с хостом.
allowed_origins
Список расширений, которые должны иметь доступ к собственному узлу обмена сообщениями. Значения allowed-origins не могут содержать подстановочные знаки.

Местоположение собственного узла обмена сообщениями

Расположение файла манифеста зависит от платформы.

В Windows файл манифеста может находиться в любом месте файловой системы. Установщик приложения должен создать ключ реестра HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application или HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.my_company.my_application и установить для этого ключа значение по умолчанию. полный путь к файлу манифеста. Например, используя следующую команду:

REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application" /ve /t REG_SZ /d "C:\path\to\nmh-manifest.json" /f

или используя следующий .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"

Когда Chrome ищет собственные хосты обмена сообщениями, сначала запрашивается 32-битный реестр, а затем 64-битный реестр.

В macOS и Linux расположение файла манифеста собственного узла обмена сообщениями зависит от браузера (Google Chrome или Chromium). Собственные узлы обмена сообщениями на уровне системы просматриваются в фиксированном местоположении, тогда как собственные узлы обмена сообщениями на уровне пользователя просматриваются в подкаталоге NativeMessagingHosts/ каталога профиля пользователя .

macOS (общесистемный)
Google Chrome: /Library/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json
Chromium: /Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json
macOS (зависит от пользователя, путь по умолчанию )
Google Chrome: ~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.my_company.my_application.json
Chromium: ~/Library/Application Support/Chromium/NativeMessagingHosts/com.my_company.my_application.json
Linux (общесистемный)
Google Chrome: /etc/opt/chrome/native-messaging-hosts/com.my_company.my_application.json
Хром: /etc/chromium/native-messaging-hosts/com.my_company.my_application.json
Linux (зависит от пользователя, путь по умолчанию )
Google Chrome: ~/.config/google-chrome/NativeMessagingHosts/com.my_company.my_application.json
Хром: ~/.config/chromium/NativeMessagingHosts/com.my_company.my_application.json

Собственный протокол обмена сообщениями

Chrome запускает каждый собственный хост обмена сообщениями в отдельном процессе и взаимодействует с ним, используя стандартный ввод ( stdin ) и стандартный вывод ( stdout ). Один и тот же формат используется для отправки сообщений в обоих направлениях; каждое сообщение сериализуется с использованием JSON в кодировке UTF-8, и ему предшествует 32-битная длина сообщения в собственном порядке байтов. Максимальный размер одного сообщения от собственного узла обмена сообщениями составляет 1 МБ, главным образом для защиты Chrome от некорректного поведения собственных приложений. Максимальный размер сообщения, отправляемого на собственный узел обмена сообщениями, составляет 4 ГБ.

Первым аргументом собственного хоста обмена сообщениями является источник вызывающего абонента, обычно chrome-extension://[ID of allowed extension] . Это позволяет собственным узлам обмена сообщениями идентифицировать источник сообщения, если в ключе allowed_origins в манифесте собственного узла обмена сообщениями указано несколько расширений.

В Windows собственному хосту обмена сообщениями также передается аргумент командной строки с дескриптором вызывающего собственного окна Chrome: --parent-window=<decimal handle value> . Это позволяет собственному узлу обмена сообщениями создавать собственные окна пользовательского интерфейса, которые правильно являются родительскими. Обратите внимание, что это значение будет равно 0, если вызывающим контекстом является сервисный работник.

Когда порт обмена сообщениями создается с помощью runtime.connectNative() Chrome запускает собственный хост-процесс обмена сообщениями и поддерживает его работу до тех пор, пока порт не будет уничтожен. С другой стороны, когда сообщение отправляется с помощью runtime.sendNativeMessage() без создания порта обмена сообщениями, Chrome запускает новый собственный хост-процесс обмена сообщениями для каждого сообщения. В этом случае первое сообщение, сгенерированное хост-процессом, обрабатывается как ответ на исходный запрос, и Chrome передает его обратному вызову ответа, указанному при вызове runtime.sendNativeMessage() . Все остальные сообщения, генерируемые собственным узлом обмена сообщениями, в этом случае игнорируются.

Подключение к родному приложению

Отправка и получение сообщений в собственное приложение и из него очень похоже на обмен сообщениями между расширениями. Основное отличие состоит в том, что вместо runtime.connectNative() используется runtime.connect() , а вместо runtime.sendNativeMessage() используется runtime.sendMessage() .

Чтобы использовать эти методы, разрешение «nativeMessaging» должно быть объявлено в файле манифеста ваших расширений.

Эти методы недоступны внутри сценариев содержимого, они доступны только на страницах вашего расширения и в сервис-воркере. Если вы хотите передать сообщение из сценария содержимого в собственное приложение, отправьте сообщение своему сервисному работнику, чтобы тот передал его собственному приложению.

В следующем примере создается объект runtime.Port , который подключен к собственному узлу обмена сообщениями com.my_company.my_application , начинает прослушивать сообщения от этого порта и отправляет одно исходящее сообщение:

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'});

Используйте runtime.sendNativeMessage для отправки сообщения в собственное приложение без создания порта, например:

chrome.runtime.sendNativeMessage(
  'com.my_company.my_application',
  {text: 'Hello'},
  function (response) {
    console.log('Received ' + response);
  }
);

Отладка встроенного обмена сообщениями

При возникновении определенных сбоев встроенного обмена сообщениями выходные данные записываются в журнал ошибок Chrome. Это включает в себя случаи, когда собственный хост обмена сообщениями не запускается, записывает в stderr или нарушает протокол связи. В Linux и macOS доступ к этому журналу можно получить, запустив Chrome из командной строки и просмотрев его вывод в терминале. В Windows используйте --enable-logging , как описано в разделе «Как включить ведение журнала» .

Вот некоторые распространенные ошибки и советы по их устранению:

Не удалось запустить собственный хост обмена сообщениями.

Проверьте, есть ли у вас достаточные разрешения для выполнения файла хоста собственного обмена сообщениями.

Указано неверное имя хоста собственной системы обмена сообщениями.

Проверьте, содержит ли имя недопустимые символы. Допускаются только строчные буквы, цифры, символы подчеркивания и точки. Имя не может начинаться или заканчиваться точкой, а за точкой не может следовать другая точка.

Родной хост вышел.

Канал к собственному хосту обмена сообщениями был сломан до того, как сообщение было прочитано Chrome. Скорее всего, это инициируется вашим собственным хостом обмена сообщениями.

Указанный собственный хост обмена сообщениями не найден.

Проверьте следующее:

  • Правильно ли написано имя в расширении и в файле манифеста?
  • Манифест находится в правильном каталоге и имеет правильное имя? Ожидаемые форматы см . в расположении собственного узла обмена сообщениями .
  • Файл манифеста имеет правильный формат? В частности, является ли JSON действительным и правильно сформированным, и соответствуют ли значения определению собственного манифеста узла обмена сообщениями ?
  • Существует ли файл, указанный в path ? В Windows пути могут быть относительными, но в macOS и Linux пути должны быть абсолютными.

Имя хоста собственного узла обмена сообщениями не зарегистрировано. (только для Windows)

Собственный узел обмена сообщениями не найден в реестре Windows. Дважды проверьте с помощью regedit , действительно ли ключ был создан и соответствует ли он требуемому формату, как описано в расположении собственного узла обмена сообщениями .

Доступ к указанному собственному хосту обмена сообщениями запрещен.

Указано ли происхождение расширения в allowed_origins ?

Ошибка при обмене данными с собственным хостом обмена сообщениями.

Это указывает на неправильную реализацию протокола связи на собственном узле обмена сообщениями.

  • Убедитесь, что весь вывод в stdout соответствует собственному протоколу обмена сообщениями . Если вы хотите распечатать некоторые данные для целей отладки, напишите в stderr .
  • Убедитесь, что длина 32-битного сообщения соответствует собственному целочисленному формату платформы (little-endian/big-endian).
  • Длина сообщения не должна превышать 1024*1024.
  • Размер сообщения должен быть равен количеству байтов в сообщении. Это может отличаться от «длины» строки, поскольку символы могут быть представлены несколькими байтами.
  • Только для Windows: убедитесь, что режим ввода-вывода программы установлен на O_BINARY . По умолчанию режим ввода-вывода — O_TEXT , который искажает формат сообщения, поскольку разрывы строк ( \n = 0A ) заменяются окончаниями строк в стиле Windows ( \r\n = 0D 0A ). Режим ввода-вывода можно установить с помощью __setmode .