Develop Polymer Chrome Apps on a ChromeBook with Chrome Dev Editor and deal with Content Security Policies

After watching this video Google I/O 2014 - How we built Chrome Dev Editor with the Chrome platform, i decides to give a (serious) try to Chrome Dev Editor:

“Chrome Dev Editor (CDE) is a developer tool for building apps on the Chrome platform - Chrome Apps and Web Apps.”

It was an opportunity to learn how to develop Chrome Apps, but directly on a ChromeBook. The aim is also to see if a “low cost” computer as C720P Chromebook can be used as development workstation.

1st contact

First good surprise CDE offers project templates, and especially for Chrome App Dart:

So, i tried the Dart template:

It’s very interesting, you even have a list of methods in the right panel.

Now it’s time to build our application, and then run it. I clicked on the “run” button … and wait …

to finally get my first Chrome App (in more than 30 seconds!):

More than 30 seconds (and 26 seconds on a MacBook pro), it’s too long! Chrome Dev Editor is still not the right tool to train me with Dart.

So I decided to try the JavaScript version. So I repeated the same manipulations, but with the javascript project template, and the launch is instantaneous, which is normal, there is no code to “transpile”. It will be much more comfortable to code, even if I lose the perks (goodies) related to Dart (as methods right panel).

It’s time to code!

It’s been a while since I played with Polymer. And I am convinced that this is the ideal model for apps. So I would use Polymer.

Add a bower.json file to your project, with this content:

{
  "name": "second-contact",
  "version": "0.0.0",
  "dependencies": {
    "polymer": "Polymer/polymer# ~0.3.5"
  }
}

And, right click on the bower.json file and choose “Bower Install”:

This is a pleasant surprise, you can use Bower from CDE even with a ChromeBook. And you can see that all dependencies have been downloaded:

First Web Component

First, create a components directory and a new file my-title.html (in the components directory) with this content:

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="my-title">

  <template>
    <h1>{{label}}</h1>
  </template>
  
  <script>
    Polymer("my-title", {
      ready: function() {
        this.label = "I <3 my ChromeBook";
      }
    });
  </script>

</polymer-element>

And, now prepare the main file of your application (window.html) to host your new component

<!-- windows.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>second-contact</title>
    <link rel="stylesheet" href="styles.css">
    <script src="bower_components/platform/platform.js"></script>
    <!-- your component -->
    <link rel="import" href="components/my-title.html">
  </head>

  <body>

    <my-title></my-title>
    
  </body>
</html>

Remark: you can delete window.js if you want.

And now … Launch the Chrome App! … And nothing!!!:

Right click on the screen application and choose “Inspect element”:

Content Security Policy

If you read this http://www.polymer-project.org/resources/faq.html# chromeapp, it is explained that “Chrome Apps have a strict Content Security Policy (CSP) which prevents the use of inline script elements”. So, you have to turn inline script elements into external files. You can use Vulcanize your components, but we are on a Chrome Book, so it’s impossible. Then change content of my-title.html like that:

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="my-title">

  <template>
    <h1>{{label}}</h1>
  </template>
  
  <script src="my-title.js"></script>

</polymer-element>

And create (at the same location) a my-title.js:

Polymer("my-title", {
  ready: function() {
    this.label = "I <3 my ChromeBook";
  }
});

And run again your application:

# Consequences

You can’t use all existing components (core-components, paper-components) on a ChromeBook unless to vulcanize them before. But you still get the templating and data binding, and the “Web Component” way. So there are other constraints due to this security policy. We will see in the next paragraph.

Second component

Let’s create an other Polymer Component : my-cute-button.htm (and my-cute-button.js):

my-cute-button.htm:

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="my-cute-button">

  <template>
    <button onclick="{{buttonClick}}">{{label}}</button>
  </template>
  
  <script src="my-cute-button.js"></script>

</polymer-element>

my-cute-button.js:

Polymer("my-cute-button", {
  ready: function() {
    this.label = "I'm a button";
  },
  buttonClick: function() {
    this.label += " Clicked!";
  }
});

Add your new component to window.html:

<!-- windows.html-->
<!DOCTYPE html>
<html>
  <head>
    <title>second-contact</title>
    <link rel="stylesheet" href="styles.css">
    <script src="bower_components/platform/platform.js"></script>
    <!-- yours components -->
    <link rel="import" href="components/my-title.html">
    <link rel="import" href="components/my-cute-button.html">
  </head>

  <body>

    <my-title></my-title>
    <my-cute-button></my-cute-button>

  </body>
</html>

Launch your application:

It’s nice but if you click on the cute button, nothing happens. So, Right click on the screen application and choose “Inspect element”:

It’s still the fault of the CSP!!! We’ve seen that inline scripts are forbidden, and it applys to inline event handlers too. See this https://developer.chrome.com/extensions/contentSecurityPolicy# JSExecution.

But, there is always a solution :)

See how to get around this problem and modify the Web Component “my-cute-button” :

  • Remove onclick="{{buttonClick}}" from the button
  • Add an id to the button

my-cute-button.html:

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="my-cute-button">

  <template>
    <button id="mybutton">{{label}}</button>
  </template>
  
  <script src="my-cute-button.js"></script>

</polymer-element>

And add a listener to “click event” on the button:

my-cute-button.js:

Polymer("my-cute-button", {
  ready: function() {
    this.label = "I'm a button";
    
    this.$.mybutton.addEventListener("click", function(event) {
      this.buttonClick();
    }.bind(this));
  },
  buttonClick: function() {
    this.label += " Clicked!";
  }
});

Run again the application, it works!:

One More Thing: communication between components

I would change the title of the first component when I click on the 2nd. For that, the <core-signals> Polymer component is perfect (see http://www.polymer-project.org/articles/communication.html# using-ltcore-signalsgt), but we’ve seen that the Chrome Apps CSP prohibit inline scripts and unless to “vulcanize” it, you have to use an other solution.

This is a quick and dirty solution (a parent controller and observer pattern are “advisable”), but it runs:

Add a listener to “yo” event in my-title.js:

Polymer("my-title", {
  ready: function() {
    console.log("Hello")
    this.label = "I <3 my ChromeBook";
    
    document.addEventListener('yo', function(event) {
      this.label += " Clicked!"
    }.bind(this));
  }
});

Fire “yo” event when button is clicked in my-cute-button.js:

Polymer("my-cute-button", {
  ready: function() {
    this.label = "I'm a button";
    
    this.$.mybutton.addEventListener("click", function(event) {
      this.buttonClick();
    }.bind(this));
  },
  buttonClick: function() {
    document.dispatchEvent(new CustomEvent("yo", {action:"clicked"}));
  }
});

And it runs!:

So, with some adjustments, it is entirely possible to use Polymer directly on a ChromeBook to develop Chrome Apps. If you want to give your application an “attractive appearance”, I advise you to use the Google Web Starter-Kit. If you want a sample, i’ve made a “quick start” here https://github.com/metals/adamantium and it looks like this on a Chrome Book:

To conclude

It’s pretty nice to develop javascript Chrome applications with CDE, and especially the possibility to launch the application directly from CDE. Unfortunately, Dart transpilation is too long, but CDE (already transpiled) is a very good example of what is possible (with Dart but also with JavaScript) on a Chrome Book. So, I think my little C720P is a very interesting computer, and Chrome OS a very good OS.

I’m waiting deeply about native HTML Imports, then we’ll can use Polymer with all its abilities.

I <3 Chrome* ;)

blog comments powered by Disqus

Related posts