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

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: everything but svn stuff 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>Message Passing</h1>
2
3
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.
10
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.
24
25
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 <a href="extension.html#method-sendMessage">chrome.extension.sendMessage()</a>
31 or
32 <a href="tabs.html#method-sendMessage">chrome.tabs.sendMessage()</a>
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.
37
38 <p>
39 Sending a request from a content script looks like this:
40 <pre>
41 contentscript.js
42 ================
43 chrome.extension.sendMessage({greeting: "hello"}, function(response) {
44 console.log(response.farewell);
45 });
46 </pre>
47
48 <p>
49 Sending a request from the extension to a content script looks very similar,
50 except that you need to specify which tab to send it to. This example
51 demonstrates sending a message to the content script in the selected tab.
52 <pre>
53 background.html
54 ===============
55 chrome.tabs.getSelected(null, function(tab) {
56 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
57 console.log(response.farewell);
58 });
59 });
60 </pre>
61
62 <p>
63 On the receiving end, you need to set up an
64 <a href="extension.html#event-onMessage">chrome.extension.onMessage</a>
65 event listener to handle the message. This looks the same from a content
66 script or extension page.
67 <pre>
68 chrome.extension.onMessage.addListener(
69 function(request, sender, sendResponse) {
70 console.log(sender.tab ?
71 "from a content script:" + sender.tab.url :
72 "from the extension");
73 if (request.greeting == "hello")
74 sendResponse({farewell: "goodbye"});
75 });
76 </pre>
77
78 <p class="note">
79 <b>Note:</b> If multiple pages are listening for onMessage events, only the
80 first to call sendResponse() for a particular event will succeed in sending the
81 response. All other responses to that event will be ignored.
82 </p>
83
84
85 <h2 id="connect">Long-lived connections</h2>
86 <p>
87 Sometimes it's useful to have a conversation that lasts longer than a single
88 request and response. In this case, you can open a long-lived channel from
89 your content script to an extension page, or vice versa, using
90 <a href="extension.html#method-connect">chrome.extension.connect()</a>
91 or
92 <a href="tabs.html#method-connect">chrome.tabs.connect()</a> respectively. The
93 channel can optionally have a name, allowing you to distinguish between
94 different types of connections.
95
96 <p>
97 One use case might be an automatic form fill extension. The content script
98 could open a channel to the extension page for a particular login, and send a
99 message to the extension for each input element on the page to request the
100 form data to fill in. The shared connection allows the extension to keep
101 shared state linking the several messages coming from the content script.
102
103 <p>
104 When establishing a connection, each end is given a
105 <a href="extension.html#type-extension.Port">Port</a>
106 object which is used for sending and receiving messages through that
107 connection.
108
109 <p>
110 Here is how you open a channel from a content script, and send and listen for
111 messages:
112 <pre>
113 contentscript.js
114 ================
115 var port = chrome.extension.connect({name: "knockknock"});
116 port.postMessage({joke: "Knock knock"});
117 port.onMessage.addListener(function(msg) {
118 if (msg.question == "Who's there?")
119 port.postMessage({answer: "Madame"});
120 else if (msg.question == "Madame who?")
121 port.postMessage({answer: "Madame... Bovary"});
122 });
123 </pre>
124
125 <p>
126 Sending a request from the extension to a content script looks very similar,
127 except that you need to specify which tab to connect to. Simply replace the
128 call to connect in the above example with
129 <a href="tabs.html#method-connect">chrome.tabs.connect(tabId, {name:
130 "knockknock"})</a>.
131
132 <p>
133 In order to handle incoming connections, you need to set up a
134 <a href="extension.html#event-onConnect">chrome.extension.onConnect</a>
135 event listener. This looks the same from a content script or an extension
136 page. When another part of your extension calls "connect()", this event is
137 fired, along with the
138 <a href="extension.html#type-extension.Port">Port</a>
139 object you can use to send and receive messages through the connection. Here's
140 what it looks like to respond to incoming connections:
141 <pre>
142 chrome.extension.onConnect.addListener(function(port) {
143 console.assert(port.name == "knockknock");
144 port.onMessage.addListener(function(msg) {
145 if (msg.joke == "Knock knock")
146 port.postMessage({question: "Who's there?"});
147 else if (msg.answer == "Madame")
148 port.postMessage({question: "Madame who?"});
149 else if (msg.answer == "Madame... Bovary")
150 port.postMessage({question: "I don't get it."});
151 });
152 });
153 </pre>
154
155 <p>
156 You may want to find out when a connection is closed, for example if you are
157 maintaining separate state for each open port. For this you can listen to the
158 <a href="extension.html#type-extension.Port">Port.onDisconnect</a>
159 event. This event is fired either when the other side of the channel manually
160 calls
161 <a href="extension.html#type-extension.Port">Port.disconnect()</a>, or when the page
162 containing the port is unloaded (for example if the tab is navigated).
163 onDisconnect is guaranteed to be fired only once for any given port.
164
165
166 <h2 id="external">Cross-extension messaging</h2>
167 <p>
168 In addition to sending messages between different components in your
169 extension, you can use the messaging API to communicate with other extensions.
170 This lets you expose a public API that other extensions can take advantage of.
171
172 <p>
173 Listening for incoming requests and connections is similar to the internal
174 case, except you use the
175 <a href="extension.html#event-onMessageExternal">chrome.extension.onMessageExter nal</a>
176 or
177 <a href="extension.html#event-onConnectExternal">chrome.extension.onConnectExter nal</a>
178 methods. Here's an example of each:
179 <pre>
180 // For simple requests:
181 chrome.extension.onMessageExternal.addListener(
182 function(request, sender, sendResponse) {
183 if (sender.id == blacklistedExtension)
184 return; // don't allow this extension access
185 else if (request.getTargetData)
186 sendResponse({targetData: targetData});
187 else if (request.activateLasers) {
188 var success = activateLasers();
189 sendResponse({activateLasers: success});
190 }
191 });
192
193 // For long-lived connections:
194 chrome.extension.onConnectExternal.addListener(function(port) {
195 port.onMessage.addListener(function(msg) {
196 // See other examples for sample onMessage handlers.
197 });
198 });
199 </pre>
200
201 <p>
202 Likewise, sending a message to another extension is similar to sending one
203 within your extension. The only difference is that you must pass the ID of the
204 extension you want to communicate with. For example:
205 <pre>
206 // The ID of the extension we want to talk to.
207 var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
208
209 // Make a simple request:
210 chrome.extension.sendMessage(laserExtensionId, {getTargetData: true},
211 function(response) {
212 if (targetInRange(response.targetData))
213 chrome.extension.sendMessage(laserExtensionId, {activateLasers: true});
214 });
215
216 // Start a long-running conversation:
217 var port = chrome.extension.connect(laserExtensionId);
218 port.postMessage(...);
219 </pre>
220
221 <h2 id="security-considerations">Security considerations</h2>
222
223 <p>
224 When receiving a message from a content script or another extension, your
225 background page should be careful not to fall victim to <a
226 href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
227 scripting</a>. Specifically, avoid using dangerous APIs such as the
228 below:
229 </p>
230 <pre>background.html
231 ===============
232 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
233 // WARNING! Might be evaluating an evil script!
234 var resp = eval("(" + response.farewell + ")");
235 });
236
237 background.html
238 ===============
239 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
240 // WARNING! Might be injecting a malicious script!
241 document.getElementById("resp").innerHTML = response.farewell;
242 });
243 </pre>
244 <p>
245 Instead, prefer safer APIs that do not run scripts:
246 </p>
247 <pre>background.html
248 ===============
249 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
250 // JSON.parse does not evaluate the attacker's scripts.
251 var resp = JSON.parse(response.farewell);
252 });
253
254 background.html
255 ===============
256 chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
257 // innerText does not let the attacker inject HTML elements.
258 document.getElementById("resp").innerText = response.farewell;
259 });
260 </pre>
261
262 <h2 id="examples">Examples</h2>
263
264 <p>
265 You can find simple examples of communication via messages in the
266 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extension s/docs/examples/api/messaging/">examples/api/messaging</a>
267 directory.
268 Also see the
269 <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extension s/docs/examples/howto/contentscript_xhr">contentscript_xhr</a> example,
270 in which a content script and its parent extension exchange messages,
271 so that the parent extension can perform
272 cross-site requests on behalf of the content script.
273 For more examples and for help in viewing the source code, see
274 <a href="samples.html">Samples</a>.
275 </p>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698