| 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}}
|
|
|