(function (h) {
  'use strict';

  var TabState = h.TabState;
  var icons = {};
  icons[TabState.states.ACTIVE] = {
    19: 'images/browser-icon-active.png',
    38: 'images/browser-icon-active@2x.png'
  };
  icons[TabState.states.INACTIVE] = {
    19: 'images/browser-icon-inactive.png',
    38: 'images/browser-icon-inactive@2x.png'
  };

  // Fake localization function.
  function _(str) {
    return str;
  }

  /* Manages the display of the browser action button. */
  function BrowserAction(chromeBrowserAction) {
    this.setState = function (tabId, state) {
      switch (state) {
        case TabState.states.ACTIVE:   this.activate(tabId); break;
        case TabState.states.INACTIVE: this.deactivate(tabId); break;
        case TabState.states.ERRORED:  this.error(tabId); break;
        default: throw new TypeError('State ' + state + ' is invalid');
      }
    };

    this.activate = function (tabId) {
      chromeBrowserAction.setIcon({tabId: tabId, path: icons[TabState.states.ACTIVE]});
      chromeBrowserAction.setTitle({tabId: tabId, title: _('Hypothesis is active')});
    };

    this.deactivate = function (tabId) {
      chromeBrowserAction.setIcon({tabId: tabId, path: icons[TabState.states.INACTIVE]});
      chromeBrowserAction.setTitle({tabId: tabId, title: _('Hypothesis is inactive')});
    };

    this.error = function (tabId) {
      chromeBrowserAction.setIcon({tabId: tabId, path: icons[TabState.states.INACTIVE]});
      chromeBrowserAction.setTitle({tabId: tabId, title: _('Hypothesis has failed to load')});
      chromeBrowserAction.setBadgeText({tabId: tabId, text: '!'});
    };
  }

  BrowserAction.icons = icons;

  h.BrowserAction = BrowserAction;
})(window.h || (window.h = {}));

@@ -32,34 +32,182 @@
 %0A%0A  
-var TabState = h.TabState;
+// Cache the tab state constants.%0A  var states = h.TabState.states;%0A%0A  // Each button state has two icons one for normal resolution (19) and one%0A  // for hi-res screens (38).
 %0A  v
@@ -225,33 +225,24 @@
 %7B%7D;%0A  icons%5B
-TabState.
 states.ACTIV
@@ -343,33 +343,24 @@
  %7D;%0A  icons%5B
-TabState.
 states.INACT
@@ -547,14 +547,15 @@
  /* 
-Manage
+Control
 s th
@@ -592,17 +592,254 @@
 n button
-.
+ setting the icon, title%0A   * and badges depending on the current state of the tab. This is a stateless%0A   * module and does not store the current state. A TabState instance should%0A   * be used to manage which tabs are active/inactive.%0A  
  */%0A  fu
@@ -960,33 +960,24 @@
        case 
-TabState.
 states.ACTIV
@@ -1019,33 +1019,24 @@
        case 
-TabState.
 states.INACT
@@ -1084,25 +1084,16 @@
    case 
-TabState.
 states.E
@@ -1207,32 +1207,109 @@
       %7D%0A    %7D;%0A%0A
+    /* Sets the active browser action appearance for the provided tab id. */%0A
     this.activat
@@ -1388,33 +1388,24 @@
 path: icons%5B
-TabState.
 states.ACTIV
@@ -1496,32 +1496,111 @@
 ve')%7D);%0A    %7D;%0A%0A
+    /* Sets the inactive browser action appearance for the provided tab id. */%0A
     this.deactiv
@@ -1681,33 +1681,24 @@
 path: icons%5B
-TabState.
 states.INACT
@@ -1797,24 +1797,102 @@
 %7D);%0A    %7D;%0A%0A
+    /* Sets the errored browser action appearance for the provided tab id. */%0A
     this.err
@@ -1976,25 +1976,16 @@
 : icons%5B
-TabState.
 states.I

Document the BrowserAction module