Mensagens nativas

Extensões e apps podem trocar mensagens com aplicativos nativos usando uma API semelhante às outras APIs de transmissão de mensagens. Os aplicativos nativos compatíveis com esse recurso precisam registrar um host de mensagens nativo que saiba como se comunicar com a extensão. O Chrome inicia o host em um processo separado e se comunica com ele usando streams de entrada e saída padrão.

Host de mensagens nativas

Para registrar um host de mensagens nativas, o aplicativo precisa instalar um arquivo de manifesto que defina a configuração do host de mensagens nativas. Confira abaixo um exemplo de arquivo de manifesto:

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

O arquivo de manifesto do host de mensagens nativas precisa ser um JSON válido e conter os seguintes campos:

NomeDescrição
nameNome do host de mensagens nativas. Os clientes transmitem essa string para runtime.connectNative ou runtime.sendNativeMessage. Esse nome só pode conter caracteres alfanuméricos minúsculos, sublinhados e pontos. O nome não pode começar ou terminar com um ponto, e um ponto não pode ser seguido por outro ponto.
descriptionBreve descrição do aplicativo.
pathCaminho para o binário do host de mensagens nativas. No Linux e no OSX, o caminho precisa ser absoluto. No Windows, ele pode ser relativo ao diretório em que o arquivo de manifesto está localizado. O processo do host é iniciado com o diretório atual definido como o diretório que contém o binário do host. Por exemplo, se o parâmetro for definido como C:\Application\nm_host.exe, ele será iniciado com o diretório atual C:\Application\.
typeTipo da interface usada para se comunicar com o host de mensagens nativas. No momento, há apenas um valor possível para esse parâmetro: stdio. Ele indica que o Chrome precisa usar stdin e stdout para se comunicar com o host.
allowed_originsLista de extensões que precisam ter acesso ao host de mensagens nativas. Caracteres curinga como chrome-extension://*/* não são permitidos.

Local do host de mensagens nativas

O local do arquivo de manifesto depende da plataforma.

No Windows, o arquivo de manifesto pode estar localizado em qualquer lugar no sistema de arquivos. O instalador do aplicativo precisa criar uma chave de registro HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\_com.my_company.my_application_ ou HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\_com.my_company.my_application_ e definir o valor padrão dessa chave como o caminho completo para o arquivo de manifesto. Por exemplo, use o seguinte comando:

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

ou usando o seguinte arquivo .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"

Quando o Chrome procura hosts de mensagens nativas, primeiro o registro de 32 bits é consultado, depois o de 64 bits.

No OS X e no Linux, o local do arquivo de manifesto do host de mensagens nativas varia de acordo com o navegador (Google Chrome ou Chromium). Os hosts de mensagens nativas do sistema são pesquisados em um local fixo, enquanto os hosts de mensagens nativas no nível do usuário são pesquisados em um subdiretório dentro do diretório de perfil do usuário chamado NativeMessagingHosts.

  • OS X (todo o sistema)
    • Google Chrome: /Library/Google/Chrome/NativeMessagingHosts/_com.my_company.my_application_.json
    • Chromium: /Library/Application Support/Chromium/NativeMessagingHosts/_com.my_company.my_application_.json
  • OS X (caminho padrão específico do usuário)
    • 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 (todo o sistema)
    • 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 (caminho padrão específico do usuário)
    • Google Chrome: ~/.config/google-chrome/NativeMessagingHosts/_com.my_company.my_application_.json
    • Chromium: ~/.config/chromium/NativeMessagingHosts/_com.my_company.my_application_.json

Protocolo de mensagens nativas

O Chrome inicia cada host de mensagens nativas em um processo separado e se comunica com ele usando a entrada padrão (stdin) e a saída padrão (stdout). O mesmo formato é usado para enviar mensagens nas duas direções: cada mensagem é serializada usando JSON, codificada em UTF-8 e precedida pelo tamanho da mensagem de 32 bits na ordem de bytes nativos. O tamanho máximo de uma única mensagem do host de mensagens nativas é de 1 MB, principalmente para proteger o Chrome contra aplicativos nativos que apresentam comportamento inadequado. O tamanho máximo da mensagem enviada ao host de mensagens nativas é de 4 GB.

O primeiro argumento para o host de mensagens nativas é a origem do autor da chamada, geralmente chrome-extension://[ID of allowed extension]. Isso permite que os hosts de mensagens nativas identifiquem a origem da mensagem quando várias extensões são especificadas na chave allowed_origins no manifesto do host de mensagens nativas. Aviso: no Windows, no Chrome 54 e em versões anteriores, a origem era transmitida como o segundo parâmetro em vez do primeiro.

Quando uma porta de mensagens é criada usando runtime.connectNative, o Chrome inicia o processo do host de mensagens nativas e o mantém em execução até que a porta seja destruída. Por outro lado, quando uma mensagem é enviada usando runtime.sendNativeMessage sem criar uma porta de mensagens, o Chrome inicia um novo processo de host de mensagens nativas para cada mensagem. Nesse caso, a primeira mensagem gerada pelo processo do host é processada como uma resposta à solicitação original, ou seja, o Chrome a transmite para o callback de resposta especificado quando runtime.sendNativeMessage é chamado. Nesse caso, todas as outras mensagens geradas pelo host de mensagens nativas serão ignoradas.

No Windows, o host de mensagens nativas também recebe um argumento de linha de comando com um identificador para a janela nativa do Chrome que chama: --parent-window=<decimal handle value>. Isso permite que o host de mensagens nativas crie janelas de IU nativas com o pai correto. Esse valor será 0 se o contexto de chamada for uma página de script em segundo plano.

Como se conectar a um aplicativo nativo

O envio e o recebimento de mensagens de e para um app nativo é muito semelhante às mensagens entre extensões. A principal diferença é que runtime.connectNative é usado em vez de runtime.connect, e runtime.sendNativeMessage é usado em vez de runtime.sendMessage. Esses métodos só poderão ser usados se a permissão "nativeMessaging" for declarada no arquivo de manifesto do app.

O exemplo a seguir cria um objeto runtime.Port que está conectado ao host de mensagens nativas com.my_company.my_application, começa a detectar as mensagens dessa porta e envia uma mensagem de saída:

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 pode ser usado para enviar uma mensagem ao aplicativo nativo sem criar uma porta. Por exemplo:

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

Como depurar mensagens nativas

Quando o host de mensagens nativas falha ao iniciar, grava em stderr ou quando viola o protocolo de comunicação, a saída é gravada no registro de erros do Chrome. No Linux e no OS X, esse registro pode ser acessado facilmente iniciando o Chrome na linha de comando e observando a saída no terminal. No Windows, use --enable-logging, conforme explicado em Como ativar a geração de registros.

Confira alguns erros e dicas para resolver os problemas:

  • Falha ao iniciar o host de mensagens nativas.
    • Verifique se você tem permissões suficientes para executar o arquivo.
  • O nome de host de mensagens nativas especificado é inválido.
    • Verifique se o nome contém caracteres inválidos. Apenas caracteres alfanuméricos minúsculos, sublinhados e pontos são permitidos. Um nome não pode começar ou terminar com um ponto, e um ponto não pode ser seguido por outro ponto.
  • O host nativo saiu.
    • O canal para o host de mensagens nativas estava corrompido antes de a mensagem ser lida pelo Chrome. Isso provavelmente é iniciado no host de mensagens nativas.
  • O host de mensagens nativas especificado não foi encontrado.
    • O nome está escrito corretamente na extensão e no arquivo de manifesto?
    • O manifesto está no diretório certo e com o nome certo? Consulte o local do host de mensagens nativas para saber os formatos esperados.
    • O arquivo de manifesto está no formato correto? Especificamente, a sintaxe JSON está correta e os valores correspondem à definição de um manifesto de host de mensagens nativas?
    • O arquivo especificado em path existe? No Windows, os caminhos podem ser relativos, mas no OS X e Linux, os caminhos precisam ser absolutos.
  • O nome do host de mensagens nativas não está registrado. (somente para Windows)
    • O host de mensagens nativas não foi encontrado no registro do Windows. Verifique usando regedit se a chave realmente foi criada e corresponde ao formato necessário, conforme documentado no local do host das mensagens nativas.
  • O acesso ao host de mensagens nativas especificado é proibido.
    • A origem da extensão está listada em allowed_origins?
  • Erro ao se comunicar com o host de mensagens nativas.
    • Esse é um erro muito comum e indica uma implementação incorreta do protocolo de comunicação no host de mensagens nativas.
    • Confira se toda a saída no stdout segue o protocolo de mensagens nativas. Caso queira exibir alguns dados para fins de depuração, grave em stderr.
    • Verifique se o tamanho da mensagem de 32 bits está no formato inteiro nativo da plataforma (little-endian / big-endian).
    • O tamanho da mensagem não pode exceder 1.024 x 1.024.
    • O tamanho da mensagem precisa ser igual ao número de bytes dela. Isso pode ser diferente do "comprimento" de uma string, porque os caracteres podem ser representados por vários bytes.
    • Somente Windows: verifique se o modo de E/S do programa está definido como O_BINARY. Por padrão, o modo de E/S é O_TEXT, o que corrompe o formato da mensagem porque as quebras de linha (\n = 0A) são substituídas por finalidades de linha no estilo do Windows (\r\n = 0D 0A). O modo de E/S pode ser definido usando __setmode.