15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Set to true when the Document is loaded IFF "test=true" is in the query
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// string.
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvar isTest = false;
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Set to true when loading a "Release" NaCl module, false when loading a
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// "Debug" NaCl module.
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)var isRelease = true;
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Javascript module pattern:
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   see http://en.wikipedia.org/wiki/Unobtrusive_JavaScript#Namespaces
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In essence, we define an anonymous function which is immediately called and
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns a new object. The new object contains only the exported definitions;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all other definitions in the anonymous function are inaccessible to external
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// code.
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvar common = (function() {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  function isHostToolchain(tool) {
22a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return tool == 'win' || tool == 'linux' || tool == 'mac';
23a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
24a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
25a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  /**
26a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * Return the mime type for NaCl plugin.
27a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   *
28a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
29a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * @return {string} The mime-type for the kind of NaCl plugin matching
30a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * the given toolchain.
31a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   */
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  function mimeTypeForTool(tool) {
33a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // For NaCl modules use application/x-nacl.
34a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    var mimetype = 'application/x-nacl';
35a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if (isHostToolchain(tool)) {
36a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      // For non-NaCl PPAPI plugins use the x-ppapi-debug/release
37a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      // mime type.
38a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      if (isRelease)
39a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        mimetype = 'application/x-ppapi-release';
40a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      else
41a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch        mimetype = 'application/x-ppapi-debug';
42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    } else if (tool == 'pnacl') {
43a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      mimetype = 'application/x-pnacl';
44a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    }
45a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return mimetype;
46a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
47a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
48a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  /**
49a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * Check if the browser supports NaCl plugins.
50a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   *
51a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
52a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * @return {bool} True if the browser supports the type of NaCl plugin
53a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   * produced by the given toolchain.
54a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch   */
55a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  function browserSupportsNaCl(tool) {
56a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // Assume host toolchains always work with the given browser.
57a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // The below mime-type checking might not work with
58a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // --register-pepper-plugins.
59a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    if (isHostToolchain(tool)) {
60a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      return true;
61a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    }
62a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    var mimetype = mimeTypeForTool(tool);
63a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return navigator.mimeTypes[mimetype] !== undefined;
64a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
65a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   * Inject a script into the DOM, and call a callback when it is loaded.
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   *
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   * @param {string} url The url of the script to load.
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   * @param {Function} onload The callback to call when the script is loaded.
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   * @param {Function} onerror The callback to call if the script fails to load.
723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   */
733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  function injectScript(url, onload, onerror) {
743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    var scriptEl = document.createElement('script');
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scriptEl.type = 'text/javascript';
763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scriptEl.src = url;
773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scriptEl.onload = onload;
783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (onerror) {
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      scriptEl.addEventListener('error', onerror, false);
803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    document.head.appendChild(scriptEl);
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  /**
853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   * Run all tests for this example.
863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   *
873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   * @param {Object} moduleEl The module DOM element.
883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)   */
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  function runTests(moduleEl) {
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    console.log('runTests()');
913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    common.tester = new Tester();
923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // All NaCl SDK examples are OK if the example exits cleanly; (i.e. the
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // NaCl module returns 0 or calls exit(0)).
953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    //
963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Without this exception, the browser_tester thinks that the module
973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // has crashed.
983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    common.tester.exitCleanlyIsOK();
993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    common.tester.addAsyncTest('loaded', function(test) {
1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      test.pass();
1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    });
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (typeof window.addTests !== 'undefined') {
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      window.addTests();
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    common.tester.waitFor(moduleEl);
1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    common.tester.run();
1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  /**
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Create the Native Client <embed> element as a child of the DOM element
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * named "listener".
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} name The name of the example.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} path Directory name where .nmf file can be found.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} width The width to create the plugin.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} height The height to create the plugin.
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch   * @param {Object} attrs Dictionary of attributes to set on the module.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  function createNaClModule(name, tool, path, width, height, attrs) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var moduleEl = document.createElement('embed');
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moduleEl.setAttribute('name', 'nacl_module');
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moduleEl.setAttribute('id', 'nacl_module');
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moduleEl.setAttribute('width', width);
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    moduleEl.setAttribute('height', height);
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    moduleEl.setAttribute('path', path);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moduleEl.setAttribute('src', path + '/' + name + '.nmf');
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Add any optional arguments
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (attrs) {
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      for (var key in attrs) {
1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        moduleEl.setAttribute(key, attrs[key]);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
139a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    var mimetype = mimeTypeForTool(tool);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    moduleEl.setAttribute('type', mimetype);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The <EMBED> element is wrapped inside a <DIV>, which has both a 'load'
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and a 'message' event listener attached.  This wrapping method is used
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // instead of attaching the event listeners directly to the <EMBED> element
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to ensure that the listeners are active before the NaCl module 'load'
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // event fires.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var listenerDiv = document.getElementById('listener');
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listenerDiv.appendChild(moduleEl);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Request the offsetTop property to force a relayout. As of Apr 10, 2014
151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // this is needed if the module is being loaded on a Chrome App's
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // background page (see crbug.com/350445).
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    moduleEl.offsetTop;
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Host plugins don't send a moduleDidLoad message. We'll fake it here.
156a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    var isHost = isHostToolchain(tool);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (isHost) {
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      window.setTimeout(function() {
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        moduleEl.readyState = 1;
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        moduleEl.dispatchEvent(new CustomEvent('loadstart'));
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        moduleEl.readyState = 4;
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        moduleEl.dispatchEvent(new CustomEvent('load'));
163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        moduleEl.dispatchEvent(new CustomEvent('loadend'));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }, 100);  // 100 ms
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // This is code that is only used to test the SDK.
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (isTest) {
1693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      var loadNaClTest = function() {
1703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        injectScript('nacltest.js', function() {
171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          runTests(moduleEl);
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        });
1737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      };
1743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      // Try to load test.js for the example. Whether or not it exists, load
1763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      // nacltest.js.
1773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      injectScript('test.js', loadNaClTest, loadNaClTest);
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Add the default "load" and "message" event listeners to the element with
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * id "listener".
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * The "load" event is sent when the module is successfully loaded. The
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * "message" event is sent when the naclModule posts a message using
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * PPB_Messaging.PostMessage() (in C) or pp::Instance().PostMessage() (in
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * C++).
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function attachDefaultListeners() {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var listenerDiv = document.getElementById('listener');
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listenerDiv.addEventListener('load', moduleDidLoad, true);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listenerDiv.addEventListener('message', handleMessage, true);
194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    listenerDiv.addEventListener('error', handleError, true);
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    listenerDiv.addEventListener('crash', handleCrash, true);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (typeof window.attachListeners !== 'undefined') {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.attachListeners();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  /**
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   * Called when the NaCl module fails to load.
203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   *
204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   * This event listener is registered in createNaClModule above.
205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)   */
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  function handleError(event) {
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // We can't use common.naclModule yet because the module has not been
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // loaded.
209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    var moduleEl = document.getElementById('nacl_module');
210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    updateStatus('ERROR [' + moduleEl.lastError + ']');
211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /**
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * Called when the Browser can not communicate with the Module
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   *
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * This event listener is registered in attachDefaultListeners above.
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   */
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  function handleCrash(event) {
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (common.naclModule.exitStatus == -1) {
2203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      updateStatus('CRASHED');
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
2223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      updateStatus('EXITED [' + common.naclModule.exitStatus + ']');
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (typeof window.handleCrash !== 'undefined') {
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window.handleCrash(common.naclModule.lastError);
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called when the NaCl module is loaded.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * This event listener is registered in attachDefaultListeners above.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function moduleDidLoad() {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    common.naclModule = document.getElementById('nacl_module');
2367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    updateStatus('RUNNING');
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (typeof window.moduleDidLoad !== 'undefined') {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.moduleDidLoad();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Hide the NaCl module's embed element.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * We don't want to hide by default; if we do, it is harder to determine that
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * a plugin failed to load. Instead, call this function inside the example's
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * "moduleDidLoad" function.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function hideModule() {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Setting common.naclModule.style.display = "None" doesn't work; the
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // module will no longer be able to receive postMessages.
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    common.naclModule.style.height = '0';
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)   * Remove the NaCl module from the page.
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)   */
26058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  function removeModule() {
26158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    common.naclModule.parentNode.removeChild(common.naclModule);
26258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    common.naclModule = null;
26358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
26458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  /**
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Return true when |s| starts with the string |prefix|.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} s The string to search.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} prefix The prefix to search for in |s|.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function startsWith(s, prefix) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // indexOf would search the entire string, lastIndexOf(p, 0) only checks at
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the first index. See: http://stackoverflow.com/a/4579228
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return s.lastIndexOf(prefix, 0) === 0;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /** Maximum length of logMessageArray. */
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var kMaxLogMessageLength = 20;
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  /** An array of messages to display in the element with id "log". */
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  var logMessageArray = [];
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   * Add a message to an element with id "log".
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * This function is used by the default "log:" message handler.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} message The message to log.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function logMessage(message) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    logMessageArray.push(message);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (logMessageArray.length > kMaxLogMessageLength)
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      logMessageArray.shift();
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    document.getElementById('log').textContent = logMessageArray.join('\n');
2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    console.log(message);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var defaultMessageTypes = {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'alert': alert,
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'log': logMessage
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called when the NaCl module sends a message to JavaScript (via
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * PPB_Messaging.PostMessage())
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * This event listener is registered in createNaClModule above.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {Event} message_event A message event. message_event.data contains
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     the data sent from the NaCl module.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function handleMessage(message_event) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (typeof message_event.data === 'string') {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (var type in defaultMessageTypes) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (defaultMessageTypes.hasOwnProperty(type)) {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (startsWith(message_event.data, type + ':')) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            func = defaultMessageTypes[type];
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            func(message_event.data.slice(type.length + 1));
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            return;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (typeof window.handleMessage !== 'undefined') {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window.handleMessage(message_event);
3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    logMessage('Unhandled message: ' + message_event.data);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Called when the DOM content has loaded; i.e. the page's document is fully
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * parsed. At this point, we can safely query any elements in the document via
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * document.querySelector, document.getElementById, etc.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} name The name of the example.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} tool The name of the toolchain, e.g. "glibc", "newlib" etc.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} path Directory name where .nmf file can be found.
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} width The width to create the plugin.
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {number} height The height to create the plugin.
3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch   * @param {Object} attrs Optional dictionary of additional attributes.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  function domContentLoaded(name, tool, path, width, height, attrs) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the page loads before the Native Client module loads, then set the
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // status message indicating that the module is still loading.  Otherwise,
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // do not change the status message.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updateStatus('Page loaded.');
353ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!browserSupportsNaCl(tool)) {
354a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      updateStatus(
355a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch          'Browser does not support NaCl (' + tool + '), or NaCl is disabled');
356a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    } else if (common.naclModule == null) {
3577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      updateStatus('Creating embed: ' + tool);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We use a non-zero sized embed to give Chrome space to place the bad
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // plug-in graphic, if there is a problem.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      width = typeof width !== 'undefined' ? width : 200;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      height = typeof height !== 'undefined' ? height : 200;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      attachDefaultListeners();
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      createNaClModule(name, tool, path, width, height, attrs);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // It's possible that the Native Client module onload event fired
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // before the page's onload event.  In this case, the status message
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // will reflect 'SUCCESS', but won't be displayed.  This call will
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // display the current message.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updateStatus('Waiting.');
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /** Saved text to display in the element with id 'statusField'. */
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var statusText = 'NO-STATUSES';
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /**
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Set the global status message. If the element with id 'statusField'
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * exists, then set its HTML to the status message as well.
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * @param {string} opt_message The message to set. If null or undefined, then
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     set element 'statusField' to the message from the last call to
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   *     updateStatus.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   */
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function updateStatus(opt_message) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (opt_message) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      statusText = opt_message;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var statusField = document.getElementById('statusField');
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (statusField) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      statusField.innerHTML = statusText;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The symbols to export.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /** A reference to the NaCl module, once it is loaded. */
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    naclModule: null,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    attachDefaultListeners: attachDefaultListeners,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    domContentLoaded: domContentLoaded,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    createNaClModule: createNaClModule,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    hideModule: hideModule,
40458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    removeModule: removeModule,
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    logMessage: logMessage,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    updateStatus: updateStatus
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}());
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Listen for the DOM content to be loaded. This event is fired when parsing of
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the page's document has finished.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)document.addEventListener('DOMContentLoaded', function() {
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  var body = document.body;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The data-* attributes on the body can be referenced via body.dataset.
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (body.dataset) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var loadFunction;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!body.dataset.customLoad) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loadFunction = common.domContentLoaded;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (typeof window.domContentLoaded !== 'undefined') {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loadFunction = window.domContentLoaded;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // From https://developer.mozilla.org/en-US/docs/DOM/window.location
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var searchVars = {};
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (window.location.search.length > 1) {
4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      var pairs = window.location.search.substr(1).split('&');
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (var key_ix = 0; key_ix < pairs.length; key_ix++) {
4307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        var keyValue = pairs[key_ix].split('=');
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        searchVars[unescape(keyValue[0])] =
4327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            keyValue.length > 1 ? unescape(keyValue[1]) : '';
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (loadFunction) {
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var toolchains = body.dataset.tools.split(' ');
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var configs = body.dataset.configs.split(' ');
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      var attrs = {};
4417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (body.dataset.attrs) {
4427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        var attr_list = body.dataset.attrs.split(' ');
4437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        for (var key in attr_list) {
4447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          var attr = attr_list[key].split('=');
4457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          var key = attr[0];
4467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          var value = attr[1];
4477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          attrs[key] = value;
4487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
4497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
4507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var tc = toolchains.indexOf(searchVars.tc) !== -1 ?
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          searchVars.tc : toolchains[0];
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // If the config value is included in the search vars, use that.
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Otherwise default to Release if it is valid, or the first value if
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Release is not valid.
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (configs.indexOf(searchVars.config) !== -1)
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        var config = searchVars.config;
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      else if (configs.indexOf('Release') !== -1)
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        var config = 'Release';
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      else
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        var config = configs[0];
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var pathFormat = body.dataset.path;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      var path = pathFormat.replace('{tc}', tc).replace('{config}', config);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      isTest = searchVars.test === 'true';
468ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      isRelease = path.toLowerCase().indexOf('release') != -1;
4697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      loadFunction(body.dataset.name, tc, path, body.dataset.width,
4717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                   body.dataset.height, attrs);
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
475