Chromebooks and Desktop Apps

You may have read some news about Chromebooks lately. It's user base is growing every day.

So what are Chromebooks? Basically, they are low-cost laptops running Chrome OS (a Linux variant) in which the Chrome browser is a central part of the user interface. As you might expect, it seamlessly integrates with the Google ecosystem. Here are some things about the Chromebook that stand out:

  1. They generally cost between $199 and $299.
  2. They take between 7 and 10 seconds to boot-up (Linux on solid state drives).
  3. They turn on instantly from sleep mode.
  4. Everything is stored in the cloud.
  5. Battery life ranges from 6.5 to 9.5 hours.
  6. Designed from the ground up with security in mind.
  7. The hardware is generally lightweight, thin and sleek.
  8. Updates happen automatically behind the scenes.
  9. Supports desktop apps.

I decided to try my hand at Chrome apps and released an educational game for the Chromebook called "The 50 States." It helps people learn about United States geography. It's a desktop app that doesn't require an Internet connection. It runs in its own window rather than the Chrome browser. Here's how it looks:

The 50 States

As you can see, it's running in its own window. In fact, the Chrome OS looks very much like a desktop operating system:

Chrome OS Desktop

The underlying technologies for Chrome apps are HTML, CSS and JavaScript. You can use any frameworks, toolkits, libraries, etc. you'd like. I would say the biggest difference in Chrome apps that developers have to understand is CSP (Content Security Policy).

You can find the documentation for CSP here.

Here are the main points of CSP:

Eval and related functions are disabled.

The documentation states this code will not work:

alert(eval("foo.bar.baz"));  
window.setTimeout("alert('hi')", 10);  
window.setInterval("alert('hi')", 10);  
new Function("return foo.bar.baz");  

It says the above code should be replaced with:

alert(foo && foo.bar && foo.bar.baz);  
window.setTimeout(function() { alert('hi'); }, 10);  
window.setInterval(function() { alert('hi'); }, 10);  
function() { return foo && foo.bar && foo.bar.baz };  

Inline JavaScript will not be executed

For example, inline code like this will not work:

<button onclick="...">  

The following code (taken straight from the documentation) contains inline JavaScript:

<!doctype html>  
<html>  
  <head>
    <title>My Awesome Popup!</title>
    <script>
      function awesome() {
        // do something awesome!
      }

      function totallyAwesome() {
        // do something TOTALLY awesome!
      }

      function clickHandler(element) {
        setTimeout("awesome(); totallyAwesome()", 1000);
      }

      function main() {
        // Initialization work goes here.
      }
    </script>
  </head>
  <body onload="main();">
    <button onclick="clickHandler(this)">
      Click for awesomeness!
    </button>
  </body>
</html>  

The above code would have to be rewritten as follows:

popup.html

<!doctype html>  
<html>  
  <head>
    <title>My Awesome Popup!</title>
    <script src="popup.js"></script>
  </head>
  <body>
    <button>Click for awesomeness!</button>
  </body>
</html>  

popup.js

function awesome() {  
  // Do something awesome!
}

function totallyAwesome() {  
  // do something TOTALLY awesome!
}

function awesomeTask() {  
  awesome();
  totallyAwesome();
}

function clickHandler(e) {  
  setTimeout(awesomeTask, 1000);
}

function main() {  
  // Initialization work goes here.
}

// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {  
  document.querySelector('button').addEventListener('click', clickHandler);
  main();
});

Only local script and and object resources are loaded

Basically, this means that you cannot reference any static resources on the web. They have to be included with the source code.

In addition to the CSP, there's a manifest file (manifest.json) where you define things like the service endpoints your app can access and the security permissions your app requires.

You can find the documentation for manifest files here.

Now, you may need to make use of a JavaScript library that does not comply with the CSP. In these cases, you can sandbox certain pages in your application. Sandboxed pages don't have to comply with CSP. However, these pages are confined to an iFrame and cannot directly utilize APIs nor access service endpoints on the Internet. Basically, these sandboxed pages have to pass messages to other pages that are not sandboxed.

I'll go into more detail about Chrome Desktop Apps in my next post.