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

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

Powered by Google App Engine
This is Rietveld 408576698