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

Side by Side Diff: native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/message-system.html

Issue 140993006: [NaCl SDK Docs] Check in the generated NaCl SDK Documentation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: try without pepper_{dev,beta,stable} Created 6 years, 11 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 {{+bindTo:partials.standard_nacl_article}}
2
3 <section id="messaging-system">
4 <span id="message-system"></span><h1 id="messaging-system"><span id="message-sys tem"></span>Messaging System</h1>
5 <div class="contents local topic" id="contents">
6 <ul class="small-gap">
7 <li><a class="reference internal" href="#reference-information" id="id2">Referen ce information</a></li>
8 <li><p class="first"><a class="reference internal" href="#introduction-to-the-me ssaging-system" id="id3">Introduction to the messaging system</a></p>
9 <ul class="small-gap">
10 <li><a class="reference internal" href="#design-of-the-messaging-system" id="id4 ">Design of the messaging system</a></li>
11 </ul>
12 </li>
13 <li><p class="first"><a class="reference internal" href="#communication-tasks-in -the-hello-world-example" id="id5">Communication tasks in the &#8220;Hello, Worl d&#8221; example</a></p>
14 <ul class="small-gap">
15 <li><a class="reference internal" href="#javascript-code" id="id6">JavaScript co de</a></li>
16 <li><a class="reference internal" href="#native-client-module" id="id7">Native C lient module</a></li>
17 </ul>
18 </li>
19 <li><p class="first"><a class="reference internal" href="#messaging-in-javascrip t-code-more-details" id="id8">Messaging in JavaScript code: More details.</a></p >
20 <ul class="small-gap">
21 <li><a class="reference internal" href="#setting-up-an-event-listener-and-handle r" id="id9">Setting up an event listener and handler</a></li>
22 </ul>
23 </li>
24 <li><p class="first"><a class="reference internal" href="#messaging-in-the-nativ e-client-module-more-details" id="id10">Messaging in the Native Client module: M ore details.</a></p>
25 <ul class="small-gap">
26 <li><a class="reference internal" href="#implementing-handlemessage" id="id11">I mplementing HandleMessage()</a></li>
27 <li><a class="reference internal" href="#implementing-application-specific-funct ions" id="id12">Implementing application-specific functions</a></li>
28 <li><a class="reference internal" href="#sending-messages-back-to-the-javascript -code" id="id13">Sending messages back to the JavaScript code</a></li>
29 <li><a class="reference internal" href="#sending-and-receiving-other-pp-var-type s" id="id14">Sending and receiving other <code>pp::Var</code> types</a></li>
30 </ul>
31 </li>
32 </ul>
33 </div>
34 <p>This chapter describes the messaging system used to communicate between the
35 JavaScript code and the Native Client module&#8217;s C or C++ code in a
36 Native Client application. It introduces the concept of asynchronous
37 programming and the basic steps required to set up a Native Client module
38 that sends messages to and receive messages from JavaScript. This chapter
39 assumes you are familiar with the material presented in the
40 <a class="reference internal" href="/native-client/devguide/coding/application-s tructure.html"><em>Application Structure</em></a> chapter.</p>
41 <aside class="note">
42 The &#8220;Hello, World&#8221; example for getting started with NaCl is used her e to
43 illustrate basic programming techniques. You can find this code in
44 the <code>/getting_started/part2</code> directory in the Native Client SDK downl oad.
45 </aside>
46 <section id="reference-information">
47 <h2 id="reference-information">Reference information</h2>
48 <p>For reference information related to the Pepper messaging API, see the
49 following documentation:</p>
50 <ul class="small-gap">
51 <li><a class="reference external" href="https://developers.google.com/native-cli ent/peppercpp/classpp_1_1_instance">pp::Instance class</a> HandleMessage(), Post Message())</li>
52 <li><a class="reference external" href="https://developers.google.com/native-cli ent/peppercpp/classpp_1_1_module">pp::Module class</a></li>
53 <li><a class="reference external" href="https://developers.google.com/native-cli ent/peppercpp/classpp_1_1_var">pp::Var class</a></li>
54 </ul>
55 </section><section id="introduction-to-the-messaging-system">
56 <h2 id="introduction-to-the-messaging-system">Introduction to the messaging syst em</h2>
57 <p>Native Client modules and JavaScript communicate by sending messages
58 to each other. The most basic form of a message is a string. Messages
59 support many JavaScript types, including ints, arrays, array buffers,
60 and dictionaries (see <a class="reference external" href="https://developers.goo gle.com/native-client/peppercpp/classpp_1_1_var">pp::Var</a>,
61 <a class="reference external" href="https://developers.google.com/native-client/ peppercpp/classpp_1_1_var_array_buffer">pp:VarArrayBuffer</a>,
62 and the general <a class="reference external" href="https://developers.google.co m/native-client/pepperc/struct_p_p_b___messaging__1__0">messaging system documen tation</a>).
63 It&#8217;s up to you to decide on the type of message and define how to
64 process the messages on both the JavaScript and Native Client
65 side. For the &#8220;Hello, World&#8221; example, we will work with string-typed
66 messages only.</p>
67 <p>When JavaScript posts a message to the Native Client module, the
68 Pepper <code>HandleMessage()</code> function is invoked on the module
69 side. Similarly, the Native Client module can post a message to
70 JavaScript, and this message triggers a JavaScript event listener for
71 <code>message</code> events in the DOM. (See the W3C specification on
72 <a class="reference external" href="http://www.w3.org/TR/DOM-Level-2-Events/even ts.html">Document Object Model Events</a> for more
73 information.) In the &#8220;Hello, World&#8221; example, the JavaScript function s for
74 posting and handling messages are named <code>postMessage()</code> and
75 <code>handleMessage()</code> (but any names could be used). On the Native Client
76 C++ side, the Pepper Library functions for posting and handling
77 messages are:</p>
78 <ul class="small-gap">
79 <li><code>void pp::Instance::PostMessage(const Var &amp;message)</code></li>
80 <li><code>virtual void pp::Instance::HandleMessage(const Var &amp;message)</code ></li>
81 </ul>
82 <p>If you want to receive messages from JavaScript, you need to implement the
83 <code>pp::Instance::HandleMessage()</code> function in your Native Client module .</p>
84 <section id="design-of-the-messaging-system">
85 <h3 id="design-of-the-messaging-system">Design of the messaging system</h3>
86 <p>The Native Client messaging system is analogous to the system used by
87 the browser to allow web workers to communicate (see the <a class="reference ext ernal" href="http://www.w3.org/TR/workers">W3 web
88 worker specification</a>). The Native
89 Client messaging system is designed to keep the web page responsive while the
90 Native Client module is performing potentially heavy processing in the
91 background. When JavaScript sends a message to the Native Client
92 module, the <code>postMessage()</code> call returns as soon as it sends its mess age
93 to the Native Client module. The JavaScript does not wait for a reply
94 from Native Client, thus avoiding bogging down the main JavaScript
95 thread. On the JavaScript side, you set up an event listener to
96 respond to the message sent by the Native Client module when it has
97 finished the requested processing and returns a message.</p>
98 <p>This asynchronous processing model keeps the main thread free while
99 avoiding the following problems:</p>
100 <ul class="small-gap">
101 <li>The JavaScript engine hangs while waiting for a synchronous call to return.< /li>
102 <li>The browser pops up a dialog when a JavaScript entry point takes longer
103 than a few moments.</li>
104 <li>The application hangs while waiting for an unresponsive Native Client module .</li>
105 </ul>
106 </section></section><section id="communication-tasks-in-the-hello-world-example" >
107 <h2 id="communication-tasks-in-the-hello-world-example">Communication tasks in t he &#8220;Hello, World&#8221; example</h2>
108 <p>The following sections describe how the &#8220;Hello, World&#8221; example po sts
109 and handles messages on both the JavaScript side and the Native Client
110 side of the application.</p>
111 <section id="javascript-code">
112 <h3 id="javascript-code">JavaScript code</h3>
113 <p>The JavaScript code and HTML in the &#8220;Hello, World&#8221; example can be
114 found in the <code>example.js</code>, <code>common.js</code>, and <code>index.ht ml</code> files.
115 The important steps are:</p>
116 <ol class="arabic simple">
117 <li>Sets up an event listener to listen for <code>message</code> events from the
118 Native Client module.</li>
119 <li>Implements an event handler that the event listener invokes to handle
120 incoming <code>message</code> events.</li>
121 <li>Calls <code>postMessage()</code> to communicate with the NaCl module,
122 after the page loads.</li>
123 </ol>
124 <section id="step-1-from-common-js">
125 <h4 id="step-1-from-common-js">Step 1: From common.js</h4>
126 <pre class="prettyprint">
127 function attachDefaultListeners() {
128 // The NaCl module embed is created within the listenerDiv
129 var listenerDiv = document.getElementById('listener');
130 // ...
131
132 // register the handleMessage function as the message event handler.
133 listenerDiv.addEventListener('message', handleMessage, true);
134 // ...
135 }
136 </pre>
137 </section><section id="step-2-from-example-js">
138 <h4 id="step-2-from-example-js">Step 2: From example.js</h4>
139 <pre class="prettyprint">
140 // This function is called by common.js when a message is received from the
141 // NaCl module.
142 function handleMessage(message) {
143 // In the example, we simply log the data that's received in the message.
144 var logEl = document.getElementById('log');
145 logEl.textContent += message.data;
146 }
147
148 // In the index.html we have set up the appropriate divs:
149 &lt;body {attrs}&gt;
150 &lt;!-- ... --&gt;
151 &lt;div id=&quot;listener&quot;&gt;&lt;/div&gt;
152 &lt;div id=&quot;log&quot;&gt;&lt;/div&gt;
153 &lt;/body&gt;
154 </pre>
155 </section><section id="step-3-from-example-js">
156 <h4 id="step-3-from-example-js">Step 3: From example.js</h4>
157 <pre class="prettyprint">
158 // From example.js, Step 3:
159 function moduleDidLoad() {
160 // After the NaCl module has loaded, common.naclModule is a reference to the
161 // NaCl module's &lt;embed&gt; element.
162 //
163 // postMessage sends a message to it.
164 common.naclModule.postMessage('hello');
165 }
166 </pre>
167 </section></section><section id="native-client-module">
168 <h3 id="native-client-module">Native Client module</h3>
169 <p>The C++ code in the Native Client module of the &#8220;Hello, World&#8221; ex ample:</p>
170 <ol class="arabic simple">
171 <li>Implements <code>pp::Instance::HandleMessage()</code> to handle messages sen t
172 by the JavaScript.</li>
173 <li>Processes incoming messages. This example simply checks that JavaScript
174 has sent a &#8220;hello&#8221; message and not some other message.</li>
175 <li>Calls <code>PostMessage()</code> to send an acknowledgement back to the
176 JavaScript code. The acknowledgement is a string in the form of a <code>Var</co de>
177 that the JavaScript code can process. In general, a <code>pp::Var</code> can be
178 several JavaScript types, see the
179 <a class="reference external" href="https://developers.google.com/native-client/ pepperc/struct_p_p_b___messaging__1__0">messaging system documentation</a>.</li>
180 </ol>
181 <pre class="prettyprint">
182 class HelloTutorialInstance : public pp::Instance {
183 public:
184 // ...
185
186 // === Step 1: Implement the HandleMessage function. ===
187 virtual void HandleMessage(const pp::Var&amp; var_message) {
188
189 // === Step 2: Process the incoming message. ===
190 // Ignore the message if it is not a string.
191 if (!var_message.is_string())
192 return;
193
194 // Get the string message and compare it to &quot;hello&quot;.
195 std::string message = var_message.AsString();
196 if (message == kHelloString) {
197 // === Step 3: Send the reply. ===
198 // If it matches, send our response back to JavaScript.
199 pp::Var var_reply(kReplyString);
200 PostMessage(var_reply);
201 }
202 }
203 };
204 </pre>
205 </section></section><section id="messaging-in-javascript-code-more-details">
206 <h2 id="messaging-in-javascript-code-more-details">Messaging in JavaScript code: More details.</h2>
207 <p>This section describes in more detail the messaging system code in the
208 JavaScript portion of the &#8220;Hello, World&#8221; example.</p>
209 <section id="setting-up-an-event-listener-and-handler">
210 <h3 id="setting-up-an-event-listener-and-handler">Setting up an event listener a nd handler</h3>
211 <p>The following JavaScript code sets up an event listener for messages
212 posted by the Native Client module. It then defines a message handler
213 that simply logs the content of messages received from the module.</p>
214 <section id="setting-up-the-message-handler-on-load">
215 <h4 id="setting-up-the-message-handler-on-load">Setting up the &#8216;message&#8 217; handler on load</h4>
216 <pre class="prettyprint">
217 // From common.js
218
219 // Listen for the DOM content to be loaded. This event is fired when
220 // parsing of the page's document has finished.
221 document.addEventListener('DOMContentLoaded', function() {
222 var body = document.body;
223 // ...
224 var loadFunction = common.domContentLoaded;
225 // ... set up parameters ...
226 loadFunction(...);
227 }
228
229 // This function is exported as common.domContentLoaded.
230 function domContentLoaded(...) {
231 // ...
232 if (common.naclModule == null) {
233 // ...
234 attachDefaultListeners();
235 // initialize common.naclModule ...
236 } else {
237 // ...
238 }
239 }
240
241 function attachDefaultListeners() {
242 var listenerDiv = document.getElementById('listener');
243 // ...
244 listenerDiv.addEventListener('message', handleMessage, true);
245 // ...
246 }
247 </pre>
248 </section><section id="implementing-the-handler">
249 <h4 id="implementing-the-handler">Implementing the handler</h4>
250 <pre class="prettyprint">
251 // From example.js
252 function handleMessage(message) {
253 var logEl = document.getElementById('log');
254 logEl.textContent += message.data;
255 }
256 </pre>
257 <p>Note that the <code>handleMessage()</code> function is handed a message_event
258 containing <code>data</code> that you can display or manipulate in JavaScript. T he
259 &#8220;Hello, World&#8221; application simply logs this data to the <code>log</c ode> div.</p>
260 </section></section></section><section id="messaging-in-the-native-client-module -more-details">
261 <h2 id="messaging-in-the-native-client-module-more-details">Messaging in the Nat ive Client module: More details.</h2>
262 <p>This section describes in more detail the messaging system code in
263 the Native Client module portion of the &#8220;Hello, World&#8221; example.</p>
264 <section id="implementing-handlemessage">
265 <h3 id="implementing-handlemessage">Implementing HandleMessage()</h3>
266 <p>If you want the Native Client module to receive and handle messages
267 from JavaScript, you need to implement a <code>HandleMessage()</code> function
268 for your module&#8217;s <code>pp::Instance</code> class. The
269 <code>HelloWorldInstance::HandleMessage()</code> function examines the message
270 posted from JavaScript. First it examines that the type of the
271 <code>pp::Var</code> is indeed a string (not a double, etc.). It then
272 interprets the data as a string with <code>var_message.AsString()</code>, and
273 checks that the string matches <code>kHelloString</code>. After examining the
274 message received from JavaScript, the code calls <code>PostMessage()</code> to
275 send a reply message back to the JavaScript side.</p>
276 <pre class="prettyprint">
277 namespace {
278
279 // The expected string sent by the JavaScript.
280 const char* const kHelloString = &quot;hello&quot;;
281 // The string sent back to the JavaScript code upon receipt of a message
282 // containing &quot;hello&quot;.
283 const char* const kReplyString = &quot;hello from NaCl&quot;;
284
285 } // namespace
286
287 class HelloTutorialInstance : public pp::Instance {
288 public:
289 // ...
290 virtual void HandleMessage(const pp::Var&amp; var_message) {
291 // Ignore the message if it is not a string.
292 if (!var_message.is_string())
293 return;
294
295 // Get the string message and compare it to &quot;hello&quot;.
296 std::string message = var_message.AsString();
297 if (message == kHelloString) {
298 // If it matches, send our response back to JavaScript.
299 pp::Var var_reply(kReplyString);
300 PostMessage(var_reply);
301 }
302 }
303 };
304 </pre>
305 </section><section id="implementing-application-specific-functions">
306 <h3 id="implementing-application-specific-functions">Implementing application-sp ecific functions</h3>
307 <p>While the &#8220;Hello, World&#8221; example is very simple, your Native Clie nt
308 module will likely include application-specific functions to perform
309 custom tasks in response to messages. For example the application
310 could be a compression and decompression service (two functions
311 exported). The application could set up an application-specific
312 convention that messages coming from JavaScript are colon-separated
313 pairs of the form <code>&lt;command&gt;:&lt;data&gt;</code>. The Native Client module
314 message handler can then split the incoming string along the <code>:</code>
315 character to determine which command to execute. If the command is
316 &#8220;compress&#8221;, then data to process is an uncompressed string. If the
317 command is &#8220;uncompress&#8221;, then data to process is an already-compress ed
318 string. After processing the data asynchronously, the application then
319 returns the result to JavaScript.</p>
320 </section><section id="sending-messages-back-to-the-javascript-code">
321 <h3 id="sending-messages-back-to-the-javascript-code">Sending messages back to t he JavaScript code</h3>
322 <p>The Native Client module sends messages back to the JavaScript code
323 using <code>PostMessage()</code>. The Native Client module always returns
324 its values in the form of a <code>pp::Var</code> that can be processed by the
325 browser&#8217;s JavaScript. In this example, the message is posted at the
326 end of the Native Client module&#8217;s <code>HandleMessage()</code> function:</ p>
327 <pre class="prettyprint">
328 PostMessage(var_reply);
329 </pre>
330 </section><section id="sending-and-receiving-other-pp-var-types">
331 <h3 id="sending-and-receiving-other-pp-var-types">Sending and receiving other <c ode>pp::Var</code> types</h3>
332 <p>Besides strings, <code>pp::Var</code> can represent other types of JavaScript
333 objects. For example, messages can be JavaScript objects. These
334 richer types can make it easier to implement an application&#8217;s
335 messaging protocol.</p>
336 <p>To send a dictionary from the NaCl module to JavaScript simply create
337 a <code>pp::VarDictionary</code> and then call <code>PostMessage</code> with the
338 dictionary.</p>
339 <pre class="prettyprint">
340 pp::VarDictionary dictionary;
341 dictionary.Set(pp::Var(&quot;command&quot;), pp::Var(next_command));
342 dictionary.Set(pp::Var(&quot;param_int&quot;), pp::Var(123));
343 pp::VarArray an_array;
344 an_array.Set(0, pp::Var(&quot;string0&quot;));
345 an_array.Set(1, pp::Var(&quot;string1&quot;))
346 dictionary.Set(pp::Var(&quot;param_array&quot;), an_array);
347 PostMessage(dictionary);
348 </pre>
349 <p>Here is how to create a similar object in JavaScript and send it to
350 the NaCl module:</p>
351 <pre class="prettyprint">
352 var dictionary = {
353 command: next_command,
354 param_int: 123,
355 param_array: ['string0', 'string1']
356 }
357 nacl_module.postMessage(dictionary);
358 </pre>
359 <p>To receive a dictionary-typed message in the NaCl module, test that
360 the message is truly a dictionary type, then convert the message
361 with the <code>pp::VarDictionary</code> class.</p>
362 <pre class="prettyprint">
363 virtual void HandleMessage(const pp::Var&amp; var) {
364 if (var.is_dictionary()) {
365 pp::VarDictionary dictionary(var);
366 // Use the dictionary
367 pp::VarArray keys = dictionary.GetKeys();
368 // ...
369 } else {
370 // ...
371 }
372 }
373 </pre>
374 </section></section></section>
375
376 {{/partials.standard_nacl_article}}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698