Home | History | Annotate | Download | only in tutorial
      1 {{+bindTo:partials.standard_nacl_article}}
      2 
      3 <section id="c-tutorial-getting-started-part-2">
      4 <span id="tutorial2"></span><h1 id="c-tutorial-getting-started-part-2"><span id="tutorial2"></span>C++ Tutorial: Getting Started (Part 2)</h1>
      5 <div class="contents local" id="contents" style="display: none">
      6 <ul class="small-gap">
      7 <li><a class="reference internal" href="#overview" id="id1">Overview</a></li>
      8 <li><p class="first"><a class="reference internal" href="#using-the-native-client-sdk-build-system" id="id2">Using the Native Client SDK build system</a></p>
      9 <ul class="small-gap">
     10 <li><a class="reference internal" href="#simplifying-the-makefile" id="id3">Simplifying the Makefile</a></li>
     11 <li><a class="reference internal" href="#choosing-valid-toolchains-and-including-common-mk" id="id4">Choosing valid toolchains, and including common.mk</a></li>
     12 <li><a class="reference internal" href="#configuring-your-project" id="id5">Configuring your project</a></li>
     13 <li><a class="reference internal" href="#build-macros" id="id6">Build macros</a></li>
     14 </ul>
     15 </li>
     16 <li><p class="first"><a class="reference internal" href="#making-index-html-work-for-chrome-apps" id="id7">Making index.html work for Chrome Apps</a></p>
     17 <ul class="small-gap">
     18 <li><a class="reference internal" href="#csp-rules" id="id8">CSP rules</a></li>
     19 <li><a class="reference internal" href="#making-index-html-csp-compliant" id="id9">Making index.html CSP-compliant</a></li>
     20 <li><a class="reference internal" href="#making-index-html-support-different-toolchains-and-configurations" id="id10">Making index.html support different toolchains and configurations</a></li>
     21 </ul>
     22 </li>
     23 <li><p class="first"><a class="reference internal" href="#sharing-common-code-with-common-js" id="id11">Sharing common code with common.js</a></p>
     24 <ul class="small-gap">
     25 <li><a class="reference internal" href="#loading-the-page-and-creating-the-module" id="id12">Loading the page and creating the module</a></li>
     26 </ul>
     27 </li>
     28 <li><a class="reference internal" href="#example-specific-behavior-with-example-js" id="id13">Example-specific behavior with example.js</a></li>
     29 </ul>
     30 
     31 </div><section id="overview">
     32 <h2 id="overview">Overview</h2>
     33 <p>This tutorial shows how to convert the finished PNaCl web application from
     34 <a class="reference internal" href="/native-client/devguide/tutorial/tutorial-part1.html"><em>Part 1</em></a> to use the Native Client SDK build system and
     35 common JavaScript files. It also demonstrates some techniques to make your web
     36 application <a class="reference external" href="/apps/contentSecurityPolicy">Content Security Policy (CSP)-compliant</a>, which is necessary for <a class="reference external" href="/apps/about_apps">Chrome Apps</a>.</p>
     37 <p>Using the Native Client SDK build system makes it easy to build with all of the
     38 SDK toolchains, and switch between the Debug and Release configurations. It
     39 also simplifies the makefiles for your project, as we&#8217;ll see in the next
     40 section. Finally, it adds some useful commands for <a class="reference internal" href="/native-client/sdk/examples.html#id1"><em>running</em></a> and <a class="reference internal" href="/native-client/sdk/examples.html#debugging-the-sdk-examples"><em>debugging</em></a>
     41 your application.</p>
     42 <p>The finished code for this example can be found in the
     43 <code>pepper_$(VERSION)/getting_started/part2</code> directory in the Native Client SDK
     44 download.</p>
     45 </section><section id="using-the-native-client-sdk-build-system">
     46 <h2 id="using-the-native-client-sdk-build-system">Using the Native Client SDK build system</h2>
     47 <p>This section describes how to use the SDK build system. To do so, we&#8217;ll make
     48 changes in the makefile. Because the makefile in part1 and part2 are so
     49 different, it is easier to start from scratch. Here is the contents of the new
     50 makefile. The following sections will describe it in more detail.</p>
     51 <section id="simplifying-the-makefile">
     52 <h3 id="simplifying-the-makefile">Simplifying the Makefile</h3>
     53 <p>The makefile from part1 only supports one toolchain (PNaCl) and one
     54 configuration (Release). It also only supports one source file. It&#8217;s relatively
     55 simple, but if we want to add support for multiple toolchains, configurations,
     56 source files, or build steps, it would grow increasingly complex. The SDK build
     57 system uses a set of variables and macros to make this possible, without
     58 significantly increasing the complexity of the makefile.</p>
     59 <p>Here is the new makefile, supporting three toolchains (PNaCl, Newlib NaCl,
     60 Glibc NaCl) and two configurations (Debug, Release).</p>
     61 <pre class="prettyprint">
     62 VALID_TOOLCHAINS := pnacl newlib glibc
     63 
     64 NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../..)
     65 include $(NACL_SDK_ROOT)/tools/common.mk
     66 
     67 TARGET = part2
     68 LIBS = ppapi_cpp ppapi
     69 
     70 CFLAGS = -Wall
     71 SOURCES = hello_tutorial.cc
     72 
     73 # Build rules generated by macros from common.mk:
     74 
     75 $(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS))))
     76 
     77 # The PNaCl workflow uses both an unstripped and finalized/stripped binary.
     78 # On NaCl, only produce a stripped binary for Release configs (not Debug).
     79 ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG))))
     80 $(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS)))
     81 $(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped))
     82 else
     83 $(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS)))
     84 endif
     85 
     86 $(eval $(call NMF_RULE,$(TARGET),))
     87 </pre>
     88 </section><section id="choosing-valid-toolchains-and-including-common-mk">
     89 <h3 id="choosing-valid-toolchains-and-including-common-mk">Choosing valid toolchains, and including common.mk</h3>
     90 <p>The makefile begins by specifying the toolchains that are valid for this
     91 project. The Native Client SDK build system supports multi-toolchain projects
     92 for its examples and libraries, but generally you will choose one toolchain
     93 when you begin your project and never change it. Please see the
     94 <a class="reference internal" href="/native-client/overview.html#toolchains"><em>Toolchains section of the Native Client overview</em></a> for more
     95 information.</p>
     96 <p>For this example, we support the <code>pnacl</code>, <code>newlib</code> and <code>glibc</code> toolchains.</p>
     97 <pre class="prettyprint">
     98 VALID_TOOLCHAINS := pnacl newlib glibc
     99 </pre>
    100 <p>Next, as a convenience, we specify where to find <code>NACL_SDK_ROOT</code>. Because
    101 this example is located in <code>pepper_$(VERSION)/getting_started/part2</code>, the
    102 root of the SDK is two directories up.</p>
    103 <pre class="prettyprint">
    104 NACL_SDK_ROOT ?= $(abspath $(CURDIR)/../..)
    105 </pre>
    106 <aside class="note">
    107 <blockquote>
    108 <div>In your own projects, you can use the absolute path to your installed SDK
    109 here. You can also override this default by setting the <code>NACL_SDK_ROOT</code>
    110 environment variable. See <a class="reference internal" href="/native-client/devguide/tutorial/tutorial-part1.html#tutorial-step-5"><em>Step 5 of Part 1 of this tutorial</em></a> for more details.</div></blockquote>
    111 
    112 </aside>
    113 <p>Next, we include the file <code>tools/common.mk</code>. This file provides the
    114 functionality for the Native Client SDK build system, including new build rules
    115 to compile and link a project, which we&#8217;ll use below.</p>
    116 <pre class="prettyprint">
    117 include $(NACL_SDK_ROOT)/tools/common.mk
    118 </pre>
    119 </section><section id="configuring-your-project">
    120 <h3 id="configuring-your-project">Configuring your project</h3>
    121 <p>After including <code>tools/common.mk</code>, we configure the project by specifying its
    122 name, the sources and libraries it uses:</p>
    123 <pre class="prettyprint">
    124 TARGET = part2
    125 LIBS = ppapi_cpp ppapi
    126 
    127 CFLAGS = -Wall
    128 SOURCES = hello_tutorial.cc
    129 </pre>
    130 <p>These variable names are not required and not used by the SDK build system;
    131 they are only used in the rules described below. By convention, all SDK
    132 makefiles use the following variables:</p>
    133 <dl class="docutils">
    134 <dt>TARGET</dt>
    135 <dd>The name of the project to build. This variable determines the name of the
    136 library or executable that will be generated. In the above example, we call
    137 the target <code>part2</code>, which will generate an executable called
    138 <code>part2.pexe</code> for PNaCl. For NaCl toolchains, the executable&#8217;s file name
    139 will be given a suffix for its architecture. For example, the ARM executable
    140 is called <code>part2_arm.nexe</code>.</dd>
    141 <dt>LIBS</dt>
    142 <dd>A list of libraries that this executable needs to link against. The library
    143 search path is already set up to only look in the directory for the current
    144 toolchain and architecture. In this example, we link against <code>ppapi_cpp</code>
    145 and <code>ppapi</code>. <code>ppapi_cpp</code> is needed to use the <a class="reference external" href="/native-client/pepper_stable/cpp/">Pepper C++ interface</a>. <code>ppapi</code> is needed for communicating
    146 with the browser.</dd>
    147 <dt>CFLAGS</dt>
    148 <dd>A list of extra flags to pass to the compiler. In this example, we pass
    149 <code>-Wall</code>, which turns on all warnings.</dd>
    150 <dt>LDFLAGS</dt>
    151 <dd>A list of additional flags to pass to the linker. This example does not need
    152 any special linker flags, so this variable is omitted.</dd>
    153 <dt>SOURCES</dt>
    154 <dd>A list of C or C++ sources to compile, separated by spaces. If you have a
    155 long list of sources, it may be easier to read if you put each file on its
    156 own line, and use <code>\</code> as a line-continuation character. Here&#8217;s an example:</dd>
    157 </dl>
    158 <pre class="prettyprint">
    159 SOURCES = foo.cc \
    160           bar.cc \
    161           baz.cc \
    162           quux.cc
    163 </pre>
    164 </section><section id="build-macros">
    165 <h3 id="build-macros">Build macros</h3>
    166 <p>For many projects, the following build macros do not need to be changed; they
    167 will use the variables we&#8217;ve defined above.</p>
    168 <pre class="prettyprint">
    169 $(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS))))
    170 
    171 ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG))))
    172 $(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS)))
    173 $(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped))
    174 else
    175 $(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS)))
    176 endif
    177 
    178 $(eval $(call NMF_RULE,$(TARGET),))
    179 </pre>
    180 <p>The first line defines rules to compile each source in <code>SOURCES</code>, using the
    181 flags in <code>CFLAGS</code>:</p>
    182 <pre class="prettyprint">
    183 $(foreach src,$(SOURCES),$(eval $(call COMPILE_RULE,$(src),$(CFLAGS))))
    184 </pre>
    185 <p>The next six lines define rules to link the object files into one or more
    186 executables. When <code>TOOLCHAIN</code> is <code>pnacl</code>, there is only one executable
    187 generated: in the example above, <code>part2.pexe</code>. When using a NaCl toolchain,
    188 there will be three executables generated, one for each architecture: in the
    189 example above, <code>part2_arm.nexe</code>, <code>part2_x86_32.nexe</code> and
    190 <code>part2_x86_64.nexe</code>.</p>
    191 <p>When <code>CONFIG</code> is <code>Release</code>, each executable is also stripped to remove
    192 debug information and reduce the file size. Otherwise, when the <code>TOOLCHAIN</code>
    193 is <code>pnacl</code>, the workflow involves creating an unstripped binary for debugging
    194 and then finalizing it and stripping it for publishing.</p>
    195 <pre class="prettyprint">
    196 ifneq (,$(or $(findstring pnacl,$(TOOLCHAIN)),$(findstring Release,$(CONFIG))))
    197 $(eval $(call LINK_RULE,$(TARGET)_unstripped,$(SOURCES),$(LIBS),$(DEPS)))
    198 $(eval $(call STRIP_RULE,$(TARGET),$(TARGET)_unstripped))
    199 else
    200 $(eval $(call LINK_RULE,$(TARGET),$(SOURCES),$(LIBS),$(DEPS)))
    201 endif
    202 </pre>
    203 <p>Finally, the NMF rule generates a NaCl manifest file (<code>.nmf</code>) that references
    204 each executable generated in the previous step:</p>
    205 <pre class="prettyprint">
    206 $(eval $(call NMF_RULE,$(TARGET),))
    207 </pre>
    208 </section></section><section id="making-index-html-work-for-chrome-apps">
    209 <h2 id="making-index-html-work-for-chrome-apps">Making index.html work for Chrome Apps</h2>
    210 <p>This section describes the changes necessary to make the HTML and JavaScript in
    211 part1 CSP-compliant. This is required if you want to build a <a class="reference external" href="/apps/about_apps">Chrome App</a>, but is not necessary if you want to use PNaCl on the open
    212 web.</p>
    213 <section id="csp-rules">
    214 <h3 id="csp-rules">CSP rules</h3>
    215 <p><a class="reference external" href="/apps/contentSecurityPolicy#what">Chrome Apps CSP</a> restricts you from doing
    216 the following:</p>
    217 <ul class="small-gap">
    218 <li>You cant use inline scripting in your Chrome App pages. The restriction
    219 bans both <code>&lt;script&gt;</code> blocks and event handlers (<code>&lt;button onclick=&quot;...&quot;&gt;</code>).</li>
    220 <li>You cant reference any external resources in any of your app files (except
    221 for video and audio resources). You cant embed external resources in an
    222 iframe.</li>
    223 <li>You cant use string-to-JavaScript methods like <code>eval()</code> and <code>new
    224 Function()</code>.</li>
    225 </ul>
    226 </section><section id="making-index-html-csp-compliant">
    227 <h3 id="making-index-html-csp-compliant">Making index.html CSP-compliant</h3>
    228 <p>To make our application CSP-compliant, we have to remove inline scripting. As
    229 described above, we can&#8217;t use inline <code>&lt;script&gt;</code> blocks or event handlers. This
    230 is easy to do&#8212;we&#8217;ll just reference some new files from our script tag, and
    231 remove all of our inlined scripts:</p>
    232 <pre class="prettyprint">
    233 &lt;head&gt;
    234   ...
    235   &lt;script type=&quot;text/javascript&quot; src=&quot;common.js&quot;&gt;&lt;/script&gt;
    236   &lt;script type=&quot;text/javascript&quot; src=&quot;example.js&quot;&gt;&lt;/script&gt;
    237 &lt;/head&gt;
    238 </pre>
    239 <p><code>common.js</code> has shared code used by all SDK examples, and is described
    240 later in this document. <code>example.js</code> is a script that has code specific to
    241 this example.</p>
    242 <p>We also need to remove the inline event handler on the body tag:</p>
    243 <pre class="prettyprint">
    244 &lt;body onload=&quot;pageDidLoad()&quot;&gt;
    245 ...
    246 </pre>
    247 <p>This logic is now handled by <code>common.js</code>.</p>
    248 </section><section id="making-index-html-support-different-toolchains-and-configurations">
    249 <h3 id="making-index-html-support-different-toolchains-and-configurations">Making index.html support different toolchains and configurations</h3>
    250 <p>Finally, there are a few changes to <code>index.html</code> that are not necessary for
    251 CSP-compliance, but help make the SDK examples more generic.</p>
    252 <p>First, we add some <a class="reference external" href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes">data attributes</a>
    253 to the body element to specify the name, supported toolchains, supported
    254 configurations, and path to the <code>.nmf</code> file:</p>
    255 <pre class="prettyprint">
    256 &lt;body data-name=&quot;part2&quot;
    257     data-tools=&quot;newlib glibc pnacl&quot;
    258     data-configs=&quot;Debug Release&quot;
    259     data-path=&quot;{tc}/{config}&quot;&gt;
    260 ...
    261 </pre>
    262 <p><code>common.js</code> will read these data attributes to allow you to load the same
    263 example with different toolchains by changing the URL&#8217;s <a class="reference external" href="http://en.wikipedia.org/wiki/Query_string">query string</a>. For example, you can load the
    264 glibc Debug version of this example by navigating to
    265 <code>index.html?tc=glibc&amp;config=Debug</code>.</p>
    266 <p>Next, we remove the <code>embed</code> element that is described in HTML. This will be
    267 automatically added for us by <code>common.js</code>, based on the current
    268 toolchain/configuration combination:</p>
    269 <pre class="prettyprint">
    270 &lt;!--
    271 Just as in part1, the &lt;embed&gt; element will be wrapped inside the &lt;div&gt;
    272 element with the id &quot;listener&quot;. In part1, the embed was specified in HTML,
    273 here the common.js module creates a new &lt;embed&gt; element and adds it to the
    274 &lt;div&gt; for us.
    275 --&gt;
    276 &lt;div id=&quot;listener&quot;&gt;&lt;/div&gt;
    277 </pre>
    278 </section></section><section id="sharing-common-code-with-common-js">
    279 <h2 id="sharing-common-code-with-common-js">Sharing common code with common.js</h2>
    280 <p><code>common.js</code> contains JavaScript code that each example uses to create a
    281 NaCl module, handle messages from that module and other common tasks like
    282 displaying the module load status and logging messages. Explaining all of
    283 <code>common.js</code> is outside the scope of this document, but please look at the
    284 documentation in that file for more information.</p>
    285 <section id="loading-the-page-and-creating-the-module">
    286 <h3 id="loading-the-page-and-creating-the-module">Loading the page and creating the module</h3>
    287 <p>Since we&#8217;ve added <code>&lt;script&gt;</code> tags for <code>common.js</code> and <code>example.js</code> to the
    288 <code>head</code> element, they will be loaded and executed before the rest of the
    289 document has been parsed. As a result, we have to wait for the page to finish
    290 loading before we try to create the embed element and add it to the page.</p>
    291 <p>We can do that by calling <code>addEventListener</code> and listening for the
    292 <code>DOMContentLoaded</code> event:</p>
    293 <pre class="prettyprint">
    294 // Listen for the DOM content to be loaded. This event is fired when parsing of
    295 // the page's document has finished.
    296 document.addEventListener('DOMContentLoaded', function() {
    297   ...
    298 });
    299 </pre>
    300 <p>Inside this function, we parse the URL query string, and compare that to the
    301 data attributes:</p>
    302 <pre class="prettyprint">
    303 // From https://developer.mozilla.org/en-US/docs/DOM/window.location
    304 var searchVars = {};
    305 if (window.location.search.length &gt; 1) {
    306   var pairs = window.location.search.substr(1).split('&amp;');
    307   for (var key_ix = 0; key_ix &lt; pairs.length; key_ix++) {
    308     var keyValue = pairs[key_ix].split('=');
    309     searchVars[unescape(keyValue[0])] =
    310         keyValue.length &gt; 1 ? unescape(keyValue[1]) : '';
    311   }
    312 }
    313 
    314 ...
    315 
    316 var toolchains = body.dataset.tools.split(' ');
    317 var configs = body.dataset.configs.split(' ');
    318 
    319 ...
    320 
    321 var tc = toolchains.indexOf(searchVars.tc) !== -1 ?
    322     searchVars.tc : toolchains[0];
    323 
    324 // If the config value is included in the search vars, use that.
    325 // Otherwise default to Release if it is valid, or the first value if
    326 // Release is not valid.
    327 if (configs.indexOf(searchVars.config) !== -1)
    328   var config = searchVars.config;
    329 else if (configs.indexOf('Release') !== -1)
    330   var config = 'Release';
    331 else
    332   var config = configs[0];
    333 </pre>
    334 <p>Then <code>domContentLoaded</code> is called, which performs some checks to see if the
    335 browser supports Native Client, then creates the NaCl module.</p>
    336 <pre class="prettyprint">
    337 function domContentLoaded(name, tool, path, width, height, attrs) {
    338   updateStatus('Page loaded.');
    339   if (!browserSupportsNaCl(tool)) {
    340     updateStatus(
    341         'Browser does not support NaCl (' + tool + '), or NaCl is disabled');
    342   } else if (common.naclModule == null) {
    343     updateStatus('Creating embed: ' + tool);
    344 
    345     // We use a non-zero sized embed to give Chrome space to place the bad
    346     // plug-in graphic, if there is a problem.
    347     width = typeof width !== 'undefined' ? width : 200;
    348     height = typeof height !== 'undefined' ? height : 200;
    349     attachDefaultListeners();
    350     createNaClModule(name, tool, path, width, height, attrs);
    351   } else {
    352     // It's possible that the Native Client module onload event fired
    353     // before the page's onload event.  In this case, the status message
    354     // will reflect 'SUCCESS', but won't be displayed.  This call will
    355     // display the current message.
    356     updateStatus('Waiting.');
    357   }
    358 }
    359 </pre>
    360 <p><code>attachDefaultListeners</code> is added before the creation of the module, to make
    361 sure that no messages are lost. Note that <code>window.attachListeners</code> is also
    362 called; this is the way that <code>common.js</code> allows each example to configure
    363 itself differently. If an example defines the <code>attachListeners</code> function, it
    364 will be called by <code>common.js</code>.</p>
    365 <pre class="prettyprint">
    366 function attachDefaultListeners() {
    367   var listenerDiv = document.getElementById('listener');
    368   listenerDiv.addEventListener('load', moduleDidLoad, true);
    369   listenerDiv.addEventListener('message', handleMessage, true);
    370   listenerDiv.addEventListener('crash', handleCrash, true);
    371   if (typeof window.attachListeners !== 'undefined') {
    372     window.attachListeners();
    373   }
    374 }
    375 </pre>
    376 <p>Finally, <code>createNaClModule</code> actually creates the <code>embed</code>, and appends it as
    377 a child of the element with id <code>listener</code>:</p>
    378 <pre class="prettyprint">
    379 function createNaClModule(name, tool, path, width, height, attrs) {
    380   var moduleEl = document.createElement('embed');
    381   moduleEl.setAttribute('name', 'nacl_module');
    382   moduleEl.setAttribute('id', 'nacl_module');
    383   moduleEl.setAttribute('width', width);
    384   moduleEl.setAttribute('height', height);
    385   moduleEl.setAttribute('path', path);
    386   moduleEl.setAttribute('src', path + '/' + name + '.nmf');
    387 
    388   ...
    389 
    390   var mimetype = mimeTypeForTool(tool);
    391   moduleEl.setAttribute('type', mimetype);
    392 
    393   var listenerDiv = document.getElementById('listener');
    394   listenerDiv.appendChild(moduleEl);
    395   ...
    396 }
    397 </pre>
    398 <p>When the module finishes loading, it will dispatch a <code>load</code> event, and the
    399 event listener function that was registered above (<code>moduleDidLoad</code>) will be
    400 called. Note that <code>common.js</code> allows each example to define a
    401 <code>window.moduleDidLoad</code> function, that will be called here as well.</p>
    402 <pre class="prettyprint">
    403 function moduleDidLoad() {
    404   common.naclModule = document.getElementById('nacl_module');
    405   updateStatus('RUNNING');
    406 
    407   if (typeof window.moduleDidLoad !== 'undefined') {
    408     window.moduleDidLoad();
    409   }
    410 }
    411 </pre>
    412 </section></section><section id="example-specific-behavior-with-example-js">
    413 <h2 id="example-specific-behavior-with-example-js">Example-specific behavior with example.js</h2>
    414 <p>As described in the previous section, <code>common.js</code> will call certain functions
    415 during the module loading process. This example only needs to respond to two:
    416 <code>moduleDidLoad</code> and <code>handleMessage</code>.</p>
    417 <pre class="prettyprint">
    418 // This function is called by common.js when the NaCl module is
    419 // loaded.
    420 function moduleDidLoad() {
    421   // Once we load, hide the plugin. In this example, we don't display anything
    422   // in the plugin, so it is fine to hide it.
    423   common.hideModule();
    424 
    425   // After the NaCl module has loaded, common.naclModule is a reference to the
    426   // NaCl module's &lt;embed&gt; element.
    427   //
    428   // postMessage sends a message to it.
    429   common.naclModule.postMessage('hello');
    430 }
    431 
    432 // This function is called by common.js when a message is received from the
    433 // NaCl module.
    434 function handleMessage(message) {
    435   var logEl = document.getElementById('log');
    436   logEl.textContent += message.data;
    437 }
    438 </pre>
    439 </section></section>
    440 
    441 {{/partials.standard_nacl_article}}
    442