Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: chrome/common/extensions/docs/server2/templates/articles/messaging.html

Issue 10832042: Extensions Docs Server: Doc conversion script (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: script/build.py fixes Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 <h1 class="page_title">Message Passing</h1>
2 <p>
3 Since content scripts run in the context of a web page and not the extension,
4 they often need some way of communicating with the rest of the extension. For
5 example, an RSS reader extension might use content scripts to detect the
6 presence of an RSS feed on a page, then notify the background page in order to
7 display a page action icon for that page.
8 <p>
9 Communication between extensions and their content scripts works by using
10 message passing. Either side can listen for messages sent from the other end,
11 and respond on the same channel. A message can contain any valid JSON object
12 (null, boolean, number, string, array, or object). There is a simple API for
13 <a href="#simple">one-time requests</a>
14 and a more complex API that allows you to have
15 <a href="#connect">long-lived connections</a>
16 for exchanging multiple messages with a shared context. It is also possible to
17 send a message to another extension if you know its ID, which is covered in
18 the
19 <a href="#external">cross-extension messages</a>
20 section.
21 <h2 id="simple">Simple one-time requests</h2>
22 <p>
23 If you only need to send a single message to another part of your extension
24 (and optionally get a response back), you should use the simplified
25 <a href="extension.html#method-sendMessage">chrome.extension.sendMessage()</a>
26 or
27 <a href="tabs.html#method-sendMessage">chrome.tabs.sendMessage()</a>
28 methods. This lets you send a one-time JSON-serializable message from a
29 content script to extension, or vice versa, respectively. An optional
30 callback parameter allows you handle the response from the other side, if
31 there is one.
32 <p>
33 Sending a request from a content script looks like this:
34 <pre>
35 contentscript.js
36 ================
37 chrome.extension.sendMessage({greeting: "hello"}, function(response) {
38 console.log(response.farewell);
39 });
40 </pre>
41 <p>
42 Sending a request from the extension to a content script looks very similar,
43 except that you need to specify which tab to send it to. This example
44 demonstrates sending a message to the content script in the selected tab.
45 <pre>
46 background.html
47 ===============
48 chrome.tabs.getSelected(null, function(tab) {
49 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
50 console.log(response.farewell);
51 });
52 });
53 </pre>
54 <p>
55 On the receiving end, you need to set up an
56 <a href="extension.html#event-onMessage">chrome.extension.onMessage</a>
57 event listener to handle the message. This looks the same from a content
58 script or extension page.
59 <pre>
60 chrome.extension.onMessage.addListener(
61 function(request, sender, sendResponse) {
62 console.log(sender.tab ?
63 "from a content script:" + sender.tab.url :
64 "from the extension");
65 if (request.greeting == "hello")
66 sendResponse({farewell: "goodbye"});
67 });
68 </pre>
69 <p class="note">
70 <b>Note:</b> If multiple pages are listening for onMessage events, only the
71 first to call sendResponse() for a particular event will succeed in sending the
72 response. All other responses to that event will be ignored.
73 </p>
74 <h2 id="connect">Long-lived connections</h2>
75 <p>
76 Sometimes it's useful to have a conversation that lasts longer than a single
77 request and response. In this case, you can open a long-lived channel from
78 your content script to an extension page, or vice versa, using
79 <a href="extension.html#method-connect">chrome.extension.connect()</a>
80 or
81 <a href="tabs.html#method-connect">chrome.tabs.connect()</a> respectively. The
82 channel can optionally have a name, allowing you to distinguish between
83 different types of connections.
84 <p>
85 One use case might be an automatic form fill extension. The content script
86 could open a channel to the extension page for a particular login, and send a
87 message to the extension for each input element on the page to request the
88 form data to fill in. The shared connection allows the extension to keep
89 shared state linking the several messages coming from the content script.
90 <p>
91 When establishing a connection, each end is given a
92 <a href="extension.html#type-extension.Port">Port</a>
93 object which is used for sending and receiving messages through that
94 connection.
95 <p>
96 Here is how you open a channel from a content script, and send and listen for
97 messages:
98 <pre>
99 contentscript.js
100 ================
101 var port = chrome.extension.connect({name: "knockknock"});
102 port.postMessage({joke: "Knock knock"});
103 port.onMessage.addListener(function(msg) {
104 if (msg.question == "Who's there?")
105 port.postMessage({answer: "Madame"});
106 else if (msg.question == "Madame who?")
107 port.postMessage({answer: "Madame... Bovary"});
108 });
109 </pre>
110 <p>
111 Sending a request from the extension to a content script looks very similar,
112 except that you need to specify which tab to connect to. Simply replace the
113 call to connect in the above example with
114 <a href="tabs.html#method-connect">chrome.tabs.connect(tabId, {name:
115 "knockknock"})</a>.
116 <p>
117 In order to handle incoming connections, you need to set up a
118 <a href="extension.html#event-onConnect">chrome.extension.onConnect</a>
119 event listener. This looks the same from a content script or an extension
120 page. When another part of your extension calls "connect()", this event is
121 fired, along with the
122 <a href="extension.html#type-extension.Port">Port</a>
123 object you can use to send and receive messages through the connection. Here's
124 what it looks like to respond to incoming connections:
125 <pre>
126 chrome.extension.onConnect.addListener(function(port) {
127 console.assert(port.name == "knockknock");
128 port.onMessage.addListener(function(msg) {
129 if (msg.joke == "Knock knock")
130 port.postMessage({question: "Who's there?"});
131 else if (msg.answer == "Madame")
132 port.postMessage({question: "Madame who?"});
133 else if (msg.answer == "Madame... Bovary")
134 port.postMessage({question: "I don't get it."});
135 });
136 });
137 </pre>
138 <p>
139 You may want to find out when a connection is closed, for example if you are
140 maintaining separate state for each open port. For this you can listen to the
141 <a href="extension.html#type-extension.Port">Port.onDisconnect</a>
142 event. This event is fired either when the other side of the channel manually
143 calls
144 <a href="extension.html#type-extension.Port">Port.disconnect()</a>, or when the page
145 containing the port is unloaded (for example if the tab is navigated).
146 onDisconnect is guaranteed to be fired only once for any given port.
147 <h2 id="external">Cross-extension messaging</h2>
148 <p>
149 In addition to sending messages between different components in your
150 extension, you can use the messaging API to communicate with other extensions.
151 This lets you expose a public API that other extensions can take advantage of.
152 <p>
153 Listening for incoming requests and connections is similar to the internal
154 case, except you use the
155 <a href="extension.html#event-onMessageExternal">chrome.extension.onMessageExter nal</a>
156 or
157 <a href="extension.html#event-onConnectExternal">chrome.extension.onConnectExter nal</a>
158 methods. Here's an example of each:
159 <pre>
160 // For simple requests:
161 chrome.extension.onMessageExternal.addListener(
162 function(request, sender, sendResponse) {
163 if (sender.id == blacklistedExtension)
164 return; // don't allow this extension access
165 else if (request.getTargetData)
166 sendResponse({targetData: targetData});
167 else if (request.activateLasers) {
168 var success = activateLasers();
169 sendResponse({activateLasers: success});
170 }
171 });
172 // For long-lived connections:
173 chrome.extension.onConnectExternal.addListener(function(port) {
174 port.onMessage.addListener(function(msg) {
175 // See other examples for sample onMessage handlers.
176 });
177 });
178 </pre>
179 <p>
180 Likewise, sending a message to another extension is similar to sending one
181 within your extension. The only difference is that you must pass the ID of the
182 extension you want to communicate with. For example:
183 <pre>
184 // The ID of the extension we want to talk to.
185 var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
186 // Make a simple request:
187 chrome.extension.sendMessage(laserExtensionId, {getTargetData: true},
188 function(response) {
189 if (targetInRange(response.targetData))
190 chrome.extension.sendMessage(laserExtensionId, {activateLasers: true});
191 });
192 // Start a long-running conversation:
193 var port = chrome.extension.connect(laserExtensionId);
194 port.postMessage(...);
195 </pre>
196 <h2 id="security-considerations">Security considerations</h2>
197 <p>
198 When receiving a message from a content script or another extension, your
199 background page should be careful not to fall victim to <a
200 href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
201 scripting</a>. Specifically, avoid using dangerous APIs such as the
202 below:
203 </p>
204 <pre>background.html
205 ===============
206 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
207 // WARNING! Might be evaluating an evil script!
208 var resp = eval("(" + response.farewell + ")");
209 });
210 background.html
211 ===============
212 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
213 // WARNING! Might be injecting a malicious script!
214 document.getElementById("resp").innerHTML = response.farewell;
215 });
216 </pre>
217 <p>
218 Instead, prefer safer APIs that do not run scripts:
219 </p>
220 <pre>background.html
221 ===============
222 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
223 // JSON.parse does not evaluate the attacker's scripts.
224 var resp = JSON.parse(response.farewell);
225 });
226 background.html
227 ===============
228 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
229 // innerText does not let the attacker inject HTML elements.
230 document.getElementById("resp").innerText = response.farewell;
231 });
232 </pre>
233 <h2 id="examples">Examples</h2>
234 <p>
235 You can find simple examples of communication via messages in the
236 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extension s/docs/examples/api/messaging/">examples/api/messaging</a>
237 directory.
238 Also see the
239 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extension s/docs/examples/howto/contentscript_xhr">contentscript_xhr</a> example,
240 in which a content script and its parent extension exchange messages,
241 so that the parent extension can perform
242 cross-site requests on behalf of the content script.
243 For more examples and for help in viewing the source code, see
244 <a href="samples.html">Samples</a>.
245 </p>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698