Commit 0db8ee2f authored by rob's avatar rob Committed by Commit bot

Improve native messaging documentation

- Specify format of NMH manifest.
- Specify the expected locations of the NMH on all platforms.
- Fully document the communication protocol and constraints.
- Document every error and offer tips for resolving the issues.
- Document other common problems and how-to-solve.

BUG=377582
R=sergeyu@chromium.org,kalman@chromium.org
NOTRY=true

Review URL: https://codereview.chromium.org/768373004

Cr-Commit-Position: refs/heads/master@{#308420}
parent ff02e6d9
...@@ -7,13 +7,15 @@ host from the host directory. ...@@ -7,13 +7,15 @@ host from the host directory.
To install the host: To install the host:
On Windows: On Windows:
Add registry key Run install_host.bat script in the host directory.
HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo This script installs the native messaging host for the current user, by
or creating a registry key
HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo
and set its default value to the full path to and setting its default value to the full path to
host\com.google.chrome.example.echo-win.json . Note that you need to have host\com.google.chrome.example.echo-win.json .
python installed. If you want to install the native messaging host for all users, change HKCU to
HKLM.
Note that you need to have python installed.
On Mac and Linux: On Mac and Linux:
Run install_host.sh script in the host directory: Run install_host.sh script in the host directory:
......
:: Copyright 2014 The Chromium Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style license that can be
:: found in the LICENSE file.
:: Change HKCU to HKLM if you want to install globally.
:: %~dp0 is the directory containing this bat script and ends with a backslash.
REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /ve /t REG_SZ /d "%~dp0com.google.chrome.example.echo-win.json" /f
...@@ -17,6 +17,13 @@ try: ...@@ -17,6 +17,13 @@ try:
except ImportError: except ImportError:
Tkinter = None Tkinter = None
# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY
# to avoid unwanted modifications of the input/output streams.
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
# Helper function that sends a message to the webapp. # Helper function that sends a message to the webapp.
def send_message(message): def send_message(message):
# Write message size. # Write message size.
......
:: Copyright 2014 The Chromium Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style license that can be
:: found in the LICENSE file.
:: Deletes the entry created by install_host.bat
REG DELETE "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /f
REG DELETE "HKLM\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /f
...@@ -279,142 +279,17 @@ chrome.runtime.onMessageExternal.addListener( ...@@ -279,142 +279,17 @@ chrome.runtime.onMessageExternal.addListener(
</pre> </pre>
<!-- Anchors to make sure that pages that link to a previous version of the
documentation do not break. -->
<a id="native-messaging-host"></a>
<a id="native-messaging-client"></a>
<h2 id="native-messaging">Native messaging</h2> <h2 id="native-messaging">Native messaging</h2>
<p> <p>
Extensions can exchange messages with native applications. Native Extensions and apps <a href="nativeMessaging#native-messaging-client">can
applications that support this feature must register a <em>native messaging exchange messages</a> with native applications that are registered as a
host</em> that knows how to communicate with the extension. Chrome starts the <a href="nativeMessaging#native-messaging-host">native messaging host</a>.
host in a separate process and communicates with it using standard input and To learn more about this feature, see <a href="nativeMessaging">Native messaging</a>.
standard output streams.
<h3 id="native-messaging-host">Native messaging host</h3>
<p>
In order to register a native messaging host the application must install a
manifest file that defines the native messaging host configuration. Below is an
example of the manifest file:
<pre data-filename="manifest.json">
{
"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/"
]
}
</pre>
<p>Native messaging host manifest file contains the following fields:
<table class="simple">
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<tr>
<td><code>name</code></td>
<td>Name of the native messaging host. Clients pass this string to
$(ref:runtime.connectNative) or $(ref:runtime.sendNativeMessage).</td>
</tr>
<tr>
<td><code>description</code></td>
<td>Short application description.</td>
</tr>
<tr>
<td><code>path</code></td>
<td>Path to the native messaging host binary. On Linux and OSX the path must
be absolute. On Windows it can be relative to the directory in which the
manifest file is located.</td>
</tr>
<tr>
<td><code>type</code></td>
<td>Type of the interface used to communicate with the native messaging
host. Currently there is only one possible value for this parameter:
<code>stdio</code>. It indicates that Chrome should use <code>stdin</code>
and <code>stdout</code> to communicate with the host.</td>
</tr>
<tr>
<td><code>allowed_origins</code></td>
<td>List of extensions that should have access to the native messaging host.</td>
</tr>
</table>
<p>Location of the manifest file depends on the platform:
<dl>
<dt>Windows:</dt>
<dd>The manifest file can be located anywhere in the file system.
The application installer must create registry key
<code>HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\<em>com.my_company.my_application</em></code>
or
<code>HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\<em>com.my_company.my_application</em></code>,
and set default value of that key to the full path to the manifest file.
</dd>
<dt>OSX:</dt>
<dd>The manifest file must be placed at
<code>/Library/Google/Chrome/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>,
or, for applications installed on user level,
<code>~/Library/Application Support/Google/Chrome/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>.
</dd>
<dt>Linux:</dt>
<dd>The manifest file must be placed at
<code>/etc/opt/chrome/native-messaging-hosts/<em>com.my_company.my_application</em>.json</code>,
or, for applications installed on user level,
<code>~/.config/google-chrome/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>.
</dd>
</dl>
<p>
Chrome starts each native messaging host in a separate process and communicates
with it using standard input (<code>stdin</code>) and standard output
(<code>stdout</code>). The same format is used to send messages in both
directions: each message is serialized using JSON, UTF-8 encoded
and is preceded with 32-bit message length in native byte order.
<p>
When a messaging port is created using $(ref:runtime.connectNative) Chrome
starts native messaging host process and keeps it running until the port is
destroyed. On the other hand, when a message is sent using
$(ref:runtime.sendNativeMessage), without creating a messaging port, Chrome starts
a new native messaging host process for each message. In that case the first
message generated by the host process is handled as a response to the original
request, i.e. Chrome will pass it to the response callback specified when
$(ref:runtime.sendNativeMessage) is called. All other messages generated by the
native messaging host in that case are ignored.
<h3 id="native-messaging-client">Connecting to a native application</h3>
<p>
Sending and receiving messages to and from a native application is very similar
to cross-extension messaging. The main difference is that
$(ref:runtime.connectNative) is used instead of $(ref:runtime.connect),
and $(ref:runtime.sendNativeMessage) is used instead of $(ref:runtime.sendMessage).
<p>
The Following example creates a $(ref:runtime.Port) object that's connected to native
messaging host <code>com.my_company.my_application</code>, starts listening for
messages from that port and sends one outgoing message:
<pre>
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" });
</pre>
<p>
$(ref:runtime.sendNativeMessage) can be used to send a message to native
application without creating a port, e.g.:
<pre>
chrome.runtime.sendNativeMessage('com.my_company.my_application',
{ text: "Hello" },
function(response) {
console.log("Received " + response);
});
</pre>
<h2 id="security-considerations">Security considerations</h2> <h2 id="security-considerations">Security considerations</h2>
...@@ -459,8 +334,8 @@ chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { ...@@ -459,8 +334,8 @@ chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
You can find simple examples of communication via messages in the You can find simple examples of communication via messages in the
<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/">examples/api/messaging</a> <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/">examples/api/messaging</a>
directory. directory.
<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/nativeMessaging/">examples/api/nativeMessaging</a> The <a href="nativeMessaging#examples">native messaging sample</a> demonstrates
contains an example application that uses native messaging. how a Chrome app can communicate with a native app.
For more examples and for help in viewing the source code, see For more examples and for help in viewing the source code, see
<a href="samples">Samples</a>. <a href="samples">Samples</a>.
</p> </p>
<h1>Native messaging</h1>
<p>
Extensions and apps can exchange messages with native applications using an API
that is similar to the other <a href="messaging">message passing APIs</a>.
Native applications that support this feature must register a
<em>native messaging host</em> that knows how to communicate with the extension.
Chrome starts the host in a separate process and communicates with it using
standard input and standard output streams.
<h2 id="native-messaging-host">Native messaging host</h2>
<p>
In order to register a native messaging host the application must install a
manifest file that defines the native messaging host configuration. Below is an
example of the manifest file:
<pre data-filename="manifest.json">
{
"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/"
]
}
</pre>
<p>The native messaging host manifest file must be valid JSON and contains the
following fields:
<table class="simple" id="native-messaging-host-manifest">
<tr>
<th>Name</th>
<th>Description</th>
</tr>
<tr>
<td><code>name</code></td>
<td>Name of the native messaging host. Clients pass this string to
$(ref:runtime.connectNative) or $(ref:runtime.sendNativeMessage).
This name can only contain lowercase alphanumeric characters, underscores
and dots. The name cannot start or end with a dot, and a dot cannot be
followed by another dot.
</td>
</tr>
<tr>
<td><code>description</code></td>
<td>Short application description.</td>
</tr>
<tr>
<td><code>path</code></td>
<td>Path to the native messaging host binary. On Linux and OSX the path must
be absolute. On Windows it can be relative to the directory in which the
manifest file is located.</td>
</tr>
<tr>
<td><code>type</code></td>
<td>Type of the interface used to communicate with the native messaging
host. Currently there is only one possible value for this parameter:
<code>stdio</code>. It indicates that Chrome should use <code>stdin</code>
and <code>stdout</code> to communicate with the host.</td>
</tr>
<tr>
<td><code>allowed_origins</code></td>
<td>List of extensions that should have access to the native messaging host.
Wildcards such as <code>chrome-extension://*/*</code> are <em>not</em>
allowed.</td>
</tr>
</table>
<h3 id="native-messaging-host-location">Native messaging host location</h3>
<p>The location of the manifest file depends on the platform.
<p id="native-messaging-host-location-windows">
On <b>Windows</b>, the manifest file can be located anywhere in the file system.
The application installer must create registry key
<code>HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\<em>com.my_company.my_application</em></code>
or
<code>HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts\<em>com.my_company.my_application</em></code>,
and set default value of that key to the full path to the manifest file.
For example, using the following command:<br>
<pre>
REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\<em>com.my_company.my_application</em>" /ve /t REG_SZ /d "C:\path\to\nmh-manifest.json" /f
</pre>
or using the following <code>.reg</code> file:
<pre>
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\<em>com.my_company.my_application</em>]
@="C:\\path\\to\\nmh-manifest.json"
</pre>
When Chrome looks for native messaging hosts, first the 32-bit registry is
queried, then the 64-bit registry.
<p id="native-messaging-host-location-nix">
On <b>OS X</b> and <b>Linux</b>, the location of the native messaging host's
manifest file varies by the browser (Google Chrome or Chromium).
The system-wide native messaging hosts are looked up at a fixed location,
while the user-level native messaging hosts are looked up in a subdirectory within the
<a href="https://www.chromium.org/user-experience/user-data-directory">user profile directory</a>
called <code>NativeMessagingHosts</code>.
<dl>
<dt>OS X (system-wide)
<dd>Google Chrome: <code>/Library/Google/Chrome/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>
<dd>Chromium: <code>/Library/Application Support/Chromium/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>
<dt>OS X (user-specific, <em>default</em> path)
<dd>Google Chrome: <code>~/Library/Application Support/Google/Chrome/Default/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>
<dd>Chromium: <code>~/Library/Application Support/Chromium/Default/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>
</dl>
<dl>
<dt>Linux (system-wide)
<dd>Google Chrome: <code>/etc/opt/chrome/native-messaging-hosts/<em>com.my_company.my_application</em>.json</code>
<dd>Chromium: <code>/etc/chromium/native-messaging-hosts/<em>com.my_company.my_application</em>.json</code>
<dt>Linux (user-specific, <em>default</em> path)
<dd>Google Chrome: <code>~/.config/google-chrome/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>
<dd>Chromium: <code>~/.config/chromium/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>
</dl>
<h3 id="native-messaging-host-protocol">Native messaging protocol</h3>
<p>
Chrome starts each native messaging host in a separate process and communicates
with it using standard input (<code>stdin</code>) and standard output
(<code>stdout</code>). The same format is used to send messages in both
directions: each message is serialized using JSON, UTF-8 encoded
and is preceded with 32-bit message length in native byte order.
The maximum size of a single message from the native messaging host is 1 MB,
mainly to protect Chrome from misbehaving native applications. The maximum
size of the message sent to the native messaging host is 4 GB.
<p>
When a messaging port is created using $(ref:runtime.connectNative) Chrome
starts native messaging host process and keeps it running until the port is
destroyed. On the other hand, when a message is sent using
$(ref:runtime.sendNativeMessage), without creating a messaging port, Chrome starts
a new native messaging host process for each message. In that case the first
message generated by the host process is handled as a response to the original
request, i.e. Chrome will pass it to the response callback specified when
$(ref:runtime.sendNativeMessage) is called. All other messages generated by the
native messaging host in that case are ignored.
<h2 id="native-messaging-client">Connecting to a native application</h2>
<p>
Sending and receiving messages to and from a native application is very similar
to cross-extension messaging. The main difference is that
$(ref:runtime.connectNative) is used instead of $(ref:runtime.connect),
and $(ref:runtime.sendNativeMessage) is used instead of $(ref:runtime.sendMessage).
<p>
The Following example creates a $(ref:runtime.Port) object that's connected to native
messaging host <code>com.my_company.my_application</code>, starts listening for
messages from that port and sends one outgoing message:
<pre>
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" });
</pre>
<p>
$(ref:runtime.sendNativeMessage) can be used to send a message to native
application without creating a port, e.g.:
<pre>
chrome.runtime.sendNativeMessage('com.my_company.my_application',
{ text: "Hello" },
function(response) {
console.log("Received " + response);
});
</pre>
<h2 id="native-messaging-debugging">Debugging native messaging</h2>
<p>
When the native messaging host fails to start, writes to <code>stderr</code> or
when it violates the communication protocol, output is written to the error log
of Chrome.
On Linux and OS X, this log can easily be accessed by starting Chrome from the
command line and watching its output in the terminal.
On Windows, use <code>--enable-logging</code> as explained at
<a href="https://www.chromium.org/for-testers/enable-logging">How to enable logging</a>.
<p>
Here are some errors and tips for solving the issues:
<dl>
<dt>Failed to start native messaging host.
<dd>Check whether you have sufficient permissions to execute the file.
<dt>Invalid native messaging host name specified.
<dd>Check whether the name contains any invalid characters.
Only lowercase alphanumeric characters, underscores and dots are allowed.
A name cannot start or end with a dot, and a dot cannot be followed by
another dot.
<dt>Native host has exited.
<dd>The pipe to the native messaging host was broken before the message was
read by Chrome. This is most likely initiated from your native messaging host.
<dt>Specified native messaging host not found.
<dd>
<ul>
<li>
Is the name spelled correctly in the extension and in the manifest file?
<li>
Is the manifest put in the right directory and with the correct name? See
<a href="#native-messaging-host-location">native messaging host location</a>
for the expected formats.
<li>
Is the manifest file in the correct format? In particular, is the JSON
syntax correct and do the values match the definition of a
<a href="native-messaging-host-manifest">native messaging host manifest</a>?
<li>
Does the file specified in <code>path</code> exist? On Windows, paths
may be relative, but on OS X and Linux, the paths must be absolute.
</ul>
<dt>Native messaging host <em>host name</em> is not registered. (Windows-only)
<dd>The native messaging host was not found in the Windows registry. Double-check
using <code>regedit</code> whether the key was really created and matches the
required format as documented at
<a href="#native-messaging-host-location">native messaging host location</a>.
<dt>Access to the specified native messaging host is forbidden.
<dd>Is the extension's origin listed in <code>allowed_origins</code>?
<dt>Error when communicating with the native messaging host.
<dd>This is a very common error and indicates an incorrect implementation of
the communication protocol in the native messaging host.
<ul>
<li>
Make sure that all output in <code>stdout</code> adheres to the native
messaging protocol. If you want to print some data for debugging purposes,
write to <code>stderr</code>.
<li>
Make sure that the 32-bit message length is in the platform's native
integer format (little-endian / big-endian).
<li>
The message length must not exceed 1024*1024.
<li>
The message size must be equal to the number of bytes in the message.
This may differ from the "length" of a string, because characters may be
represented by multiple bytes.
<li>
<b>Windows-only: Make sure that the program's I/O mode is set to
<code>O_BINARY</code></b>. By default, the I/O mode is <code>O_TEXT</code>,
which corrupts the message format as line breaks (<code>\n</code> =
<code>0A</code>) are replaced with Windows-style line endings
(<code>\r\n</code> = <code>0D 0A</code>). The I/O mode can be set using
<a href="http://msdn.microsoft.com/en-us/library/tw4k6df8.aspx"><code>__setmode</code></a>.
</ul>
</dl>
<h2 id="examples">Examples</h2>
<p>
The <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/docs/examples/api/nativeMessaging">examples/api/nativeMessaging</a>
directory contains an example application that uses native messaging to
communicate with a Python script that serves as a native messaging host.
The sample host's directory also contains scripts to install/remove the native
messaging host.
<p>
To try out the example, first download and extract the
<a href="https://developer.chrome.com/extensions/examples/api/nativeMessaging/app.zip">sample app</a>
and
<a href="https://developer.chrome.com/extensions/examples/api/nativeMessaging/host.zip">sample host</a>.
Run <code>install_host.bat</code> (Windows) or
<code>install_host.sh</code> (Linux / OS X) to install the native messaging
host.
Then <a href="getstarted#unpacked">load the app</a> and interact with the app.
Run <code>uninstall_host.bat</code> or <code>uninstall_host.sh</code> to
unregister the native messaging host when you are done.
{{+partials.standard_apps_article article:articles.nativeMessaging/}}
{{+partials.standard_extensions_article article:articles.nativeMessaging/}}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment