Index: native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/message-system.html |
diff --git a/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/message-system.html b/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/message-system.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c28cef4a0a7891fe5d2e4c54b41d2a208d481275 |
--- /dev/null |
+++ b/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/message-system.html |
@@ -0,0 +1,376 @@ |
+{{+bindTo:partials.standard_nacl_article}} |
+ |
+<section id="messaging-system"> |
+<span id="message-system"></span><h1 id="messaging-system"><span id="message-system"></span>Messaging System</h1> |
+<div class="contents local topic" id="contents"> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#reference-information" id="id2">Reference information</a></li> |
+<li><p class="first"><a class="reference internal" href="#introduction-to-the-messaging-system" id="id3">Introduction to the messaging system</a></p> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#design-of-the-messaging-system" id="id4">Design of the messaging system</a></li> |
+</ul> |
+</li> |
+<li><p class="first"><a class="reference internal" href="#communication-tasks-in-the-hello-world-example" id="id5">Communication tasks in the “Hello, World” example</a></p> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#javascript-code" id="id6">JavaScript code</a></li> |
+<li><a class="reference internal" href="#native-client-module" id="id7">Native Client module</a></li> |
+</ul> |
+</li> |
+<li><p class="first"><a class="reference internal" href="#messaging-in-javascript-code-more-details" id="id8">Messaging in JavaScript code: More details.</a></p> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#setting-up-an-event-listener-and-handler" id="id9">Setting up an event listener and handler</a></li> |
+</ul> |
+</li> |
+<li><p class="first"><a class="reference internal" href="#messaging-in-the-native-client-module-more-details" id="id10">Messaging in the Native Client module: More details.</a></p> |
+<ul class="small-gap"> |
+<li><a class="reference internal" href="#implementing-handlemessage" id="id11">Implementing HandleMessage()</a></li> |
+<li><a class="reference internal" href="#implementing-application-specific-functions" id="id12">Implementing application-specific functions</a></li> |
+<li><a class="reference internal" href="#sending-messages-back-to-the-javascript-code" id="id13">Sending messages back to the JavaScript code</a></li> |
+<li><a class="reference internal" href="#sending-and-receiving-other-pp-var-types" id="id14">Sending and receiving other <code>pp::Var</code> types</a></li> |
+</ul> |
+</li> |
+</ul> |
+</div> |
+<p>This chapter describes the messaging system used to communicate between the |
+JavaScript code and the Native Client module’s C or C++ code in a |
+Native Client application. It introduces the concept of asynchronous |
+programming and the basic steps required to set up a Native Client module |
+that sends messages to and receive messages from JavaScript. This chapter |
+assumes you are familiar with the material presented in the |
+<a class="reference internal" href="/native-client/devguide/coding/application-structure.html"><em>Application Structure</em></a> chapter.</p> |
+<aside class="note"> |
+The “Hello, World” example for getting started with NaCl is used here to |
+illustrate basic programming techniques. You can find this code in |
+the <code>/getting_started/part2</code> directory in the Native Client SDK download. |
+</aside> |
+<section id="reference-information"> |
+<h2 id="reference-information">Reference information</h2> |
+<p>For reference information related to the Pepper messaging API, see the |
+following documentation:</p> |
+<ul class="small-gap"> |
+<li><a class="reference external" href="https://developers.google.com/native-client/peppercpp/classpp_1_1_instance">pp::Instance class</a> HandleMessage(), PostMessage())</li> |
+<li><a class="reference external" href="https://developers.google.com/native-client/peppercpp/classpp_1_1_module">pp::Module class</a></li> |
+<li><a class="reference external" href="https://developers.google.com/native-client/peppercpp/classpp_1_1_var">pp::Var class</a></li> |
+</ul> |
+</section><section id="introduction-to-the-messaging-system"> |
+<h2 id="introduction-to-the-messaging-system">Introduction to the messaging system</h2> |
+<p>Native Client modules and JavaScript communicate by sending messages |
+to each other. The most basic form of a message is a string. Messages |
+support many JavaScript types, including ints, arrays, array buffers, |
+and dictionaries (see <a class="reference external" href="https://developers.google.com/native-client/peppercpp/classpp_1_1_var">pp::Var</a>, |
+<a class="reference external" href="https://developers.google.com/native-client/peppercpp/classpp_1_1_var_array_buffer">pp:VarArrayBuffer</a>, |
+and the general <a class="reference external" href="https://developers.google.com/native-client/pepperc/struct_p_p_b___messaging__1__0">messaging system documentation</a>). |
+It’s up to you to decide on the type of message and define how to |
+process the messages on both the JavaScript and Native Client |
+side. For the “Hello, World” example, we will work with string-typed |
+messages only.</p> |
+<p>When JavaScript posts a message to the Native Client module, the |
+Pepper <code>HandleMessage()</code> function is invoked on the module |
+side. Similarly, the Native Client module can post a message to |
+JavaScript, and this message triggers a JavaScript event listener for |
+<code>message</code> events in the DOM. (See the W3C specification on |
+<a class="reference external" href="http://www.w3.org/TR/DOM-Level-2-Events/events.html">Document Object Model Events</a> for more |
+information.) In the “Hello, World” example, the JavaScript functions for |
+posting and handling messages are named <code>postMessage()</code> and |
+<code>handleMessage()</code> (but any names could be used). On the Native Client |
+C++ side, the Pepper Library functions for posting and handling |
+messages are:</p> |
+<ul class="small-gap"> |
+<li><code>void pp::Instance::PostMessage(const Var &message)</code></li> |
+<li><code>virtual void pp::Instance::HandleMessage(const Var &message)</code></li> |
+</ul> |
+<p>If you want to receive messages from JavaScript, you need to implement the |
+<code>pp::Instance::HandleMessage()</code> function in your Native Client module.</p> |
+<section id="design-of-the-messaging-system"> |
+<h3 id="design-of-the-messaging-system">Design of the messaging system</h3> |
+<p>The Native Client messaging system is analogous to the system used by |
+the browser to allow web workers to communicate (see the <a class="reference external" href="http://www.w3.org/TR/workers">W3 web |
+worker specification</a>). The Native |
+Client messaging system is designed to keep the web page responsive while the |
+Native Client module is performing potentially heavy processing in the |
+background. When JavaScript sends a message to the Native Client |
+module, the <code>postMessage()</code> call returns as soon as it sends its message |
+to the Native Client module. The JavaScript does not wait for a reply |
+from Native Client, thus avoiding bogging down the main JavaScript |
+thread. On the JavaScript side, you set up an event listener to |
+respond to the message sent by the Native Client module when it has |
+finished the requested processing and returns a message.</p> |
+<p>This asynchronous processing model keeps the main thread free while |
+avoiding the following problems:</p> |
+<ul class="small-gap"> |
+<li>The JavaScript engine hangs while waiting for a synchronous call to return.</li> |
+<li>The browser pops up a dialog when a JavaScript entry point takes longer |
+than a few moments.</li> |
+<li>The application hangs while waiting for an unresponsive Native Client module.</li> |
+</ul> |
+</section></section><section id="communication-tasks-in-the-hello-world-example"> |
+<h2 id="communication-tasks-in-the-hello-world-example">Communication tasks in the “Hello, World” example</h2> |
+<p>The following sections describe how the “Hello, World” example posts |
+and handles messages on both the JavaScript side and the Native Client |
+side of the application.</p> |
+<section id="javascript-code"> |
+<h3 id="javascript-code">JavaScript code</h3> |
+<p>The JavaScript code and HTML in the “Hello, World” example can be |
+found in the <code>example.js</code>, <code>common.js</code>, and <code>index.html</code> files. |
+The important steps are:</p> |
+<ol class="arabic simple"> |
+<li>Sets up an event listener to listen for <code>message</code> events from the |
+Native Client module.</li> |
+<li>Implements an event handler that the event listener invokes to handle |
+incoming <code>message</code> events.</li> |
+<li>Calls <code>postMessage()</code> to communicate with the NaCl module, |
+after the page loads.</li> |
+</ol> |
+<section id="step-1-from-common-js"> |
+<h4 id="step-1-from-common-js">Step 1: From common.js</h4> |
+<pre class="prettyprint"> |
+function attachDefaultListeners() { |
+ // The NaCl module embed is created within the listenerDiv |
+ var listenerDiv = document.getElementById('listener'); |
+ // ... |
+ |
+ // register the handleMessage function as the message event handler. |
+ listenerDiv.addEventListener('message', handleMessage, true); |
+ // ... |
+} |
+</pre> |
+</section><section id="step-2-from-example-js"> |
+<h4 id="step-2-from-example-js">Step 2: From example.js</h4> |
+<pre class="prettyprint"> |
+// This function is called by common.js when a message is received from the |
+// NaCl module. |
+function handleMessage(message) { |
+ // In the example, we simply log the data that's received in the message. |
+ var logEl = document.getElementById('log'); |
+ logEl.textContent += message.data; |
+} |
+ |
+// In the index.html we have set up the appropriate divs: |
+<body {attrs}> |
+ <!-- ... --> |
+ <div id="listener"></div> |
+ <div id="log"></div> |
+</body> |
+</pre> |
+</section><section id="step-3-from-example-js"> |
+<h4 id="step-3-from-example-js">Step 3: From example.js</h4> |
+<pre class="prettyprint"> |
+// From example.js, Step 3: |
+function moduleDidLoad() { |
+ // After the NaCl module has loaded, common.naclModule is a reference to the |
+ // NaCl module's <embed> element. |
+ // |
+ // postMessage sends a message to it. |
+ common.naclModule.postMessage('hello'); |
+} |
+</pre> |
+</section></section><section id="native-client-module"> |
+<h3 id="native-client-module">Native Client module</h3> |
+<p>The C++ code in the Native Client module of the “Hello, World” example:</p> |
+<ol class="arabic simple"> |
+<li>Implements <code>pp::Instance::HandleMessage()</code> to handle messages sent |
+by the JavaScript.</li> |
+<li>Processes incoming messages. This example simply checks that JavaScript |
+has sent a “hello” message and not some other message.</li> |
+<li>Calls <code>PostMessage()</code> to send an acknowledgement back to the |
+JavaScript code. The acknowledgement is a string in the form of a <code>Var</code> |
+that the JavaScript code can process. In general, a <code>pp::Var</code> can be |
+several JavaScript types, see the |
+<a class="reference external" href="https://developers.google.com/native-client/pepperc/struct_p_p_b___messaging__1__0">messaging system documentation</a>.</li> |
+</ol> |
+<pre class="prettyprint"> |
+class HelloTutorialInstance : public pp::Instance { |
+ public: |
+ // ... |
+ |
+ // === Step 1: Implement the HandleMessage function. === |
+ virtual void HandleMessage(const pp::Var& var_message) { |
+ |
+ // === Step 2: Process the incoming message. === |
+ // Ignore the message if it is not a string. |
+ if (!var_message.is_string()) |
+ return; |
+ |
+ // Get the string message and compare it to "hello". |
+ std::string message = var_message.AsString(); |
+ if (message == kHelloString) { |
+ // === Step 3: Send the reply. === |
+ // If it matches, send our response back to JavaScript. |
+ pp::Var var_reply(kReplyString); |
+ PostMessage(var_reply); |
+ } |
+ } |
+}; |
+</pre> |
+</section></section><section id="messaging-in-javascript-code-more-details"> |
+<h2 id="messaging-in-javascript-code-more-details">Messaging in JavaScript code: More details.</h2> |
+<p>This section describes in more detail the messaging system code in the |
+JavaScript portion of the “Hello, World” example.</p> |
+<section id="setting-up-an-event-listener-and-handler"> |
+<h3 id="setting-up-an-event-listener-and-handler">Setting up an event listener and handler</h3> |
+<p>The following JavaScript code sets up an event listener for messages |
+posted by the Native Client module. It then defines a message handler |
+that simply logs the content of messages received from the module.</p> |
+<section id="setting-up-the-message-handler-on-load"> |
+<h4 id="setting-up-the-message-handler-on-load">Setting up the ‘message’ handler on load</h4> |
+<pre class="prettyprint"> |
+// From common.js |
+ |
+// Listen for the DOM content to be loaded. This event is fired when |
+// parsing of the page's document has finished. |
+document.addEventListener('DOMContentLoaded', function() { |
+ var body = document.body; |
+ // ... |
+ var loadFunction = common.domContentLoaded; |
+ // ... set up parameters ... |
+ loadFunction(...); |
+} |
+ |
+// This function is exported as common.domContentLoaded. |
+function domContentLoaded(...) { |
+ // ... |
+ if (common.naclModule == null) { |
+ // ... |
+ attachDefaultListeners(); |
+ // initialize common.naclModule ... |
+ } else { |
+ // ... |
+ } |
+} |
+ |
+function attachDefaultListeners() { |
+ var listenerDiv = document.getElementById('listener'); |
+ // ... |
+ listenerDiv.addEventListener('message', handleMessage, true); |
+ // ... |
+} |
+</pre> |
+</section><section id="implementing-the-handler"> |
+<h4 id="implementing-the-handler">Implementing the handler</h4> |
+<pre class="prettyprint"> |
+// From example.js |
+function handleMessage(message) { |
+ var logEl = document.getElementById('log'); |
+ logEl.textContent += message.data; |
+} |
+</pre> |
+<p>Note that the <code>handleMessage()</code> function is handed a message_event |
+containing <code>data</code> that you can display or manipulate in JavaScript. The |
+“Hello, World” application simply logs this data to the <code>log</code> div.</p> |
+</section></section></section><section id="messaging-in-the-native-client-module-more-details"> |
+<h2 id="messaging-in-the-native-client-module-more-details">Messaging in the Native Client module: More details.</h2> |
+<p>This section describes in more detail the messaging system code in |
+the Native Client module portion of the “Hello, World” example.</p> |
+<section id="implementing-handlemessage"> |
+<h3 id="implementing-handlemessage">Implementing HandleMessage()</h3> |
+<p>If you want the Native Client module to receive and handle messages |
+from JavaScript, you need to implement a <code>HandleMessage()</code> function |
+for your module’s <code>pp::Instance</code> class. The |
+<code>HelloWorldInstance::HandleMessage()</code> function examines the message |
+posted from JavaScript. First it examines that the type of the |
+<code>pp::Var</code> is indeed a string (not a double, etc.). It then |
+interprets the data as a string with <code>var_message.AsString()</code>, and |
+checks that the string matches <code>kHelloString</code>. After examining the |
+message received from JavaScript, the code calls <code>PostMessage()</code> to |
+send a reply message back to the JavaScript side.</p> |
+<pre class="prettyprint"> |
+namespace { |
+ |
+// The expected string sent by the JavaScript. |
+const char* const kHelloString = "hello"; |
+// The string sent back to the JavaScript code upon receipt of a message |
+// containing "hello". |
+const char* const kReplyString = "hello from NaCl"; |
+ |
+} // namespace |
+ |
+class HelloTutorialInstance : public pp::Instance { |
+ public: |
+ // ... |
+ virtual void HandleMessage(const pp::Var& var_message) { |
+ // Ignore the message if it is not a string. |
+ if (!var_message.is_string()) |
+ return; |
+ |
+ // Get the string message and compare it to "hello". |
+ std::string message = var_message.AsString(); |
+ if (message == kHelloString) { |
+ // If it matches, send our response back to JavaScript. |
+ pp::Var var_reply(kReplyString); |
+ PostMessage(var_reply); |
+ } |
+ } |
+}; |
+</pre> |
+</section><section id="implementing-application-specific-functions"> |
+<h3 id="implementing-application-specific-functions">Implementing application-specific functions</h3> |
+<p>While the “Hello, World” example is very simple, your Native Client |
+module will likely include application-specific functions to perform |
+custom tasks in response to messages. For example the application |
+could be a compression and decompression service (two functions |
+exported). The application could set up an application-specific |
+convention that messages coming from JavaScript are colon-separated |
+pairs of the form <code><command>:<data></code>. The Native Client module |
+message handler can then split the incoming string along the <code>:</code> |
+character to determine which command to execute. If the command is |
+“compress”, then data to process is an uncompressed string. If the |
+command is “uncompress”, then data to process is an already-compressed |
+string. After processing the data asynchronously, the application then |
+returns the result to JavaScript.</p> |
+</section><section id="sending-messages-back-to-the-javascript-code"> |
+<h3 id="sending-messages-back-to-the-javascript-code">Sending messages back to the JavaScript code</h3> |
+<p>The Native Client module sends messages back to the JavaScript code |
+using <code>PostMessage()</code>. The Native Client module always returns |
+its values in the form of a <code>pp::Var</code> that can be processed by the |
+browser’s JavaScript. In this example, the message is posted at the |
+end of the Native Client module’s <code>HandleMessage()</code> function:</p> |
+<pre class="prettyprint"> |
+PostMessage(var_reply); |
+</pre> |
+</section><section id="sending-and-receiving-other-pp-var-types"> |
+<h3 id="sending-and-receiving-other-pp-var-types">Sending and receiving other <code>pp::Var</code> types</h3> |
+<p>Besides strings, <code>pp::Var</code> can represent other types of JavaScript |
+objects. For example, messages can be JavaScript objects. These |
+richer types can make it easier to implement an application’s |
+messaging protocol.</p> |
+<p>To send a dictionary from the NaCl module to JavaScript simply create |
+a <code>pp::VarDictionary</code> and then call <code>PostMessage</code> with the |
+dictionary.</p> |
+<pre class="prettyprint"> |
+pp::VarDictionary dictionary; |
+dictionary.Set(pp::Var("command"), pp::Var(next_command)); |
+dictionary.Set(pp::Var("param_int"), pp::Var(123)); |
+pp::VarArray an_array; |
+an_array.Set(0, pp::Var("string0")); |
+an_array.Set(1, pp::Var("string1")) |
+dictionary.Set(pp::Var("param_array"), an_array); |
+PostMessage(dictionary); |
+</pre> |
+<p>Here is how to create a similar object in JavaScript and send it to |
+the NaCl module:</p> |
+<pre class="prettyprint"> |
+var dictionary = { |
+ command: next_command, |
+ param_int: 123, |
+ param_array: ['string0', 'string1'] |
+} |
+nacl_module.postMessage(dictionary); |
+</pre> |
+<p>To receive a dictionary-typed message in the NaCl module, test that |
+the message is truly a dictionary type, then convert the message |
+with the <code>pp::VarDictionary</code> class.</p> |
+<pre class="prettyprint"> |
+virtual void HandleMessage(const pp::Var& var) { |
+ if (var.is_dictionary()) { |
+ pp::VarDictionary dictionary(var); |
+ // Use the dictionary |
+ pp::VarArray keys = dictionary.GetKeys(); |
+ // ... |
+ } else { |
+ // ... |
+ } |
+} |
+</pre> |
+</section></section></section> |
+ |
+{{/partials.standard_nacl_article}} |