messaging.html revision 201ade2fbba22bfb27ae029f4d23fca6ded109a0
1<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
2    1) The <head> information in this page is significant, should be uniform
3       across api docs and should be edited only with knowledge of the
4       templating mechanism.
5    3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
6       browser, it will be re-generated from the template, json schema and
7       authored overview content.
8    4) The <body>.innerHTML is also generated by an offline step so that this
9       page may easily be indexed by search engines.
10--><html xmlns="http://www.w3.org/1999/xhtml"><head>
11    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
12    <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
13    <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
14    <script type="text/javascript" src="/third_party/jstemplate/jstemplate_compiled.js">
15    </script>
16    <script type="text/javascript" src="js/api_page_generator.js"></script>
17    <script type="text/javascript" src="js/bootstrap.js"></script>
18    <script type="text/javascript" src="js/sidebar.js"></script>
19  <title>Message Passing - Google Chrome Extensions - Google Code</title></head>
20  <body>  <div id="gc-container" class="labs">
21      <div id="devModeWarning">
22        You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
23      </div>
24      <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
25      <!-- In particular, sub-templates that recurse, must be used by allowing
26           jstemplate to make a copy of the template in this section which
27           are not operated on by way of the jsskip="true" -->
28      <div style="display:none">
29
30        <!-- VALUE -->
31        <div id="valueTemplate">
32          <dt>
33            <var>paramName</var>
34              <em>
35
36                <!-- TYPE -->
37                <div style="display:inline">
38                  (
39                    <span class="optional">optional</span>
40                    <span class="enum">enumerated</span>
41                    <span id="typeTemplate">
42                      <span>
43                        <a> Type</a>
44                      </span>
45                      <span>
46                        <span>
47                          array of <span><span></span></span>
48                        </span>
49                        <span>paramType</span>
50                        <span></span>
51                      </span>
52                    </span>
53                  )
54                </div>
55
56              </em>
57          </dt>
58          <dd class="todo">
59            Undocumented.
60          </dd>
61          <dd>
62            Description of this parameter from the json schema.
63          </dd>
64          <dd>
65            This parameter was added in version
66            <b><span></span></b>.
67            You must omit this parameter in earlier versions,
68            and you may omit it in any version.  If you require this
69            parameter, the manifest key
70            <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
71            can ensure that your extension won't be run in an earlier browser version.
72          </dd>
73
74          <!-- OBJECT PROPERTIES -->
75          <dd>
76            <dl>
77              <div>
78                <div>
79                </div>
80              </div>
81            </dl>
82          </dd>
83
84          <!-- FUNCTION PARAMETERS -->
85          <dd>
86            <div></div>
87          </dd>
88
89        </div> <!-- /VALUE -->
90
91        <div id="functionParametersTemplate">
92          <h5>Parameters</h5>
93          <dl>
94            <div>
95              <div>
96              </div>
97            </div>
98          </dl>
99        </div>
100      </div> <!-- /SUBTEMPLATES -->
101
102  <a id="top"></a>
103    <div id="skipto">
104      <a href="#gc-pagecontent">Skip to page content</a>
105      <a href="#gc-toc">Skip to main navigation</a>
106    </div>
107    <!-- API HEADER -->
108    <table id="header" width="100%" cellspacing="0" border="0">
109      <tbody><tr>
110        <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
111        <td valign="middle" width="100%" style="padding-left:0.6em;">
112          <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
113            <div id="gsc-search-box">
114              <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
115              <input type="hidden" name="ie" value="UTF-8">
116              <input type="text" name="q" value="" size="55">
117              <input class="gsc-search-button" type="submit" name="sa" value="Search">
118              <br>
119              <span class="greytext">e.g. "page action" or "tabs"</span>
120            </div>
121          </form>
122
123          <script type="text/javascript" src="http://www.google.com/jsapi"></script>
124          <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
125          <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&t13n_langs=en"></script>
126          <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&lang=en"></script>
127        </td>
128      </tr>
129    </tbody></table>
130
131    <div id="codesiteContent" class="">
132
133      <a id="gc-topnav-anchor"></a>
134      <div id="gc-topnav">
135        <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
136        <ul id="home" class="gc-topnav-tabs">
137          <li id="home_link">
138            <a href="index.html" title="Google Chrome Extensions home page">Home</a>
139          </li>
140          <li id="docs_link">
141            <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
142          </li>
143          <li id="faq_link">
144            <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
145          </li>
146          <li id="samples_link">
147            <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
148          </li>
149          <li id="group_link">
150            <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
151          </li>
152        </ul>
153      </div> <!-- end gc-topnav -->
154
155    <div class="g-section g-tpl-170">
156      <!-- SIDENAV -->
157      <div class="g-unit g-first" id="gc-toc">
158        <ul>
159          <li><a href="getstarted.html">Getting Started</a></li>
160          <li><a href="overview.html">Overview</a></li>
161          <li><a href="whats_new.html">What's New?</a></li>
162          <li><h2><a href="devguide.html">Developer's Guide</a></h2>
163            <ul>
164              <li>Browser UI
165                <ul>
166                  <li><a href="browserAction.html">Browser Actions</a></li>
167                  <li><a href="contextMenus.html">Context Menus</a></li>
168                  <li><a href="notifications.html">Desktop Notifications</a></li>
169                  <li><a href="omnibox.html">Omnibox</a></li>
170                  <li><a href="options.html">Options Pages</a></li>
171                  <li><a href="override.html">Override Pages</a></li>
172                  <li><a href="pageAction.html">Page Actions</a></li>
173                </ul>
174              </li>
175              <li>Browser Interaction
176                <ul>
177                  <li><a href="bookmarks.html">Bookmarks</a></li>
178                  <li><a href="cookies.html">Cookies</a></li>
179                  <li><a href="events.html">Events</a></li>
180                  <li><a href="history.html">History</a></li>
181                  <li><a href="management.html">Management</a></li>
182                  <li><a href="tabs.html">Tabs</a></li>
183                  <li><a href="windows.html">Windows</a></li>
184                </ul>
185              </li>
186              <li>Implementation
187                <ul>
188                  <li><a href="a11y.html">Accessibility</a></li>
189                  <li><a href="background_pages.html">Background Pages</a></li>
190                  <li><a href="content_scripts.html">Content Scripts</a></li>
191                  <li><a href="xhr.html">Cross-Origin XHR</a></li>
192                  <li><a href="idle.html">Idle</a></li>
193                  <li><a href="i18n.html">Internationalization</a></li>
194                  <li class="leftNavSelected">Message Passing</li>
195                  <li><a href="npapi.html">NPAPI Plugins</a></li>
196                </ul>
197              </li>
198              <li>Finishing
199                <ul>
200                  <li><a href="hosting.html">Hosting</a></li>
201                  <li><a href="external_extensions.html">Other Deployment Options</a></li>
202                </ul>
203              </li>
204            </ul>
205          </li>
206          <li><h2><a href="apps.html">Packaged Apps</a></h2></li>
207          <li><h2><a href="tutorials.html">Tutorials</a></h2>
208            <ul>
209              <li><a href="tut_debugging.html">Debugging</a></li>
210              <li><a href="tut_analytics.html">Google Analytics</a></li>
211              <li><a href="tut_oauth.html">OAuth</a></li>
212            </ul>
213          </li>
214          <li><h2>Reference</h2>
215            <ul>
216              <li>Formats
217                <ul>
218                  <li><a href="manifest.html">Manifest Files</a></li>
219                  <li><a href="match_patterns.html">Match Patterns</a></li>
220                </ul>
221              </li>
222              <li><a href="permission_warnings.html">Permission Warnings</a></li>
223              <li><a href="api_index.html">chrome.* APIs</a></li>
224              <li><a href="api_other.html">Other APIs</a></li>
225            </ul>
226          </li>
227          <li><h2><a href="samples.html">Samples</a></h2></li>
228          <div class="line"> </div>
229          <li><h2>More</h2>
230            <ul>
231              <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li>
232              <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li>
233              <li><a href="themes.html">Themes</a></li>
234            </ul>
235          </li>
236        </ul>
237      </div>
238      <script>
239        initToggles();
240      </script>
241
242    <div class="g-unit" id="gc-pagecontent">
243      <div id="pageTitle">
244        <h1 class="page_title">Message Passing</h1>
245      </div>
246        <!-- TABLE OF CONTENTS -->
247        <div id="toc">
248          <h2>Contents</h2>
249          <ol>
250            <li>
251              <a href="#simple">Simple one-time requests</a>
252              <ol>
253                <li style="display: none; ">
254                  <a>h3Name</a>
255                </li>
256              </ol>
257            </li><li>
258              <a href="#connect">Long-lived connections</a>
259              <ol>
260                <li style="display: none; ">
261                  <a>h3Name</a>
262                </li>
263              </ol>
264            </li><li>
265              <a href="#external">Cross-extension messaging</a>
266              <ol>
267                <li style="display: none; ">
268                  <a>h3Name</a>
269                </li>
270              </ol>
271            </li><li>
272              <a href="#security-considerations">Security considerations</a>
273              <ol>
274                <li style="display: none; ">
275                  <a>h3Name</a>
276                </li>
277              </ol>
278            </li><li>
279              <a href="#examples">Examples</a>
280              <ol>
281                <li style="display: none; ">
282                  <a>h3Name</a>
283                </li>
284              </ol>
285            </li>
286              <li style="display: none; ">
287                <a href="#apiReference">API reference</a>
288                <ol>
289                  <li>
290                    <a href="#properties">Properties</a>
291                    <ol>
292                      <li>
293                        <a href="#property-anchor">propertyName</a>
294                      </li>
295                    </ol>
296                  </li>
297                  <li>
298                    <a href="#methods">Methods</a>
299                    <ol>
300                      <li>
301                        <a href="#method-anchor">methodName</a>
302                      </li>
303                    </ol>
304                  </li>
305                  <li>
306                    <a href="#events">Events</a>
307                    <ol>
308                      <li>
309                        <a href="#event-anchor">eventName</a>
310                      </li>
311                    </ol>
312                  </li>
313                  <li>
314                    <a href="#types">Types</a>
315                    <ol>
316                      <li>
317                        <a href="#id-anchor">id</a>
318                      </li>
319                    </ol>
320                  </li>
321                </ol>
322              </li>
323          </ol>
324        </div>
325        <!-- /TABLE OF CONTENTS -->
326
327        <!-- Standard content lead-in for experimental API pages -->
328        <p id="classSummary" style="display: none; ">
329          For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
330        </p>
331
332        <!-- STATIC CONTENT PLACEHOLDER -->
333        <div id="static"><div id="pageData-name" class="pageData">Message Passing</div>
334<div id="pageData-showTOC" class="pageData">true</div>
335
336<p>
337Since content scripts run in the context of a web page and not the extension,
338they often need some way of communicating with the rest of the extension. For
339example, an RSS reader extension might use content scripts to detect the
340presence of an RSS feed on a page, then notify the background page in order to
341display a page action icon for that page.
342
343</p><p>
344Communication between extensions and their content scripts works by using
345message passing. Either side can listen for messages sent from the other end,
346and respond on the same channel. A message can contain any valid JSON object
347(null, boolean, number, string, array, or object). There is a simple API for
348<a href="#simple">one-time requests</a>
349and a more complex API that allows you to have
350<a href="#connect">long-lived connections</a>
351for exchanging multiple messages with a shared context. It is also possible to
352send a message to another extension if you know its ID, which is covered in
353the
354<a href="#external">cross-extension messages</a>
355section.
356
357
358</p><h2 id="simple">Simple one-time requests</h2>
359<p>
360If you only need to send a single message to another part of your extension
361(and optionally get a response back), you should use the simplified
362<a href="extension.html#method-sendRequest">chrome.extension.sendRequest()</a>
363or
364<a href="tabs.html#method-sendRequest">chrome.tabs.sendRequest()</a>
365methods. This lets you send a one-time JSON-serializable message from a
366content script to extension, or vice versa, respectively. An optional
367callback parameter allows you handle the response from the other side, if
368there is one.
369
370</p><p>
371Sending a request from a content script looks like this:
372</p><pre>contentscript.js
373================
374chrome.extension.sendRequest({greeting: "hello"}, function(response) {
375  console.log(response.farewell);
376});
377</pre>
378
379<p>
380Sending a request from the extension to a content script looks very similar,
381except that you need to specify which tab to send it to. This example
382demonstrates sending a message to the content script in the selected tab.
383</p><pre>background.html
384===============
385chrome.tabs.getSelected(null, function(tab) {
386  chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
387    console.log(response.farewell);
388  });
389});
390</pre>
391
392<p>
393On the receiving end, you need to set up an
394<a href="extension.html#event-onRequest">chrome.extension.onRequest</a>
395event listener to handle the message. This looks the same from a content
396script or extension page. The request will remain open until you call
397sendResponse, so it is good practice to call sendResponse with an empty
398object to allow the request to be cleaned up.
399</p><pre>chrome.extension.onRequest.addListener(
400  function(request, sender, sendResponse) {
401    console.log(sender.tab ?
402                "from a content script:" + sender.tab.url :
403                "from the extension");
404    if (request.greeting == "hello")
405      sendResponse({farewell: "goodbye"});
406    else
407      sendResponse({}); // snub them.
408  });
409</pre>
410
411<p class="note">
412<b>Note:</b> If multiple pages are listening for onRequest events, only the
413first to call sendResponse() for a particular event will succeed in sending the
414response. All other responses to that event will be ignored.
415</p>
416
417
418<h2 id="connect">Long-lived connections</h2>
419<p>
420Sometimes it's useful to have a conversation that lasts longer than a single
421request and response. In this case, you can open a long-lived channel from
422your content script to an extension page, or vice versa, using
423<a href="extension.html#method-connect">chrome.extension.connect()</a>
424or
425<a href="tabs.html#method-connect">chrome.tabs.connect()</a> respectively. The
426channel can optionally have a name, allowing you to distinguish between
427different types of connections.
428
429</p><p>
430One use case might be an automatic form fill extension. The content script
431could open a channel to the extension page for a particular login, and send a
432message to the extension for each input element on the page to request the
433form data to fill in. The shared connection allows the extension to keep
434shared state linking the several messages coming from the content script.
435
436</p><p>
437When establishing a connection, each end is given a
438<a href="extension.html#type-Port">Port</a>
439object which is used for sending and receiving messages through that
440connection.
441
442</p><p>
443Here is how you open a channel from a content script, and send and listen for
444messages:
445</p><pre>contentscript.js
446================
447var port = chrome.extension.connect({name: "knockknock"});
448port.postMessage({joke: "Knock knock"});
449port.onMessage.addListener(function(msg) {
450  if (msg.question == "Who's there?")
451    port.postMessage({answer: "Madame"});
452  else if (msg.question == "Madame who?")
453    port.postMessage({answer: "Madame... Bovary");
454});
455</pre>
456
457<p>
458Sending a request from the extension to a content script looks very similar,
459except that you need to specify which tab to connect to. Simply replace the
460call to connect in the above example with
461<a href="tabs.html#method-connect">chrome.tabs.connect(tabId, {name:
462"knockknock"})</a>.
463
464</p><p>
465In order to handle incoming connections, you need to set up a
466<a href="extension.html#event-onConnect">chrome.extension.onConnect</a>
467event listener. This looks the same from a content script or an extension
468page. When another part of your extension calls "connect()", this event is
469fired, along with the
470<a href="extension.html#type-Port">Port</a>
471object you can use to send and receive messages through the connection. Here's
472what it looks like to respond to incoming connections:
473</p><pre>chrome.extension.onConnect.addListener(function(port) {
474  console.assert(port.name == "knockknock");
475  port.onMessage.addListener(function(msg) {
476    if (msg.joke == "Knock knock")
477      port.postMessage({question: "Who's there?"});
478    else if (msg.answer == "Madame")
479      port.postMessage({question: "Madame who?"});
480    else if (msg.answer == "Madame... Bovary")
481      port.postMessage({question: "I don't get it."});
482  });
483});
484</pre>
485
486<p>
487You may want to find out when a connection is closed, for example if you are
488maintaining separate state for each open port. For this you can listen to the
489<a href="extension.html#type-Port">Port.onDisconnect</a>
490event. This event is fired either when the other side of the channel manually
491calls
492<a href="extension.html#type-Port">Port.disconnect()</a>, or when the page
493containing the port is unloaded (for example if the tab is navigated).
494onDisconnect is guaranteed to be fired only once for any given port.
495
496
497</p><h2 id="external">Cross-extension messaging</h2>
498<p>
499In addition to sending messages between different components in your
500extension, you can use the messaging API to communicate with other extensions.
501This lets you expose a public API that other extensions can take advantage of.
502
503</p><p>
504Listening for incoming requests and connections is similar to the internal
505case, except you use the
506<a href="extension.html#event-onRequestExternal">chrome.extension.onRequestExternal</a>
507or
508<a href="extension.html#event-onConnectExternal">chrome.extension.onConnectExternal</a>
509methods. Here's an example of each:
510</p><pre>// For simple requests:
511chrome.extension.onRequestExternal.addListener(
512  function(request, sender, sendResponse) {
513    if (sender.id == blacklistedExtension)
514      sendResponse({});  // don't allow this extension access
515    else if (request.getTargetData)
516      sendResponse({targetData: targetData});
517    else if (request.activateLasers) {
518      var success = activateLasers();
519      sendResponse({activateLasers: success});
520    }
521  });
522
523// For long-lived connections:
524chrome.extension.onConnectExternal.addListener(function(port) {
525  port.onMessage.addListener(function(msg) {
526    // See other examples for sample onMessage handlers.
527  });
528});
529</pre>
530
531<p>
532Likewise, sending a message to another extension is similar to sending one
533within your extension. The only difference is that you must pass the ID of the
534extension you want to communicate with. For example:
535</p><pre>// The ID of the extension we want to talk to.
536var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc";
537
538// Make a simple request:
539chrome.extension.sendRequest(laserExtensionId, {getTargetData: true},
540  function(response) {
541    if (targetInRange(response.targetData))
542      chrome.extension.sendRequest(laserExtensionId, {activateLasers: true});
543  });
544
545// Start a long-running conversation:
546var port = chrome.extension.connect(laserExtensionId);
547port.postMessage(...);
548</pre>
549
550<h2 id="security-considerations">Security considerations</h2>
551
552<p>
553When receiving a message from a content script or another extension, your
554background page should be careful not to fall victim to <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site
555scripting</a>.  Specifically, avoid using dangerous APIs such as the
556below:
557</p>
558<pre>background.html
559===============
560chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
561  // WARNING! Might be evaluating an evil script!
562  var resp = eval("(" + response.farewell + ")");
563});
564
565background.html
566===============
567chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
568  // WARNING! Might be injecting a malicious script!
569  document.getElementById("resp").innerHTML = response.farewell;
570});
571</pre>
572<p>
573Instead, prefer safer APIs that do not run scripts:
574</p>
575<pre>background.html
576===============
577chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
578  // JSON.parse does not evaluate the attacker's scripts.
579  var resp = JSON.parse(response.farewell);
580});
581
582background.html
583===============
584chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
585  // innerText does not let the attacker inject HTML elements.
586  document.getElementById("resp").innerText = response.farewell;
587});
588</pre>
589
590<h2 id="examples">Examples</h2>
591
592<p>
593You can find simple examples of communication via messages in the
594<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/">examples/api/messaging</a>
595directory.
596Also see the
597<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr">contentscript_xhr</a> example,
598in which a content script and its parent extension exchange messages,
599so that the parent extension can perform
600cross-site requests on behalf of the content script.
601For more examples and for help in viewing the source code, see
602<a href="samples.html">Samples</a>.
603</p>
604</div>
605
606        <!-- API PAGE -->
607        <div class="apiPage" style="display: none; ">
608        <a name="apiReference"></a>
609        <h2>API reference: chrome.apiname </h2>
610
611          <!-- PROPERTIES -->
612          <div class="apiGroup">
613            <a name="properties"></a>
614            <h3 id="properties">Properties</h3>
615
616            <div>
617              <a></a>
618              <h4>getLastError</h4>
619              <div class="summary">
620                <!-- Note: intentionally longer 80 columns -->
621                <span>chrome.extension</span><span>lastError</span>
622              </div>
623              <div>
624              </div>
625            </div>
626
627          </div> <!-- /apiGroup -->
628
629          <!-- METHODS -->
630          <div class="apiGroup" id="methods">
631            <a name="methods"></a>
632            <h3>Methods</h3>
633
634            <!-- iterates over all functions -->
635            <div class="apiItem">
636              <a></a> <!-- method-anchor -->
637              <h4>method name</h4>
638
639              <div class="summary"><span>void</span>
640                  <!-- Note: intentionally longer 80 columns -->
641                  <span>chrome.module.methodName</span>(<span><span>, </span><span></span>
642                      <var><span></span></var></span>)</div>
643
644              <div class="description">
645                <p class="todo">Undocumented.</p>
646                <p>
647                  A description from the json schema def of the function goes here.
648                </p>
649
650                <!-- PARAMETERS -->
651                <h4>Parameters</h4>
652                <dl>
653                  <div>
654                    <div>
655                    </div>
656                  </div>
657                </dl>
658
659                <!-- RETURNS -->
660                <h4>Returns</h4>
661                <dl>
662                  <div>
663                    <div>
664                    </div>
665                  </div>
666                </dl>
667
668                <!-- CALLBACK -->
669                <div>
670                  <div>
671                  <h4>Callback function</h4>
672                  <p>
673                    The callback <em>parameter</em> should specify a function
674                    that looks like this:
675                  </p>
676                  <p>
677                    If you specify the <em>callback</em> parameter, it should
678                    specify a function that looks like this:
679                  </p>
680
681                  <!-- Note: intentionally longer 80 columns -->
682                  <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>;</pre>
683                  <dl>
684                    <div>
685                      <div>
686                      </div>
687                    </div>
688                  </dl>
689                  </div>
690                </div>
691
692                <!-- MIN_VERSION -->
693                <p>
694                  This function was added in version <b><span></span></b>.
695                  If you require this function, the manifest key
696                  <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
697                  can ensure that your extension won't be run in an earlier browser version.
698                </p>
699              </div> <!-- /description -->
700
701            </div>  <!-- /apiItem -->
702
703          </div>  <!-- /apiGroup -->
704
705          <!-- EVENTS -->
706          <div class="apiGroup">
707            <a name="events"></a>
708            <h3 id="events">Events</h3>
709
710            <!-- iterates over all events -->
711            <div class="apiItem">
712              <a></a>
713              <h4>event name</h4>
714
715              <div class="summary">
716                <!-- Note: intentionally longer 80 columns -->
717                <span class="subdued">chrome.bookmarks</span><span>onEvent</span><span class="subdued">.addListener</span>(function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);
718              </div>
719
720              <div class="description">
721                <p class="todo">Undocumented.</p>
722                <p>
723                  A description from the json schema def of the event goes here.
724                </p>
725
726                <!-- PARAMETERS -->
727                <h4>Parameters</h4>
728                <dl>
729                  <div>
730                    <div>
731                    </div>
732                  </div>
733                </dl>
734
735              </div> <!-- /decription -->
736
737            </div> <!-- /apiItem -->
738
739          </div> <!-- /apiGroup -->
740
741          <!-- TYPES -->
742          <div class="apiGroup">
743            <a name="types"></a>
744            <h3 id="types">Types</h3>
745
746            <!-- iterates over all types -->
747            <div class="apiItem">
748              <a></a>
749              <h4>type name</h4>
750
751              <div>
752              </div>
753
754            </div> <!-- /apiItem -->
755
756          </div> <!-- /apiGroup -->
757
758        </div> <!-- /apiPage -->
759      </div> <!-- /gc-pagecontent -->
760    </div> <!-- /g-section -->
761  </div> <!-- /codesiteContent -->
762    <div id="gc-footer" --="">
763      <div class="text">
764  <p>
765  Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
766  the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
767  Attribution 3.0 License</a>, and code samples are licensed under the
768  <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
769  </p>
770  <p>
771  ©2010 Google
772  </p>
773
774<!-- begin analytics -->
775<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
776<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
777
778<script type="text/javascript">
779  // chrome doc tracking
780  try {
781    var engdocs = _gat._getTracker("YT-10763712-2");
782    engdocs._trackPageview();
783  } catch(err) {}
784
785  // code.google.com site-wide tracking
786  try {
787    _uacct="UA-18071-1";
788    _uanchor=1;
789    _uff=0;
790    urchinTracker();
791  }
792  catch(e) {/* urchinTracker not available. */}
793</script>
794<!-- end analytics -->
795      </div>
796    </div> <!-- /gc-footer -->
797  </div> <!-- /gc-container -->
798</body></html>
799