Reflections on Developing our First Chrome* App

By Randy Schott

When the Techsmith* Snagit* for Google Chrome team was formed, we were tasked with fulfilling a simple request from our customers:  screencasting on Chromebooks*.  We had little knowledge of the platform or possibilities, but it was an exciting opportunity.  What follows are some reflections on our experiences and some information that I hope will be useful to other developers wishing to explore the Chrome platform.


Our product team started and has remained relatively small, initially consisting of 2 developers, a UX designer, a shared QA resource, and a few people dedicated to market research and strategy.  We’ve since added a full-time QA and a few additional developers.

Our developers came from all parts of the company, including our desktop C++ products, front-end web development, and even an iOS experiment in the educational arena.  Most of us had never heard of Chrome Apps, though almost all of us had used Chrome Extensions*.

Apps vs. Extensions

Before we go any further, it would be helpful to understand the different types of applications you can develop for Chrome.  If you already understand the differences between Chrome Apps and Chrome Extensions, feel free to skip ahead.

Chrome Extensions extend the functionality of the browser.  They are intended to enhance your experience within the browser. Extensions are exposed as a series of icons near the Chrome URL bar, and they must operate inside the browser window.

Chrome Apps, on the other hand, are full-fledged applications that use Chrome as a platform.  You write a single code base, and Chrome does the work of making that code run on Windows*, OS X*, Linux* and Chrome OS.  Apps don’t get an icon in the URL bar and can’t access the content of your pages. Instead they show up in the Apps section of Chrome’s new tab page, as well as in the Chrome Apps Launcher.

Chrome apps can be broken into two categories:  Hosted Apps and Packaged Apps.  Hosted Apps are externally hosted sites that are listed in the Chrome Web Store, must be run within the browser, and make use of the Chrome Platform APIs to provide functionality beyond what a traditional web app can deliver. Packaged Apps are self-contained downloadable applications that can be installed to your machine.  Packaged apps run in their own window, separate from Chrome, and have a more native feel.

From here on, I will collectively refer to Chrome Apps and Extensions as “Chrome applications”, and use proper nouns (Chrome Apps, Chrome Extensions) when talking specifics.

What’s in a Chrome application?

Chrome applications are built just like you would a modern web application: HTML, Javascript, CSS.  It’s like writing a web app and not having to worry about testing or supporting any other browser.  You are also instantly granted access to a host of web standards that you’ve been avoiding because they aren’t cross-browser yet. For example, the library view in our application uses flexbox for layout.  You could probably make that work in a modern web app with a polyfill or aggressive browser targeting, but it was an easy decision for us when we only had to care about Chrome.

Front end frameworks and libraries are perfectly acceptable, but be mindful of those that are designed to bridge the gaps between browsers (for example: Modernizr or jQuery), as there are no gaps to fill.  Chrome applications are encouraged to follow the MVC pattern, so if you have a library you prefer, then go for it.  We had previous experience with AngularJS, so we chose to use that.

In addition to the usual web resources, your application will also include a manifest file.  This is a JSON file, the purpose of which is to:

  • Define all the information Chrome will need in order to install and run your application (name, version, minimum Chrome version, etc.).
  • Act as a means to declare special permissions your application will need.

There are also some additional fields that are specific to Apps and Extensions.  For instance, Extensions use the manifest to declare which pages it would like access to, and Apps use the manifest to enable “kiosk mode”.

The Development Cycle

Web app development often involves some version of running a local server to host files, editing those files, and reloading the page to test your changes; with a Chrome application, your test environment is the browser itself.  Chrome will allow you to load “unpacked extensions” into the browser by visiting the chrome://extensions page and switching to “Developer Mode”.  An unpacked extension is a directory containing all the assets (including the manifest) needed to run your application.

When you install an unpacked extension, Chrome will generate an application ID for you based on the path to the directory hosting the extension.  On the same machine, this appears to be consistent, so uninstalling and reinstalling the unpacked extension from the same folder will generate the same ID.  If you decide to use any google APIs (Google Drive*, YouTube*, etc.), you will have to generate OAuth credentials for those APIs based on the application ID, so moving the code to a new folder means generating a new set of credentials.

Platform and Extension APIs

Chrome exposes a plethora of APIs that allow you to do things like accessing the file system, saving and loading settings, managing the user’s bookmarks, and even capturing the content of the screen.  Most of the APIs require declaration of a permission in your manifest file, which in turn requires the user to accept those permissions when installing your application.

One thing that wasn’t immediately clear to me is that Apps and Extensions have separate sets of APIs available to them.  Many of the extension APIs are related to the browsing experience, such as accessing information about the open tabs.  The App APIs tend to lean more toward native functionality such as creating and managing windows, querying information about connected displays, and interacting with USB devices.

It’s not directly documented, but a few of the Extension APIs, such as desktopCapture, are actually available to Apps as well.  The documentation is constantly improving, but if you’re unsure, the easiest way to tell is to try including the required permission in your manifest.  Chrome will notify you if requested permissions are not allowed for your application type.

Aside from the APIs, there are also a handful of permissions that give your application special privileges, such as unlimited storage in the HTML5 filesystem.

Tooling and Dev Environments

If you’ve done any work on web applications, the development environment should feel familiar.  The final output that you deploy will mostly be a bundle of HTML, Javascript, and CSS. How you create those files is entirely up to you. 

My team has taken a liking to WebStorm, but any editor will do.  You may want to choose one that is web-aware (i.e. supports syntax highlighting and completion for HTML/JS/CSS).  But if vim is your thing, go for it.

We’re also big fans of Grunt for automating build tasks.  We use it for compiling and concatenating sources, minification, generating application manifests, installing dependencies, running unit tests, packaging the app, and even deploying to the web store.

The Chrome Web Store

When you’re ready to publish your application, you will end up in the Chrome Web Store. Publishing an application involves creating a store entry and uploading a zip archive.  The store entry consists of things like a product description, providing thumbnails and screenshots, picking categories and selecting which countries and regions should have access to your application.  The zip archive contains your manifest file and any assets required to run your application.  For Extensions and Packaged Apps, “assets” means your HTML/JS/CSS/etc. For Hosted Apps, the archive will only contain the manifest, since all assets are hosted externally.

The CWS keeps your entries in a perpetual “draft” state until you decide to hit “Publish”.  This means that you can make several changes to the description, and upload multiple zip archives before your entry ever goes live in the store.  Beware the “Discard Draft” button, which will completely erase the information stored in your draft (even if you have already published!).  Once you hit “Publish”, the CWS will begin processing your entry and deploying it.  One thing to note is that uploading a zip archive typically incurs a 30-60 minute delay while the application is being analyzed.  You can avoid this by uploading the archive in advance and saving a draft.  When you come back later to publish, the archive will have been analyzed and publishing will cause the entry to go live within a few minutes.

Google recently added an API to allow publishing to the web store programmatically.  This means that once you have set up the store entries, you can push a new version right from the command line.  Our team has special build targets set up in TeamCity that allow any team member to generate and push a new development build to the store with the click of a button.  It probably saves us a few hours a week.

Beta and Development Builds

During our development cycle, we often want to fire off development builds of the product so that QA can test new features. We could package a CRX and put it on a shared network location, but that loses the full workflow of having an application installed from the web store and automatically updating when a new version is pushed.  To get the full experience, we maintain two separate store entries.  One entry will be the production version of the application, and another is our “Hot n’ Busted” version, built directly from the development branch in GitHub. 

To keep the development build from being publicly accessible, we take advantage of the visibility setting in the Chrome Web Store.  This setting allows you to choose between publishing an application publicly, within your Google Apps* domain (if you have one), to members of a specific Google Group, or to Google users in a specific list.  We chose to publish the application within our domain, so everyone at the company has the option of staying on the bleeding edge.

Native Client (NaCl)

Some applications need to perform compute-intensive operations, such as mathematical calculations or audio/video processing.  Native Client provides a solution to this by allowing you to write C/C++ code that will be compiled down to native byte-code, instead of running in a Javascript VM.

Native Client code runs in a sandboxed DOM element.  Your Javascript code will communicate with it by passing messages and data via postMessage calls on the element and listening to ‘onMessage’ events that bubble up from the element.  Due to the sandboxing, Native Client code does not have access to the DOM.  However, there are APIs available for reading/writing to the HTML5 file system, drawing to the screen, emitting audio, capturing pointer/keyboard events, and more.

TechSmith has a proprietary screen recording codec that we were able to port over to Native Client.  Having this codec in native code is what allowed us to get acceptable performance for screencasting in Chrome. Native Client even supports intrinsic CPU instructions, which allowed us to optimize the performance even further.  This proved to be incredibly helpful for running on Chromebooks, especially Haswell-based machines, which performed exceptionally well.

The Moving Target

Developing for Chrome as a platform often means staying on the bleeding edge.  The Chrome update cycle seems to average about 6 weeks.  Each update pushes new features (and potentially new bugs) into the world.  For example, version 34 saw the release of the desktopCapture API. Knowing that the API was in beta and would be released to stable with version 34 allowed our team to have our screen recording feature positioned for launch roughly around the same time.  However, we also lost some application functionality that day, as version 34 introduced a few bugs that happened to hit our application unusually hard.

Keeping an eye on the target isn’t incredibly difficult.  Chrome provides several release tracks (Dev, Beta, Stable) as well as nightly builds through Chrome Canary.  It’s a good idea to have a few people on your team running at least Chrome Beta, so you see any upcoming issues well ahead of time.  Upcoming APIs will initially be available only in the Dev channel, and then in the Beta channel as they become stable.

Tracking time between Chrome version releases

Also keep in mind that Chrome only updates when you restart.  So, if you’re like me and you tend to keep 20 tabs open for a week, you may want to force yourself to restart every morning to make sure you have the latest update.  You can always recover those tabs (all at once!) via the History menu.

Further Reading

Google has extensive documentation on Chrome Apps and Chrome Extensions, far more than I could try to cover here.  Take time to really dig through the developer sites.  There are also Google Groups that can be of assistance: chromium-apps, chromium-extensions, and native-client-discuss

Randy Schott, the author of this article, is a Senior Software Engineer at TechSmith Corporation. To find out more about TechSmith Snagit for Google Chrome, visit the TechSmith blog post announcing screen recording. To download the app AND extension (you need both!), visit the TechSmith Snagit for Google Chrome homepage.


For more complete information about compiler optimizations, see our Optimization Notice.