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

Расширения могут обмениваться сообщениями с нативными приложениями, используя 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
Chromium: /etc/chromium/native-messaging-hosts/com.my_company.my_application.json
Linux (зависит от пользователя, путь по умолчанию )
Google Chrome: ~/.config/google-chrome/NativeMessagingHosts/com.my_company.my_application.json
Chromium: ~/.config/chromium/NativeMessagingHosts/com.my_company.my_application.json

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

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

Первый аргумент для собственного хоста обмена сообщениями — это источник вызывающего объекта, обычно 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.connect() используется runtime.connectNative() , а вместо 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. Скорее всего, это произошло из-за вашего нативного хоста обмена сообщениями.

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

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

Имя хоста собственного сервера обмена сообщениями не зарегистрировано. (Только для 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 .