Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / common / extensions / docs / templates / articles / messaging.html
blob9fa7daad304fe0c8f00a880eb112605fadeae8f5
1 <h1>Message Passing</h1>
4 <p>
5 Since content scripts run in the context of a web page and not the extension,
6 they often need some way of communicating with the rest of the extension. For
7 example, an RSS reader extension might use content scripts to detect the
8 presence of an RSS feed on a page, then notify the background page in order to
9 display a page action icon for that page.
11 <p>
12 Communication between extensions and their content scripts works by using
13 message passing. Either side can listen for messages sent from the other end,
14 and respond on the same channel. A message can contain any valid JSON object
15 (null, boolean, number, string, array, or object). There is a simple API for
16 <a href="#simple">one-time requests</a>
17 and a more complex API that allows you to have
18 <a href="#connect">long-lived connections</a>
19 for exchanging multiple messages with a shared context. It is also possible to
20 send a message to another extension if you know its ID, which is covered in
21 the
22 <a href="#external">cross-extension messages</a>
23 section.
26 <h2 id="simple">Simple one-time requests</h2>
27 <p>
28 If you only need to send a single message to another part of your extension
29 (and optionally get a response back), you should use the simplified
30 $ref:runtime.sendMessage
32 $ref:tabs.sendMessage
33 methods. This lets you send a one-time JSON-serializable message from a
34 content script to extension, or vice versa, respectively. An optional
35 callback parameter allows you handle the response from the other side, if
36 there is one.
38 <p>
39 Sending a request from a content script looks like this:
40 <pre data-filename="contentscript.js">
41 chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
42 console.log(response.farewell);
43 });
44 </pre>
46 <p>
47 Sending a request from the extension to a content script looks very similar,
48 except that you need to specify which tab to send it to. This example
49 demonstrates sending a message to the content script in the selected tab.
50 <pre data-filename="background.html">
51 chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
52 chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
53 console.log(response.farewell);
54 });
55 });
56 </pre>
58 <p>
59 On the receiving end, you need to set up an
60 $ref:runtime.onMessage
61 event listener to handle the message. This looks the same from a content
62 script or extension page.
63 <pre>
64 chrome.runtime.onMessage.addListener(
65 function(request, sender, sendResponse) {
66 console.log(sender.tab ?
67 "from a content script:" + sender.tab.url :
68 "from the extension");
69 if (request.greeting == "hello")
70 sendResponse({farewell: "goodbye"});
71 });
72 </pre>
74 <p class="note">
75 <b>Note:</b> If multiple pages are listening for onMessage events, only the
76 first to call sendResponse() for a particular event will succeed in sending the
77 response. All other responses to that event will be ignored.
78 </p>
81 <h2 id="connect">Long-lived connections</h2>
82 <p>
83 Sometimes it's useful to have a conversation that lasts longer than a single
84 request and response. In this case, you can open a long-lived channel from
85 your content script to an extension page, or vice versa, using
86 $ref:runtime.connect
88 $ref:tabs.connect respectively. The
89 channel can optionally have a name, allowing you to distinguish between
90 different types of connections.
92 <p>
93 One use case might be an automatic form fill extension. The content script
94 could open a channel to the extension page for a particular login, and send a
95 message to the extension for each input element on the page to request the
96 form data to fill in. The shared connection allows the extension to keep
97 shared state linking the several messages coming from the content script.
99 <p>
100 When establishing a connection, each end is given a
101 $ref:runtime.Port
102 object which is used for sending and receiving messages through that
103 connection.
106 Here is how you open a channel from a content script, and send and listen for
107 messages:
108 <pre data-filename="contentscript.js">
109 var port = chrome.runtime.connect({name: "knockknock"});
110 port.postMessage({joke: "Knock knock"});
111 port.onMessage.addListener(function(msg) {
112 if (msg.question == "Who's there?")
113 port.postMessage({answer: "Madame"});
114 else if (msg.question == "Madame who?")
115 port.postMessage({answer: "Madame... Bovary"});
117 </pre>
120 Sending a request from the extension to a content script looks very similar,
121 except that you need to specify which tab to connect to. Simply replace the
122 call to connect in the above example with
123 $ref:tabs.connect.
126 In order to handle incoming connections, you need to set up a
127 $ref:runtime.onConnect
128 event listener. This looks the same from a content script or an extension
129 page. When another part of your extension calls "connect()", this event is
130 fired, along with the
131 $ref:runtime.Port
132 object you can use to send and receive messages through the connection. Here's
133 what it looks like to respond to incoming connections:
134 <pre>
135 chrome.runtime.onConnect.addListener(function(port) {
136 console.assert(port.name == "knockknock");
137 port.onMessage.addListener(function(msg) {
138 if (msg.joke == "Knock knock")
139 port.postMessage({question: "Who's there?"});
140 else if (msg.answer == "Madame")
141 port.postMessage({question: "Madame who?"});
142 else if (msg.answer == "Madame... Bovary")
143 port.postMessage({question: "I don't get it."});
146 </pre>
149 You may want to find out when a connection is closed, for example if you are
150 maintaining separate state for each open port. For this you can listen to the
151 $ref:runtime.Port.onDisconnect
152 event. This event is fired either when the other side of the channel manually
153 calls
154 $ref:runtime.Port.disconnect, or when the page
155 containing the port is unloaded (for example if the tab is navigated).
156 onDisconnect is guaranteed to be fired only once for any given port.
159 <h2 id="external">Cross-extension messaging</h2>
161 In addition to sending messages between different components in your
162 extension, you can use the messaging API to communicate with other extensions.
163 This lets you expose a public API that other extensions can take advantage of.
166 Listening for incoming requests and connections is similar to the internal
167 case, except you use the
168 $ref:runtime.onMessageExternal
170 $ref:runtime.onConnectExternal
171 methods. Here's an example of each:
172 <pre>
173 // For simple requests:
174 chrome.runtime.onMessageExternal.addListener(
175 function(request, sender, sendResponse) {
176 if (sender.id == blacklistedExtension)
177 return; // don't allow this extension access
178 else if (request.getTargetData)
179 sendResponse({targetData: targetData});
180 else if (request.activateLasers) {
181 var success = activateLasers();
182 sendResponse({activateLasers: success});
186 // For long-lived connections:
187 chrome.runtime.onConnectExternal.addListener(function(port) {
188 port.onMessage.addListener(function(msg) {
189 // See other examples for sample onMessage handlers.
192 </pre>
195 Likewise, sending a message to another extension is similar to sending one
196 within your extension. The only difference is that you must pass the ID of the
197 extension you want to communicate with. For example:
198 <pre>
199 // The ID of the extension we want to talk to.
200 var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
202 // Make a simple request:
203 chrome.runtime.sendMessage(laserExtensionId, {getTargetData: true},
204 function(response) {
205 if (targetInRange(response.targetData))
206 chrome.runtime.sendMessage(laserExtensionId, {activateLasers: true});
209 // Start a long-running conversation:
210 var port = chrome.runtime.connect(laserExtensionId);
211 port.postMessage(...);
212 </pre>
215 <h2 id="external-webpage">Sending messages from web pages</h2>
217 Similar to <a href="#external">cross-extension messaging</a>,
218 your app or extension can receive and
219 respond to messages from regular web pages.
220 To use this feature, you must first
221 specify in your manifest.json which web sites you want to communicate with. For
222 example:
224 <pre data-filename="manifest.json">
225 "externally_connectable": {
226 "matches": ["*://*.example.com/*"]
228 </pre>
231 This will expose the messaging API to any page which matches the URL patterns
232 you specify. The URL pattern must contain at least a
233 <a href="http://en.wikipedia.org/wiki/Second-level_domain">second-level domain</a>
234 - that is, hostname
235 patterns like "*", "*.com", "*.co.uk", and "*.appspot.com" are prohibited.
236 From the web page, use the
237 $ref:runtime.sendMessage
239 $ref:runtime.connect
240 APIs to send a message to a specific app or extension. For example:
241 <pre>
242 // The ID of the extension we want to talk to.
243 var editorExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
245 // Make a simple request:
246 chrome.runtime.sendMessage(editorExtensionId, {openUrlInEditor: url},
247 function(response) {
248 if (!response.success)
249 handleError(url);
251 </pre>
254 From your app or extension, you may listen to messages from web pages via the
255 $ref:runtime.onMessageExternal
257 $ref:runtime.onConnectExternal
258 APIs, similar to <a href="#external">cross-extension messaging</a>.
259 Only the web page can initiate a connection.
260 Here is an example:
262 <pre>
263 chrome.runtime.onMessageExternal.addListener(
264 function(request, sender, sendResponse) {
265 if (sender.url == blacklistedWebsite)
266 return; // don't allow this web page access
267 if (request.openUrlInEditor)
268 openUrl(request.openUrlInEditor);
270 </pre>
273 <h2 id="native-messaging">Native messaging</h2>
275 Extensions can exchange messages with native applications. Native
276 applications that support this feature must register a <em>native messaging
277 host</em> that knows how to communicate with the extension. Chrome starts the
278 host in a separate process and communicates with it using standard input and
279 standard output streams.
281 <h3 id="native-messaging-host">Native messaging host</h3>
283 In order to register a native messaging host the application must install a
284 manifest file that defines the native messaging host configuration. Below is an
285 example of the manifest file:
286 <pre data-filename="manifest.json">
288 "name": "com.my_company.my_application",
289 "description": "My Application",
290 "path": "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe",
291 "type": "stdio",
292 "allowed_origins": [
293 "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
296 </pre>
298 <p>Native messaging host manifest file contains the following fields:
299 <table class="simple">
300 <tr>
301 <th>Name</th>
302 <th>Description</th>
303 </tr>
304 <tr>
305 <td><code>name</code></td>
306 <td>Name of the native messaging host. Clients pass this string to
307 $ref:runtime.connectNative or $ref:runtime.sendNativeMessage.</td>
308 </tr>
309 <tr>
310 <td><code>description</code></td>
311 <td>Short application description.</td>
312 </tr>
313 <tr>
314 <td><code>path</code></td>
315 <td>Path to the native messaging host binary. On Linux and OSX the path must
316 be absolute. On Windows it can be relative to the directory in which the
317 manifest file is located.</td>
318 </tr>
319 <tr>
320 <td><code>type</code></td>
321 <td>Type of the interface used to communicate with the native messaging
322 host. Currently there is only one possible value for this parameter:
323 <code>stdio</code>. It indicates that Chrome should use <code>stdin</code>
324 and <code>stdout</code> to communicate with the host.</td>
325 </tr>
326 <tr>
327 <td><code>allowed_origins</code></td>
328 <td>List of extensions that should have access to the native messaging host.</td>
329 </tr>
330 </table>
332 <p>Location of the manifest file depends on the platform:
334 <dl>
335 <dt>Windows:</dt>
336 <dd>The manifest file can be located anywhere in the file system.
337 The application installer must create registry key
338 <code>HKEY_LOCAL_MACHINE\SOFTWARE\Google\Chrome\NativeMessagingHosts\<em>com.my_company.my_application</em></code>
339 and set default value of that key to the full path to the manifest file.
340 </dd>
342 <dt>OSX:</dt>
343 <dd>The manifest file must be placed at
344 <code>/Library/Google/Chrome/NativeMessagingHosts/<em>com.my_company.my_application</em>.json</code>
345 </dd>
346 <dt>Linux:</dt>
347 <dd>The manifest file must be placed at
348 <code>/etc/opt/chrome/native-messaging-hosts/<em>com.my_company.my_application</em>.json</code>
349 </dd>
350 </dl>
353 Chrome starts each native messaging host in a separate process and communicates
354 with it using standard input (<code>stdin</code>) and standard output
355 (<code>stdout</code>). The same format is used to send messages in both
356 directions: each message is serialized using JSON, UTF-8 encoded
357 and is preceded with 32-bit message length in native byte order.
360 When a messaging port is created using $ref:runtime.connectNative Chrome
361 starts native messaging host process and keeps it running until the port is
362 destroyed. On the other hand, when a message is sent using
363 $ref:runtime.sendNativeMessage, without creating a messaging port, Chrome starts
364 a new native messaging host process for each message. In that case the first
365 message generated by the host process is handled as a response to the original
366 request, i.e. Chrome will pass it to the response callback specified when
367 $ref:runtime.sendNativeMessage is called. All other messages generated by the
368 native messaging host in that case are ignored.
370 <h3 id="native-messaging-client">Connecting to a native application</h3>
372 Sending and receiving messages to and from a native application is very similar
373 to cross-extension messaging. The main difference is that
374 $ref:runtime.connectNative is used instead of $ref:runtime.connect,
375 and $ref:runtime.sendNativeMessage is used instead of $ref:runtime.sendMessage.
378 The Following example creates a $ref:runtime.Port object that's connected to native
379 messaging host <code>com.my_company.my_application</code>, starts listening for
380 messages from that port and sends one outgoing message:
381 <pre>
382 var port = chrome.runtime.connectNative('com.my_company.my_application');
383 port.onMessage.addListener(function(msg) {
384 console.log("Received" + msg);
386 port.onDisconnect.addListener(function() {
387 console.log("Disconnected");
389 port.postMessage({ text: "Hello, my_application" });
390 </pre>
393 $ref:runtime.sendNativeMessage can be used to send a message to native
394 application without creating a port, e.g.:
395 <pre>
396 chrome.runtime.sendNativeMessage('com.my_company.my_application',
397 { text: "Hello" },
398 function(response) {
399 console.log("Received " + response);
401 </pre>
403 <h2 id="security-considerations">Security considerations</h2>
406 When receiving a message from a content script or another extension, your
407 background page should be careful not to fall victim to <a
408 href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
409 scripting</a>. Specifically, avoid using dangerous APIs such as the
410 below:
411 </p>
412 <pre data-filename="background.js">
413 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
414 // WARNING! Might be evaluating an evil script!
415 var resp = eval("(" + response.farewell + ")");
417 </pre>
418 <pre data-filename="background.js">
419 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
420 // WARNING! Might be injecting a malicious script!
421 document.getElementById("resp").innerHTML = response.farewell;
423 </pre>
425 Instead, prefer safer APIs that do not run scripts:
426 </p>
427 <pre data-filename="background.js">
428 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
429 // JSON.parse does not evaluate the attacker's scripts.
430 var resp = JSON.parse(response.farewell);
432 </pre>
433 <pre data-filename="background.js">
434 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
435 // innerText does not let the attacker inject HTML elements.
436 document.getElementById("resp").innerText = response.farewell;
438 </pre>
440 <h2 id="examples">Examples</h2>
443 You can find simple examples of communication via messages in the
444 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/">examples/api/messaging</a>
445 directory.
446 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/nativeMessaging/">examples/api/nativeMessaging</a>
447 contains an example application that uses native messaging.
448 Also see the
449 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr">contentscript_xhr</a> example,
450 in which a content script and its parent extension exchange messages,
451 so that the parent extension can perform
452 cross-site requests on behalf of the content script.
453 For more examples and for help in viewing the source code, see
454 <a href="samples.html">Samples</a>.
455 </p>