Merge from m-c tip
authorBrian R. Bondy <netzen@gmail.com>
Thu, 16 Oct 2014 14:10:17 -0400
changeset 491331 d61f80a32dc158f9ce0c254921006675614f54a8
parent 491330 9ebe995cd8c354e49a795b4771415b96e0ec8b7e (current diff)
parent 210706 77f3ca1fe052ca3eced92af99221e29a7fc6c36b (diff)
child 491332 18dc1708c1b78859af183b7ab891b517a5699cf0
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
milestone36.0a1
Merge from m-c tip
b2g/components/AppFrames.jsm
b2g/installer/package-manifest.in
browser/app/nsBrowserApp.cpp
browser/app/profile/firefox.js
browser/components/loop/content/shared/libs/react-0.11.1-prod.js
browser/components/loop/content/shared/libs/react-0.11.1.js
browser/components/sessionstore/RevivableWindows.jsm
browser/components/sessionstore/test/browser_revive_windows.js
browser/confvars.sh
browser/installer/package-manifest.in
build/autoconf/ccache.m4
content/base/src/nsChannelPolicy.cpp
content/base/src/nsChannelPolicy.h
dom/canvas/test/webgl-conformance/mochi-wrapper.css
dom/mobileconnection/gonk/MobileConnectionService.js
dom/mobileconnection/gonk/nsIGonkMobileConnectionService.idl
gfx/gl/SurfaceStream.cpp
gfx/gl/SurfaceStream.h
ipc/glue/GeckoChildProcessHost.cpp
js/public/OldDebugAPI.h
js/src/vm/OldDebugAPI.cpp
js/xpconnect/src/XPCShellImpl.cpp
js/xpconnect/tests/unit/test_bug805807.js
layout/xul/nsBoxObject.cpp
layout/xul/nsBoxObject.h
layout/xul/nsContainerBoxObject.cpp
layout/xul/nsIEditorBoxObject.idl
layout/xul/nsIIFrameBoxObject.idl
layout/xul/nsIPopupBoxObject.idl
layout/xul/nsListBoxObject.cpp
layout/xul/nsMenuBoxObject.cpp
layout/xul/nsPopupBoxObject.cpp
layout/xul/nsScrollBoxObject.cpp
layout/xul/tree/nsTreeBoxObject.cpp
layout/xul/tree/nsTreeBoxObject.h
memory/replace/defs.mk
memory/replace/dmd/test/full-heap-expected1.txt
memory/replace/dmd/test/full-heap-expected2.txt
memory/replace/dmd/test/full-heap-expected3.txt
memory/replace/dmd/test/full-heap-expected4.txt
memory/replace/dmd/test/full-reports-expected1.txt
memory/replace/dmd/test/full-reports-expected2.txt
memory/replace/dmd/test/full-reports-expected3.txt
memory/replace/dmd/test/full-reports-expected4.txt
mobile/android/base/gfx/NinePatchTileLayer.java
mobile/android/base/gfx/SingleTileLayer.java
mobile/android/base/gfx/TextLayer.java
mobile/android/base/resources/drawable-mdpi/bookmarkdefaults_favicon_addons.png
mobile/android/base/resources/drawable-mdpi/bookmarkdefaults_favicon_marketplace.png
mobile/android/base/resources/drawable-mdpi/bookmarkdefaults_favicon_support.png
netwerk/base/public/nsChannelProperties.h
netwerk/base/public/nsIChannelPolicy.idl
netwerk/base/public/nsNetStrings.h
netwerk/base/src/nsNetStrings.cpp
security/manager/ssl/tests/unit/head_psm.js
startupcache/test/TestStartupCache.cpp
testing/mochitest/mochitest_options.py
testing/mochitest/runtests.py
testing/web-platform/meta/media-source/mediasource-config-change-webm-a-bitrate.html.ini
testing/web-platform/meta/media-source/mediasource-config-change-webm-av-audio-bitrate.html.ini
testing/web-platform/meta/media-source/mediasource-config-change-webm-av-video-bitrate.html.ini
toolkit/components/places/tests/queries/test_excludeReadOnlyFolders.js
toolkit/components/telemetry/Histograms.json
toolkit/content/aboutWebrtc.xhtml
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/mozapps/update/tests/chrome/utils.js
toolkit/mozapps/update/tests/shared.js
toolkit/mozapps/update/tests/unit_aus_update/head_update.js
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsUpdateDriver.cpp
toolkit/xre/nsXREDirProvider.cpp
tools/footprint/README.reports
tools/footprint/buster.cgi
tools/footprint/create_dat.awk
tools/footprint/foldelf.cpp
tools/footprint/foldelf.mk
tools/footprint/leak-gauge.html
tools/footprint/leak-gauge.pl
tools/footprint/linear-regression.awk
tools/footprint/linux-gdf.mk
tools/footprint/linux.gnuplot.in
tools/footprint/lists/100.list
tools/footprint/lists/500.list
tools/footprint/lists/static41.list
tools/footprint/thrashview.cpp
tools/footprint/thrashview.mk
tools/footprint/top100.txt
tools/footprint/watch.sh
tools/footprint/win32-gdf.mk
tools/footprint/win32.gnuplot.in
tools/footprint/wm.cpp
tools/jprof/split-profile.pl
tools/page-loader/PageData.pm
tools/page-loader/README.txt
tools/page-loader/RegistryPrefork.pm
tools/page-loader/URLTimingDataSet.pm
tools/page-loader/URLTimingGraph.pm
tools/page-loader/dump.pl
tools/page-loader/echo.pl
tools/page-loader/graph.pl
tools/page-loader/loader.pl
tools/page-loader/report.pl
tools/page-loader/urllist.txt
tools/performance/diff-talos.py
tools/performance/layout/40-url-dup.txt
tools/performance/layout/40-url.txt
tools/performance/layout/Averagetable2.pl
tools/performance/layout/Footer.pl
tools/performance/layout/Header.pl
tools/performance/layout/collect.pl
tools/performance/layout/genfromlogs.pl
tools/performance/layout/history.pl
tools/performance/layout/history.txt
tools/performance/layout/perf-doc.html
tools/performance/layout/perf.pl
tools/performance/layout/property.inc
tools/performance/layout/property.t
tools/performance/layout/readme.txt
tools/performance/layout/tables/013100.html
tools/performance/layout/tables/021300.html
tools/performance/layout/tables/Daily-0317-TrendTable.html
tools/performance/layout/tables/Daily-0317.html
tools/performance/layout/tables/Daily_021700-TrendTable.html
tools/performance/layout/tables/Daily_021700-mozilla.html
tools/performance/layout/tables/Daily_021700.html
tools/performance/layout/tables/Daily_022500.html
tools/performance/layout/tables/Daily_0302.html
tools/performance/layout/tables/Daily_0308-TrendTable.html
tools/performance/layout/tables/Daily_0308.html
tools/performance/layout/tables/Daily_0324.html
tools/performance/layout/tables/M13.html
tools/performance/layout/uncombine.pl
tools/performance/pageload/base/bugzilla.mozilla.org/index.html
tools/performance/pageload/base/bugzilla.mozilla.org/res/mozilla-banner.gif
tools/performance/pageload/base/lxr.mozilla.org/index.html
tools/performance/pageload/base/lxr.mozilla.org/res/mozilla-banner.gif
tools/performance/pageload/base/vanilla-page/index.html
tools/performance/pageload/cycler.html
tools/performance/pageload/header.html
tools/performance/pageload/report.html
tools/performance/pageload/start.html
tools/performance/startup/gettime.pl
tools/performance/startup/quit.html
tools/performance/startup/quit.js
tools/performance/startup/quitForMac.html
tools/performance/startup/startup-test.html
tools/performance/startup/startup-unix.pl
tools/reorder/Makefile
tools/reorder/addrs2text.cpp
tools/reorder/cygprof.c
tools/reorder/elf_symbol_table.cpp
tools/reorder/elf_symbol_table.h
tools/reorder/elf_utils.cpp
tools/reorder/elf_utils.h
tools/reorder/func-by-addr.sh
tools/reorder/garope.cpp
tools/reorder/grope.cpp
tools/reorder/histogram.cpp
tools/reorder/interval_map.h
tools/reorder/mapaddrs.cpp
tools/reorder/mcount.c
tools/reorder/missing-syms.pl
tools/reorder/mult.c
tools/reorder/rseed.c
tools/reorder/syms-by-addr.sh
tools/reorder/test.cpp
tools/test-harness/jssh-driver/data/foo.html
tools/test-harness/jssh-driver/data/foo_inner_html.txt
tools/test-harness/jssh-driver/jssh_driver.py
tools/test-harness/jssh-driver/test_layout_engine.py
tools/tests/ctor-dtor.pl
tools/tests/isa-module.pl
tools/uuiddeps/uuidgrep.bash
widget/xremoteclient/Makefile.in
widget/xremoteclient/XRemoteClientFactory.cpp
widget/xremoteclient/mozilla-xremote-client.cpp
xpcom/build/XPCOMInit.cpp
xpcom/glue/standalone/nsXPCOMGlue.cpp
xpcom/tests/unit/head_xpcom.js
--- a/.hgtags
+++ b/.hgtags
@@ -99,8 +99,9 @@ 2520866d58740851d862c7c59246a4e3f8b4a176
 05025f4889a0bf4dc99ce0c244c750adc002f015 FIREFOX_AURORA_27_BASE
 9f12a9fab080f2d363d7424e25b9ffe85ebc3414 FIREFOX_AURORA_28_BASE
 ba2cc1eda988a1614d8986ae145d28e1268409b9 FIREFOX_AURORA_29_BASE
 83c9853e136451474dfa6d1aaa60a7fca7d2d83a FIREFOX_AURORA_30_BASE
 cfde3603b0206e119abea76fdd6e134b634348f1 FIREFOX_AURORA_31_BASE
 16f3cac5e8fe471e12f76d6a94a477b14e78df7c FIREFOX_AURORA_32_BASE
 dc23164ba2a289a8b22902e30990c77d9677c214 FIREFOX_AURORA_33_BASE
 c360f3d1c00d73b0c1fb0a2c0da525cb55e58b83 FIREFOX_AURORA_34_BASE
+cec1a116c4f9a3e887d52e9a26e8bbec200fe162 FIREFOX_AURORA_35_BASE
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1069071: IPDL changes require CLOBBER (second time around)
+Bug 1061335 - CLOBBER for Win32 compiler update.
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -52,17 +52,17 @@ nsCoreUtils::HasClickListener(nsIContent
     (listenerManager->HasListenersFor(nsGkAtoms::onclick) ||
      listenerManager->HasListenersFor(nsGkAtoms::onmousedown) ||
      listenerManager->HasListenersFor(nsGkAtoms::onmouseup));
 }
 
 void
 nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
                                 int32_t aRowIndex, nsITreeColumn *aColumn,
-                                const nsCString& aPseudoElt)
+                                const nsAString& aPseudoElt)
 {
   nsCOMPtr<nsIDOMElement> tcElm;
   aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
   if (!tcElm)
     return;
 
   nsCOMPtr<nsIContent> tcContent(do_QueryInterface(tcElm));
   nsIDocument *document = tcContent->GetCurrentDoc();
--- a/accessible/base/nsCoreUtils.h
+++ b/accessible/base/nsCoreUtils.h
@@ -39,17 +39,17 @@ public:
    * @param  aTreeBoxObj  [in] tree box object
    * @param  aRowIndex    [in] row index
    * @param  aColumn      [in] column object
    * @param  aPseudoElm   [in] pseudo elemenet inside the cell, see
    *                       nsITreeBoxObject for available values
    */
   static void DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj,
                                  int32_t aRowIndex, nsITreeColumn *aColumn,
-                                 const nsCString& aPseudoElt = EmptyCString());
+                                 const nsAString& aPseudoElt = EmptyString());
 
   /**
    * Send mouse event to the given element.
    *
    * @param aEventType   [in] an event type (see BasicEvents.h for constants)
    * @param aX           [in] x coordinate in dev pixels
    * @param aY           [in] y coordinate in dev pixels
    * @param aContent     [in] the element
@@ -309,9 +309,8 @@ public:
   static bool IsWhitespace(char16_t aChar)
   {
     return aChar == ' ' || aChar == '\n' ||
       aChar == '\r' || aChar == '\t' || aChar == 0xa0;
   }
 };
 
 #endif
-
--- a/accessible/interfaces/nsIAccessiblePivot.idl
+++ b/accessible/interfaces/nsIAccessiblePivot.idl
@@ -186,17 +186,17 @@ interface nsIAccessiblePivot : nsISuppor
    * @param aObserver [in] the observer object to remove from being notified.
    */
   void removeObserver(in nsIAccessiblePivotObserver aObserver);
 };
 
 /**
  * An observer interface for pivot changes.
  */
-[scriptable, uuid(b6508c5e-c081-467d-835c-613eedf9ee9b)]
+[scriptable, uuid(6006e502-3861-49bd-aba1-fa6d2e74e237)]
 interface nsIAccessiblePivotObserver : nsISupports
 {
   /**
    * Called when the pivot changes.
    *
    * @param aPivot           [in] the pivot that has changed.
    * @param aOldAccessible   [in] the old pivot position before the change,
    *                           or null.
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -15,16 +15,18 @@ this.EXPORTED_SYMBOLS = ['AccessFu']; //
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 
 const ACCESSFU_DISABLE = 0; // jshint ignore:line
 const ACCESSFU_ENABLE = 1;
 const ACCESSFU_AUTO = 2;
 
 const SCREENREADER_SETTING = 'accessibility.screenreader';
+const QUICKNAV_MODES_PREF = 'accessibility.accessfu.quicknav_modes';
+const QUICKNAV_INDEX_PREF = 'accessibility.accessfu.quicknav_index';
 
 this.AccessFu = { // jshint ignore:line
   /**
    * Initialize chrome-layer accessibility functionality.
    * If accessibility is enabled on the platform, then a special accessibility
    * mode is started.
    */
   attach: function attach(aWindow) {
@@ -98,21 +100,28 @@ this.AccessFu = { // jshint ignore:line
     let stylesheet = Utils.win.document.createProcessingInstruction(
       'xml-stylesheet', 'href="' + stylesheetURL + '" type="text/css"');
     Utils.win.document.insertBefore(stylesheet, Utils.win.document.firstChild);
     this.stylesheet = Cu.getWeakReference(stylesheet);
 
 
     // Populate quicknav modes
     this._quicknavModesPref =
-      new PrefCache(
-        'accessibility.accessfu.quicknav_modes',
-        (aName, aValue) => {
-          this.Input.quickNavMode.updateModes(aValue);
-        }, true);
+      new PrefCache(QUICKNAV_MODES_PREF, (aName, aValue, aFirstRun) => {
+        this.Input.quickNavMode.updateModes(aValue);
+        if (!aFirstRun) {
+          // If the modes change, reset the current mode index to 0.
+          Services.prefs.setIntPref(QUICKNAV_INDEX_PREF, 0);
+        }
+      }, true);
+
+    this._quicknavCurrentModePref =
+      new PrefCache(QUICKNAV_INDEX_PREF, (aName, aValue) => {
+        this.Input.quickNavMode.updateCurrentMode(Number(aValue));
+      }, true);
 
     // Check for output notification
     this._notifyOutputPref =
       new PrefCache('accessibility.accessfu.notify_output');
 
 
     this.Input.start();
     Output.start();
@@ -662,27 +671,31 @@ var Input = {
           aGesture.touches[0].y);
         break;
       case 'doubletap1':
         this.activateCurrent();
         break;
       case 'taphold1':
         this.sendContextMenuMessage();
         break;
+      case 'doubletaphold1':
+        Utils.dispatchChromeEvent('accessibility-control', 'quicknav-menu');
+        break;
       case 'swiperight1':
         this.moveCursor('moveNext', 'Simple', 'gestures');
         break;
       case 'swipeleft1':
         this.moveCursor('movePrevious', 'Simple', 'gesture');
         break;
       case 'swipeup1':
-        this.contextAction('backward');
+        this.moveCursor(
+          'movePrevious', this.quickNavMode.current, 'gesture', true);
         break;
       case 'swipedown1':
-        this.contextAction('forward');
+        this.moveCursor('moveNext', this.quickNavMode.current, 'gesture', true);
         break;
       case 'exploreend1':
       case 'dwellend1':
         this.activateCurrent(null, true);
         break;
       case 'swiperight2':
         if (aGesture.edge) {
           Utils.dispatchChromeEvent('accessibility-control',
@@ -824,27 +837,22 @@ var Input = {
         {rule: aRule, x: aX, y: aY, origin: 'top'});
     } else {
       let win = Utils.win;
       Utils.winUtils.sendMouseEvent('mousemove',
         aX - win.mozInnerScreenX, aY - win.mozInnerScreenY, 0, 0, 0);
     }
   },
 
-  moveCursor: function moveCursor(aAction, aRule, aInputType) {
+  moveCursor: function moveCursor(aAction, aRule, aInputType, aAdjustRange) {
     let mm = Utils.getMessageManager(Utils.CurrentBrowser);
     mm.sendAsyncMessage('AccessFu:MoveCursor',
-                        {action: aAction, rule: aRule,
-                         origin: 'top', inputType: aInputType});
-  },
-
-  contextAction: function contextAction(aDirection) {
-    // XXX: For now, the only supported context action is adjusting a range.
-    let mm = Utils.getMessageManager(Utils.CurrentBrowser);
-    mm.sendAsyncMessage('AccessFu:AdjustRange', {direction: aDirection});
+                        { action: aAction, rule: aRule,
+                          origin: 'top', inputType: aInputType,
+                          adjustRange: aAdjustRange });
   },
 
   moveByGranularity: function moveByGranularity(aDetails) {
     const MOVEMENT_GRANULARITY_PARAGRAPH = 8;
 
     if (!this.editState.editing) {
       if (aDetails.granularity === MOVEMENT_GRANULARITY_PARAGRAPH) {
         this.moveCursor('move' + aDetails.direction, 'Paragraph', 'gesture');
@@ -952,31 +960,34 @@ var Input = {
   },
 
   quickNavMode: {
     get current() {
       return this.modes[this._currentIndex];
     },
 
     previous: function quickNavMode_previous() {
-      if (--this._currentIndex < 0) {
-        this._currentIndex = this.modes.length - 1;
-      }
+      Services.prefs.setIntPref(QUICKNAV_INDEX_PREF,
+        this._currentIndex > 0 ?
+          this._currentIndex - 1 : this.modes.length - 1);
     },
 
     next: function quickNavMode_next() {
-      if (++this._currentIndex >= this.modes.length) {
-        this._currentIndex = 0;
-      }
+      Services.prefs.setIntPref(QUICKNAV_INDEX_PREF,
+        this._currentIndex + 1 >= this.modes.length ?
+          0 : this._currentIndex + 1);
     },
 
     updateModes: function updateModes(aModes) {
       if (aModes) {
         this.modes = aModes.split(',');
       } else {
         this.modes = [];
       }
     },
 
-    _currentIndex: -1
+    updateCurrentMode: function updateCurrentMode(aModeIndex) {
+      Logger.debug('Quicknav mode:', this.modes[aModeIndex]);
+      this._currentIndex = aModeIndex;
+    }
   }
 };
 AccessFu.Input = Input;
--- a/accessible/jsat/ContentControl.jsm
+++ b/accessible/jsat/ContentControl.jsm
@@ -89,23 +89,28 @@ this.ContentControl.prototype = {
       Logger.logException(
         x, 'Error handling message: ' + JSON.stringify(aMessage.json));
     }
   },
 
   handleMoveCursor: function cc_handleMoveCursor(aMessage) {
     let origin = aMessage.json.origin;
     let action = aMessage.json.action;
+    let adjustRange = aMessage.json.adjustRange;
     let vc = this.vc;
 
     if (origin != 'child' && this.sendToChild(vc, aMessage)) {
       // Forwarded succesfully to child cursor.
       return;
     }
 
+    if (adjustRange && this.adjustRange(vc.position, action === 'moveNext')) {
+      return;
+    }
+
     let moved = vc[action](TraversalRules[aMessage.json.rule]);
 
     if (moved) {
       if (origin === 'child') {
         // We just stepped out of a child, clear child cursor.
         Utils.getMessageManager(aMessage.target).sendAsyncMessage(
           'AccessFu:ClearCursor', {});
       } else {
@@ -117,20 +122,24 @@ this.ContentControl.prototype = {
         } else if (action === 'movePrevious') {
           childAction = 'moveLast';
         }
 
         // Attempt to forward move to a potential child cursor in our
         // new position.
         this.sendToChild(vc, aMessage, { action: childAction }, true);
       }
-    } else if (!this._childMessageSenders.has(aMessage.target)) {
-      // We failed to move, and the message is not from a child, so forward
-      // to parent.
+    } else if (!this._childMessageSenders.has(aMessage.target) &&
+               origin !== 'top') {
+      // We failed to move, and the message is not from a parent, so forward
+      // to it.
       this.sendToParent(aMessage);
+    } else {
+      this._contentScope.get().sendAsyncMessage('AccessFu:Present',
+        Presentation.noMove(action));
     }
   },
 
   handleEvent: function cc_handleEvent(aEvent) {
     if (aEvent.type === 'mousemove') {
       this.handleMoveToPoint(
         { json: { x: aEvent.screenX, y: aEvent.screenY, rule: 'Simple' } });
     }
@@ -164,17 +173,17 @@ this.ContentControl.prototype = {
 
   handleActivate: function cc_handleActivate(aMessage) {
     let activateAccessible = (aAccessible) => {
       Logger.debug(() => {
         return ['activateAccessible', Logger.accessibleToString(aAccessible)];
       });
       try {
         if (aMessage.json.activateIfKey &&
-          aAccessible.role != Roles.KEY) {
+          !Utils.isActivatableOnFingerUp(aAccessible)) {
           // Only activate keys, don't do anything on other objects.
           return;
         }
       } catch (e) {
         // accessible is invalid. Silently fail.
         return;
       }
 
@@ -205,17 +214,17 @@ this.ContentControl.prototype = {
         for (let eventType of ['mousedown', 'mouseup']) {
           let evt = this.document.createEvent('MouseEvents');
           evt.initMouseEvent(eventType, true, true, this.window,
             x, y, 0, 0, 0, false, false, false, false, 0, null);
           node.dispatchEvent(evt);
         }
       }
 
-      if (aAccessible.role !== Roles.KEY) {
+      if (!Utils.isActivatableOnFingerUp(aAccessible)) {
         // Keys will typically have a sound of their own.
         this._contentScope.get().sendAsyncMessage('AccessFu:Present',
           Presentation.actionInvoked(aAccessible, 'click'));
       }
     };
 
     let focusedAcc = Utils.AccRetrieval.getAccessibleFor(
       this.document.activeElement);
@@ -252,16 +261,47 @@ this.ContentControl.prototype = {
 
     let vc = this.vc;
     if (!this.sendToChild(vc, aMessage, null, true)) {
       let position = vc.position;
       activateAccessible(getActivatableDescendant(position) || position);
     }
   },
 
+  adjustRange: function cc_adjustRange(aAccessible, aStepUp) {
+    let acc = Utils.getEmbeddedControl(aAccessible) || aAccessible;
+    try {
+      acc.QueryInterface(Ci.nsIAccessibleValue);
+    } catch (x) {
+      // This is not an adjustable, return false.
+      return false;
+    }
+
+    let elem = acc.DOMNode;
+    if (!elem) {
+      return false;
+    }
+
+    if (elem.tagName === 'INPUT' && elem.type === 'range') {
+      elem[aStepUp ? 'stepDown' : 'stepUp']();
+      let evt = this.document.createEvent('UIEvent');
+      evt.initEvent('change', true, true);
+      elem.dispatchEvent(evt);
+    } else {
+      let evt = this.document.createEvent('KeyboardEvent');
+      let keycode = aStepUp ? content.KeyEvent.DOM_VK_DOWN :
+        content.KeyEvent.DOM_VK_UP;
+      evt.initKeyEvent(
+        "keypress", false, true, null, false, false, false, false, keycode, 0);
+      elem.dispatchEvent(evt);
+    }
+
+    return true;
+  },
+
   handleMoveByGranularity: function cc_handleMoveByGranularity(aMessage) {
     // XXX: Add sendToChild. Right now this is only used in Android, so no need.
     let direction = aMessage.json.direction;
     let granularity;
 
     switch(aMessage.json.granularity) {
       case MOVEMENT_GRANULARITY_CHARACTER:
         granularity = Ci.nsIAccessiblePivot.CHAR_BOUNDARY;
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -56,16 +56,17 @@ this.EventManager.prototype = {
         AccessibilityEventObserver.addListener(this);
 
         this.webProgress.addProgressListener(this,
           (Ci.nsIWebProgress.NOTIFY_STATE_ALL |
            Ci.nsIWebProgress.NOTIFY_LOCATION));
         this.addEventListener('wheel', this, true);
         this.addEventListener('scroll', this, true);
         this.addEventListener('resize', this, true);
+        this._preDialogPosition = new WeakMap();
       }
       this.present(Presentation.tabStateChanged(null, 'newtab'));
 
     } catch (x) {
       Logger.logException(x, 'Failed to start EventManager');
     }
   },
 
@@ -73,16 +74,17 @@ this.EventManager.prototype = {
   // late). It is only called when the AccessFu is disabled explicitly.
   stop: function stop() {
     if (!this._started) {
       return;
     }
     Logger.debug('EventManager.stop');
     AccessibilityEventObserver.removeListener(this);
     try {
+      this._preDialogPosition.clear();
       this.webProgress.removeProgressListener(this);
       this.removeEventListener('wheel', this, true);
       this.removeEventListener('scroll', this, true);
       this.removeEventListener('resize', this, true);
     } catch (x) {
       // contentScope is dead.
     } finally {
       this._started = false;
@@ -267,18 +269,18 @@ this.EventManager.prototype = {
       {
         let position = this.contentControl.vc.position;
         if (aEvent.accessible === aEvent.accessibleDocument ||
             (position && Utils.isInSubtree(position, aEvent.accessible))) {
           // Do not automove into the document if the virtual cursor is already
           // positioned inside it.
           break;
         }
-        this.contentControl.autoMove(
-          aEvent.accessible, { delay: 500 });
+        this._preDialogPosition.set(aEvent.accessible.DOMNode, position);
+        this.contentControl.autoMove(aEvent.accessible, { delay: 500 });
         break;
       }
       case Events.VALUE_CHANGE:
       {
         let position = this.contentControl.vc.position;
         let target = aEvent.accessible;
         if (position === target ||
             Utils.getEmbeddedControl(position) === target) {
@@ -361,17 +363,18 @@ this.EventManager.prototype = {
         return;
       }
       this._queueLiveEvent(Events.HIDE, liveRegion, isPolite);
     } else {
       let vc = Utils.getVirtualCursor(this.contentScope.content.document);
       if (vc.position &&
         (Utils.getState(vc.position).contains(States.DEFUNCT) ||
           Utils.isInSubtree(vc.position, acc))) {
-        let position = aEvent.targetPrevSibling || aEvent.targetParent;
+        let position = this._preDialogPosition.get(aEvent.accessible.DOMNode) ||
+          aEvent.targetPrevSibling || aEvent.targetParent;
         if (!position) {
           try {
             position = acc.previousSibling;
           } catch (x) {
             // Accessible is unattached from the accessible tree.
             position = acc.parent;
           }
         }
--- a/accessible/jsat/Presentation.jsm
+++ b/accessible/jsat/Presentation.jsm
@@ -112,16 +112,21 @@ Presenter.prototype = {
   editingModeChanged: function editingModeChanged(aIsEditing) {}, // jshint ignore:line
 
   /**
    * Announce something. Typically an app state change.
    */
   announce: function announce(aAnnouncement) {}, // jshint ignore:line
 
 
+  /**
+   * User tried to move cursor forward or backward with no success.
+   * @param {string} aMoveMethod move method that was used (eg. 'moveNext').
+   */
+  noMove: function noMove(aMoveMethod) {},
 
   /**
    * Announce a live region.
    * @param  {PivotContext} aContext context object for an accessible.
    * @param  {boolean} aIsPolite A politeness level for a live region.
    * @param  {boolean} aIsHide An indicator of hide/remove event.
    * @param  {string} aModifiedText Optional modified text.
    */
@@ -477,17 +482,17 @@ B2GPresenter.prototype.pivotChanged =
 
     return {
       type: this.type,
       details: {
         eventType: 'vc-change',
         data: UtteranceGenerator.genForContext(aContext),
         options: {
           pattern: this.PIVOT_CHANGE_HAPTIC_PATTERN,
-          isKey: aContext.accessible.role === Roles.KEY,
+          isKey: Utils.isActivatableOnFingerUp(aContext.accessible),
           reason: this.pivotChangedReasons[aReason],
           isUserInput: aIsUserInput
         }
       }
     };
   };
 
 B2GPresenter.prototype.valueChanged =
@@ -531,16 +536,27 @@ B2GPresenter.prototype.announce =
       type: this.type,
       details: {
         eventType: 'announcement',
         data: aAnnouncement
       }
     };
   };
 
+B2GPresenter.prototype.noMove =
+  function B2GPresenter_noMove(aMoveMethod) {
+    return {
+      type: this.type,
+      details: {
+        eventType: 'no-move',
+        data: aMoveMethod
+      }
+    };
+  };
+
 /**
  * A braille presenter
  */
 function BraillePresenter() {}
 
 BraillePresenter.prototype = Object.create(Presenter.prototype);
 
 BraillePresenter.prototype.type = 'Braille';
@@ -631,16 +647,20 @@ this.Presentation = { // jshint ignore:l
 
   announce: function Presentation_announce(aAnnouncement) {
     // XXX: Typically each presenter uses the UtteranceGenerator,
     // but there really isn't a point here.
     return [p.announce(UtteranceGenerator.genForAnnouncement(aAnnouncement)) // jshint ignore:line
       for each (p in this.presenters)]; // jshint ignore:line
   },
 
+  noMove: function Presentation_noMove(aMoveMethod) {
+    return [p.noMove(aMoveMethod) for each (p in this.presenters)]; // jshint ignore:line
+  },
+
   liveRegion: function Presentation_liveRegion(aAccessible, aIsPolite, aIsHide,
     aModifiedText) {
     let context;
     if (!aModifiedText) {
       context = new PivotContext(aAccessible, null, -1, -1, true,
         aIsHide ? true : false);
     }
     return [p.liveRegion(context, aIsPolite, aIsHide, aModifiedText) // jshint ignore:line
--- a/accessible/jsat/TraversalRules.jsm
+++ b/accessible/jsat/TraversalRules.jsm
@@ -29,16 +29,20 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 let gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
 
 function BaseTraversalRule(aRoles, aMatchFunc, aPreFilter) {
   this._explicitMatchRoles = new Set(aRoles);
   this._matchRoles = aRoles;
   if (aRoles.indexOf(Roles.LABEL) < 0) {
     this._matchRoles.push(Roles.LABEL);
   }
+  if (aRoles.indexOf(Roles.INTERNAL_FRAME) < 0) {
+    // Used for traversing in to child OOP frames.
+    this._matchRoles.push(Roles.INTERNAL_FRAME);
+  }
   this._matchFunc = aMatchFunc || function() { return Filters.MATCH; };
   this.preFilter = aPreFilter || gSimplePreFilter;
 }
 
 BaseTraversalRule.prototype = {
     getMatchRoles: function BaseTraversalRule_getmatchRoles(aRules) {
       aRules.value = this._matchRoles;
       return aRules.value.length;
@@ -93,19 +97,17 @@ var gSimpleTraversalRoles =
    Roles.HEADER,
    Roles.HEADING,
    Roles.SLIDER,
    Roles.SPINBUTTON,
    Roles.OPTION,
    Roles.LISTITEM,
    Roles.GRID_CELL,
    Roles.COLUMNHEADER,
-   Roles.ROWHEADER,
-   // Used for traversing in to child OOP frames.
-   Roles.INTERNAL_FRAME];
+   Roles.ROWHEADER];
 
 var gSimpleMatchFunc = function gSimpleMatchFunc(aAccessible) {
   // An object is simple, if it either has a single child lineage,
   // or has a flat subtree.
   function isSingleLineage(acc) {
     for (let child = acc; child; child = child.firstChild) {
       if (Utils.visibleChildCount(child) > 1) {
         return false;
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -465,16 +465,24 @@ this.Utils = { // jshint ignore:line
       // emulator add-on.
       window.dispatchEvent(new window.CustomEvent(aType, {
         bubbles: true,
         cancelable: true,
         detail: details
       }));
     }
 
+  },
+
+  isActivatableOnFingerUp: function isActivatableOnFingerUp(aAccessible) {
+    if (aAccessible.role === Roles.KEY) {
+      return true;
+    }
+    let quick_activate = this.getAttributes(aAccessible)['moz-quick-activate'];
+    return quick_activate && JSON.parse(quick_activate);
   }
 };
 
 /**
  * State object used internally to process accessible's states.
  * @param {Number} aBase     Base state.
  * @param {Number} aExtended Extended state.
  */
@@ -944,17 +952,17 @@ this.PrefCache = function PrefCache(aNam
   this.name = aName;
   this.callback = aCallback;
 
   let branch = Services.prefs;
   this.value = this._getValue(branch);
 
   if (this.callback && aRunCallbackNow) {
     try {
-      this.callback(this.name, this.value);
+      this.callback(this.name, this.value, true);
     } catch (x) {
       Logger.logException(x);
     }
   }
 
   branch.addObserver(aName, this, true);
 };
 
@@ -977,19 +985,20 @@ PrefCache.prototype = {
     } catch (x) {
       // Pref does not exist.
       return null;
     }
   },
 
   observe: function observe(aSubject) {
     this.value = this._getValue(aSubject.QueryInterface(Ci.nsIPrefBranch));
+    Logger.info('pref changed', this.name, this.value);
     if (this.callback) {
       try {
-        this.callback(this.name, this.value);
+        this.callback(this.name, this.value, false);
       } catch (x) {
         Logger.logException(x);
       }
     }
   },
 
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference])
--- a/accessible/jsat/content-script.js
+++ b/accessible/jsat/content-script.js
@@ -87,56 +87,29 @@ function scroll(aMessage) {
   if (!forwardToChild(aMessage, scroll, position)) {
     sendAsyncMessage('AccessFu:DoScroll',
                      { bounds: Utils.getBounds(position, true),
                        page: aMessage.json.page,
                        horizontal: aMessage.json.horizontal });
   }
 }
 
-function adjustRange(aMessage) {
-  function sendUpDownKey(aAccessible) {
-    let acc = Utils.getEmbeddedControl(aAccessible) || aAccessible;
-    let elem = acc.DOMNode;
-    if (elem) {
-      if (elem.tagName === 'INPUT' && elem.type === 'range') {
-        elem[aMessage.json.direction === 'forward' ? 'stepDown' : 'stepUp']();
-        let changeEvent = content.document.createEvent('UIEvent');
-        changeEvent.initEvent('change', true, true);
-        elem.dispatchEvent(changeEvent);
-      } else {
-        let evt = content.document.createEvent('KeyboardEvent');
-        let keycode = aMessage.json.direction == 'forward' ?
-              content.KeyEvent.DOM_VK_DOWN : content.KeyEvent.DOM_VK_UP;
-        evt.initKeyEvent(
-          "keypress", false, true, null, false, false, false, false, keycode, 0);
-        elem.dispatchEvent(evt);
-      }
-    }
-  }
-
-  let position = Utils.getVirtualCursor(content.document).position;
-  if (!forwardToChild(aMessage, adjustRange, position)) {
-    sendUpDownKey(position);
-  }
-}
 addMessageListener(
   'AccessFu:Start',
   function(m) {
     if (m.json.logLevel) {
       Logger.logLevel = Logger[m.json.logLevel];
     }
 
     Logger.debug('AccessFu:Start');
     if (m.json.buildApp)
       Utils.MozBuildApp = m.json.buildApp;
 
     addMessageListener('AccessFu:ContextMenu', activateContextMenu);
     addMessageListener('AccessFu:Scroll', scroll);
-    addMessageListener('AccessFu:AdjustRange', adjustRange);
 
     if (!contentControl) {
       contentControl = new ContentControl(this);
     }
     contentControl.start();
 
     if (!eventManager) {
       eventManager = new EventManager(this, contentControl);
--- a/accessible/tests/mochitest/actions/test_treegrid.xul
+++ b/accessible/tests/mochitest/actions/test_treegrid.xul
@@ -150,18 +150,17 @@
     {
       var treeNode = getNode("tabletree");
       waitForEvent(EVENT_REORDER, treeNode, doTestActions);
       treeNode.view = new nsTreeTreeView();
     }
 
     function test1()
     {
-      var boxObj = getNode("tabletree").treeBoxObject;
-      boxObj.view.setCellValue(0, boxObj.columns.firstColumn, "false");
+      getNode("tabletree").view.setCellValue(0, boxObj.columns.firstColumn, "false");
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
@@ -191,9 +190,8 @@
       </tree>
 
       <vbox id="debug"/>
       <button oncommand="test1();" label="uncheck"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/hittest/test_zoom_tree.xul
+++ b/accessible/tests/mochitest/hittest/test_zoom_tree.xul
@@ -35,26 +35,24 @@
       var treecol1 = tabDocument.getElementById("treecol1");
 
       // tree columns
       hitTest(tree, treecols, treecol1);
 
       // tree rows and cells
       var treeBoxObject = tree.treeBoxObject;
       var treeBodyBoxObj = tree.treeBoxObject.treeBody.boxObject;
-      var xObj = {}, yObj = {}, widthObj = {}, heightObj = {};
-      treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell",
-                                         xObj, yObj, widthObj, heightObj);
+      var rect = treeBoxObject.getCoordsForCellItem(1, tree.columns[0], "cell");
 
       var treeAcc = getAccessible(tree, [nsIAccessibleTable]);
       var cellAcc = treeAcc.getCellAt(1, 0);
       var rowAcc = cellAcc.parent;
 
-      var cssX = xObj.value + treeBodyBoxObj.x;
-      var cssY = yObj.value + treeBodyBoxObj.y;
+      var cssX = rect.x + treeBodyBoxObj.x;
+      var cssY = rect.y + treeBodyBoxObj.y;
       var [x, y] = CSSToDevicePixels(tabWindow, cssX, cssY);
 
       testChildAtPoint(treeAcc, x, y, rowAcc, cellAcc);
       testChildAtPoint(rowAcc, x, y, cellAcc, cellAcc);
 
       // do zoom
       zoomDocument(tabDocument, 1.5);
 
@@ -95,9 +93,8 @@
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/jsat/a11y.ini
+++ b/accessible/tests/mochitest/jsat/a11y.ini
@@ -13,11 +13,12 @@ support-files =
 skip-if = buildapp == 'mulet'
 [test_content_text.html]
 skip-if = buildapp == 'mulet'
 [test_explicit_names.html]
 [test_gesture_tracker.html]
 [test_landmarks.html]
 [test_live_regions.html]
 [test_output.html]
+[test_quicknav_modes.html]
 [test_tables.html]
 [test_pointer_relay.html]
 [test_traversal.html]
--- a/accessible/tests/mochitest/jsat/doc_content_integration.html
+++ b/accessible/tests/mochitest/jsat/doc_content_integration.html
@@ -70,19 +70,19 @@
 
   </style>
 
 </head>
 <body>
   <div>Phone status bar</div>
   <div id="windows">
     <button id="back">Back</button>
-    <div id="appframe"></div>
     <div role="dialog" id="alert" hidden>
       <h1>This is an alert!</h1>
       <p>Do you agree?</p>
-      <button onclick="hideAlert()">Yes</button>
+      <button onclick="setTimeout(hideAlert, 500)">Yes</button>
       <button onclick="hideAlert()">No</button>
     </div>
+    <div id="appframe"></div>
   </div>
   <button id="home">Home</button>
 </body>
 </html>
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -130,17 +130,17 @@ var AccessFuTest = {
     } catch (ex) {
       // StopIteration exception.
       this.finish();
       return;
     }
     testFunc();
   },
 
-  runTests: function AccessFuTest_runTests() {
+  runTests: function AccessFuTest_runTests(aAdditionalPrefs) {
     if (gTestFuncs.length === 0) {
       ok(false, "No tests specified!");
       SimpleTest.finish();
       return;
     }
 
     // Create an Iterator for gTestFuncs array.
     gIterator = Iterator(gTestFuncs); // jshint ignore:line
@@ -151,20 +151,21 @@ var AccessFuTest = {
     AccessFu.attach(getMainChromeWindow(window));
 
     AccessFu.readyCallback = function readyCallback() {
       // Enable logging to the console service.
       Logger.test = true;
       Logger.logLevel = Logger.DEBUG;
     };
 
-    SpecialPowers.pushPrefEnv({
-      'set': [['accessibility.accessfu.notify_output', 1],
-              ['dom.mozSettings.enabled', true]]
-    }, function () {
+    var prefs = [['accessibility.accessfu.notify_output', 1],
+      ['dom.mozSettings.enabled', true]];
+    prefs.push.apply(prefs, aAdditionalPrefs);
+
+    SpecialPowers.pushPrefEnv({ 'set': prefs }, function () {
       if (AccessFuTest._waitForExplicitFinish) {
         // Run all test functions asynchronously.
         AccessFuTest.nextTest();
       } else {
         // Run all test functions synchronously.
         [testFunc() for (testFunc of gTestFuncs)]; // jshint ignore:line
         AccessFuTest.finish();
       }
@@ -359,29 +360,39 @@ var ContentMessages = {
 
   clearCursor: {
     name: 'AccessFu:ClearCursor',
     json: {
       origin: 'top'
     }
   },
 
-  adjustRangeUp: {
-    name: 'AccessFu:AdjustRange',
-    json: {
-      origin: 'top',
-      direction: 'backward'
+  moveOrAdjustUp: function moveOrAdjustUp(aRule) {
+    return {
+      name: 'AccessFu:MoveCursor',
+      json: {
+        origin: 'top',
+        action: 'movePrevious',
+        inputType: 'gesture',
+        rule: (aRule || 'Simple'),
+        adjustRange: true
+      }
     }
   },
 
-  adjustRangeDown: {
-    name: 'AccessFu:AdjustRange',
-    json: {
-      origin: 'top',
-      direction: 'forward'
+  moveOrAdjustDown: function moveOrAdjustUp(aRule) {
+    return {
+      name: 'AccessFu:MoveCursor',
+      json: {
+        origin: 'top',
+        action: 'moveNext',
+        inputType: 'gesture',
+        rule: (aRule || 'Simple'),
+        adjustRange: true
+      }
     }
   },
 
   focusSelector: function focusSelector(aSelector, aBlur) {
     return {
       name: 'AccessFuTest:Focus',
       json: {
         selector: aSelector,
@@ -649,16 +660,22 @@ function ExpectedAnnouncement(aAnnouncem
     eventType: AndroidEvent.ANNOUNCEMENT,
     text: [ aAnnouncement],
     addedCount: aAnnouncement.length
   }], aOptions);
 }
 
 ExpectedAnnouncement.prototype = Object.create(ExpectedPresent.prototype);
 
+function ExpectedNoMove(aOptions) {
+  ExpectedPresent.call(this, {eventType: 'no-move' }, null, aOptions);
+}
+
+ExpectedNoMove.prototype = Object.create(ExpectedPresent.prototype);
+
 var AndroidEvent = {
   VIEW_CLICKED: 0x01,
   VIEW_LONG_CLICKED: 0x02,
   VIEW_SELECTED: 0x04,
   VIEW_FOCUSED: 0x08,
   VIEW_TEXT_CHANGED: 0x10,
   WINDOW_STATE_CHANGED: 0x20,
   VIEW_HOVER_ENTER: 0x80,
--- a/accessible/tests/mochitest/jsat/test_content_integration.html
+++ b/accessible/tests/mochitest/jsat/test_content_integration.html
@@ -29,16 +29,17 @@
       iframe.addEventListener('mozbrowserloadend', function () {
       var contentTest = new AccessFuContentTest(
         [
           // Simple traversal forward
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(
             ['Phone status bar', 'Traversal Rule test document'],
             { focused: 'body' })],
+          [ContentMessages.simpleMovePrevious, new ExpectedNoMove()],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
           [ContentMessages.simpleMoveNext, new ExpectedCursorChange(
             ['wow', {'string': 'headingLevel', 'args': [1]} ,'such app'],
             { focused: 'iframe' })],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['many option', {'string': 'stateNotChecked'},
             {'string': 'checkbutton'}, {'string': 'listStart'},
@@ -47,24 +48,24 @@
           // check checkbox
           [ContentMessages.activateCurrent(),
            new ExpectedClickAction({ no_android: true }),
            new ExpectedCheckAction(true, { android_todo: true })],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['much range', {'string': 'label'}])],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['much range', '5', {'string': 'slider'}])],
-          [ContentMessages.adjustRangeUp, new ExpectedValueChange('6')],
+          [ContentMessages.moveOrAdjustUp(), new ExpectedValueChange('6')],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
 
           // Simple traversal backward
           [ContentMessages.simpleMovePrevious,
            new ExpectedCursorChange(['much range', '6', {'string': 'slider'}, 'such app'])],
-          [ContentMessages.adjustRangeDown, new ExpectedValueChange('5')],
+          [ContentMessages.moveOrAdjustDown(), new ExpectedValueChange('5')],
           [ContentMessages.simpleMovePrevious,
            new ExpectedCursorChange(['much range', {'string': 'label'}])],
           [ContentMessages.simpleMovePrevious,
            new ExpectedCursorChange(['many option', {'string': 'stateChecked'},
             {'string': 'checkbutton'}, {'string': 'listStart'},
             {'string': 'list'}, {'string': 'listItemsCount', 'count': 1}])],
           // uncheck checkbox
           [ContentMessages.activateCurrent(),
@@ -86,16 +87,42 @@
             ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
           // Move from an inner frame to the last element in the parent doc
           [ContentMessages.simpleMoveLast,
             new ExpectedCursorChange(
               ['Home', {'string': 'pushbutton'}], { b2g_todo: true })],
 
           [ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
 
+          [ContentMessages.simpleMoveNext,
+           new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
+          [ContentMessages.moveOrAdjustDown('FormElement'),
+           new ExpectedCursorChange(['Back', {"string": "pushbutton"}])],
+          [ContentMessages.moveOrAdjustDown('FormElement'),
+           new ExpectedCursorChange(['many option', {'string': 'stateNotChecked'},
+            {'string': 'checkbutton'}, {'string': 'listStart'},
+            {'string': 'list'}, {'string': 'listItemsCount', 'count': 1}, 'such app'])],
+          [ContentMessages.moveOrAdjustDown('FormElement'),
+           new ExpectedCursorChange(['much range', '5', {'string': 'slider'}])],
+          // Calling AdjustOrMove should adjust the range.
+          [ContentMessages.moveOrAdjustDown('FormElement'),
+           new ExpectedValueChange('4')],
+          [ContentMessages.moveOrAdjustUp('FormElement'),
+           new ExpectedValueChange('5')],
+          [ContentMessages.simpleMovePrevious,
+           new ExpectedCursorChange(['much range', {'string': 'label'}])],
+          [ContentMessages.moveOrAdjustUp('FormElement'),
+           new ExpectedCursorChange(['many option', {'string': 'stateNotChecked'},
+            {'string': 'checkbutton'}, {'string': 'listStart'},
+            {'string': 'list'}, {'string': 'listItemsCount', 'count': 1}])],
+          [ContentMessages.moveOrAdjustUp('FormElement'),
+           new ExpectedCursorChange(['Back', {"string": "pushbutton"}])],
+
+          [ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
+
           // Moving to the absolute first item from an embedded document
           // fails. Bug 972035.
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
@@ -174,60 +201,64 @@
             // Must not speak Back button as it is aria-hidden
            new ExpectedCursorChange(
              ["wow", {"string": "headingLevel","args": [1]}, "such app"])],
           [doc.defaultView.ariaShowBack],
           [ContentMessages.focusSelector('button#back', true), null],
           [ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
 
           // Open dialog in outer doc, while cursor is also in outer doc
-          [ContentMessages.simpleMoveNext,
-           new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
+          [ContentMessages.simpleMoveLast,
+           new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
           [doc.defaultView.showAlert,
             new ExpectedCursorChange(['This is an alert!',
               {'string': 'headingLevel', 'args': [1]},
               {'string': 'dialog'}])],
 
           [doc.defaultView.hideAlert,
-           new ExpectedCursorChange(["wow",
-            {"string": "headingLevel", "args": [1]}, "such app"])],
+           new ExpectedCursorChange(['Home', {'string': 'pushbutton'}])],
 
           [ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
 
           // Open dialog in outer doc, while cursor is in inner frame
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(["Back", {"string": "pushbutton"}])],
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(
             ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
           [doc.defaultView.showAlert, new ExpectedCursorChange(['This is an alert!',
                     {'string': 'headingLevel', 'args': [1]},
                     {'string': 'dialog'}])],
 
-          // XXX: Place cursor back where it was.
-          [doc.defaultView.hideAlert,
+          [ContentMessages.simpleMoveNext,
+            new ExpectedCursorChange(['Do you agree?'])],
+          [ContentMessages.simpleMoveNext,
+            new ExpectedCursorChange(['Yes', {'string': 'pushbutton'}])],
+          [ContentMessages.activateCurrent(),
+           new ExpectedClickAction(),
            new ExpectedCursorChange(
             ['wow', {'string': 'headingLevel', 'args': [1]}, 'such app'])],
 
           [ContentMessages.clearCursor, 'AccessFu:CursorCleared'],
 
           // Open dialog, then focus on something when closing
           [ContentMessages.simpleMoveNext,
            new ExpectedCursorChange(['Phone status bar', 'Traversal Rule test document'])],
           [doc.defaultView.showAlert,
            new ExpectedCursorChange(['This is an alert!',
             {'string': 'headingLevel', 'args': [1]}, {'string': 'dialog'}])],
 
           [function hideAlertAndFocusHomeButton() {
             doc.defaultView.hideAlert();
             doc.querySelector('button#home').focus();
           }, new ExpectedCursorChange(['Home', {'string': 'pushbutton'},
-            'Traversal Rule test document'])]
+            'Traversal Rule test document'])],
+          [ContentMessages.simpleMoveNext, new ExpectedNoMove()]
         ]);
 
         addA11yLoadEvent(function() {
           contentTest.start(function () {
             closeBrowserWindow();
             SimpleTest.finish();
           });
         }, doc.defaultView)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/jsat/test_quicknav_modes.html
@@ -0,0 +1,103 @@
+<html>
+
+<head>
+  <title>AccessFu test for enabling</title>
+
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="./jsatcommon.js"></script>
+  <script type="application/javascript">
+
+    function prefStart() {
+      // Start AccessFu via pref.
+      SpecialPowers.setIntPref("accessibility.accessfu.activate", 1);
+      AccessFuTest.once_log("EventManager.start", AccessFuTest.nextTest);
+    }
+
+    function nextMode(aCurrentMode, aNextMode) {
+      return function() {
+        is(AccessFu.Input.quickNavMode.current, aCurrentMode,
+          'initial current mode is correct');
+        AccessFu.Input.quickNavMode.next();
+        _expectMode(aNextMode, AccessFuTest.nextTest);
+      }
+    }
+
+    function prevMode(aCurrentMode, aNextMode) {
+      return function() {
+        is(AccessFu.Input.quickNavMode.current, aCurrentMode,
+          'initial current mode is correct');
+        AccessFu.Input.quickNavMode.previous();
+        _expectMode(aNextMode, AccessFuTest.nextTest);
+      }
+    }
+
+    function setMode(aModeIndex, aExpectedMode) {
+      return function() {
+        SpecialPowers.setIntPref(
+          'accessibility.accessfu.quicknav_index', aModeIndex);
+        _expectMode(aExpectedMode, AccessFuTest.nextTest);
+      }
+    }
+
+    function reconfigureModes() {
+      SpecialPowers.setCharPref('accessibility.accessfu.quicknav_modes',
+        'Landmark,Button,Entry,Graphic');
+      // When the modes are reconfigured, the current mode should
+      // be set to the first in the new list.
+      _expectMode('Landmark', AccessFuTest.nextTest);
+    }
+
+    function _expectMode(aExpectedMode, aCallback) {
+      if (AccessFu.Input.quickNavMode.current === aExpectedMode) {
+        ok(true, 'correct mode');
+        aCallback();
+      } else {
+        AccessFuTest.once_log('Quicknav mode: ' + aExpectedMode, function() {
+          ok(true, 'correct mode');
+          aCallback();
+        });
+      }
+    }
+
+    // Listen for initial 'EventManager.start' and disable AccessFu.
+    function prefStop() {
+      ok(AccessFu._enabled, "AccessFu was started via preference.");
+      AccessFuTest.once_log("EventManager.stop", AccessFuTest.finish);
+      SpecialPowers.setIntPref("accessibility.accessfu.activate", 0);
+    }
+
+    function doTest() {
+      AccessFuTest.addFunc(prefStart);
+      AccessFuTest.addFunc(nextMode('Link', 'Heading'));
+      AccessFuTest.addFunc(nextMode('Heading', 'FormElement'));
+      AccessFuTest.addFunc(nextMode('FormElement', 'Link'));
+      AccessFuTest.addFunc(nextMode('Link', 'Heading'));
+      AccessFuTest.addFunc(prevMode('Heading', 'Link'));
+      AccessFuTest.addFunc(prevMode('Link', 'FormElement'));
+      AccessFuTest.addFunc(setMode(1, 'Heading'));
+      AccessFuTest.addFunc(reconfigureModes);
+      AccessFuTest.addFunc(prefStop);
+      AccessFuTest.waitForExplicitFinish();
+      AccessFuTest.runTests([   // Will call SimpleTest.finish();
+        ['accessibility.accessfu.quicknav_modes', 'Link,Heading,FormElement']]);
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+
+</head>
+<body>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=811307"
+     title="[AccessFu] Add mochitest for enabling">
+    Mozilla Bug 811307
+  </a>
+</body>
+</html>
\ No newline at end of file
--- a/accessible/tests/mochitest/name/test_tree.xul
+++ b/accessible/tests/mochitest/name/test_tree.xul
@@ -27,17 +27,17 @@
   <script type="application/javascript">
   <![CDATA[
     function treeTester(aID)
     {
       this.DOMNode = getNode(aID);
 
       this.invoke = function treeTester_invoke()
       {
-        this.DOMNode.treeBoxObject.view = new nsTreeTreeView();
+        this.DOMNode.view = new nsTreeTreeView();
       }
 
       this.check = function treeTester_check(aEvent)
       {
         var tree = {
           role: ROLE_OUTLINE,
           children: [
             {
@@ -85,17 +85,17 @@
     }
 
     function tableTester(aID, aIsTable, aCol1ID, aCol2ID)
     {
       this.DOMNode = getNode(aID);
 
       this.invoke = function tableTester_invoke()
       {
-        this.DOMNode.treeBoxObject.view = new nsTableTreeView(2);
+        this.DOMNode.view = new nsTableTreeView(2);
       }
 
       this.check = function tableTester_check(aEvent)
       {
         var tree = {
           role: aIsTable ? ROLE_TABLE : ROLE_TREE_TABLE,
           children: [
             {
@@ -204,9 +204,8 @@
       <treecol id="tt_col2" flex="1" label="column 2"/>
     </treecols>
     <treechildren/>
   </tree>
 
   </vbox> <!-- close tests area -->
   </hbox> <!-- close main area -->
 </window>
-
--- a/accessible/tests/mochitest/selectable/test_tree.xul
+++ b/accessible/tests/mochitest/selectable/test_tree.xul
@@ -37,17 +37,17 @@
      * accessible.
      */
     function statesChecker(aTreeID, aView)
     {
       this.DOMNode = getNode(aTreeID);
       
       this.invoke = function invoke()
       {
-        this.DOMNode.treeBoxObject.view = aView;
+        this.DOMNode.view = aView;
       }
       this.check = function check()
       {
         var tree = getAccessible(this.DOMNode);
 
         var isTreeMultiSelectable = false;
         var seltype = this.DOMNode.getAttribute("seltype");
         if (seltype != "single" && seltype != "cell" && seltype != "text")
@@ -181,9 +181,8 @@
         <treechildren/>
       </tree>
 
       <vbox id="debug"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/states/test_tree.xul
+++ b/accessible/tests/mochitest/states/test_tree.xul
@@ -33,17 +33,17 @@
      * accessible.
      */
     function statesChecker(aTreeID, aView)
     {
       this.DOMNode = getNode(aTreeID);
 
       this.invoke = function statesChecker_invoke()
       {
-        this.DOMNode.treeBoxObject.view = aView;
+        this.DOMNode.view = aView;
       }
 
       this.check = function statesChecker_check()
       {
         var tree = getAccessible(this.DOMNode);
 
         // tree states
         testStates(tree, STATE_READONLY);
@@ -145,9 +145,8 @@
         <treechildren/>
       </tree>
 
       <vbox id="debug"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/tree/test_tree.xul
+++ b/accessible/tests/mochitest/tree/test_tree.xul
@@ -67,17 +67,17 @@
       var accTreeForTree = {
         role: aRole,
         children: [
           accTreeForColumns
         ]
       };
 
       var treeBoxObject = aTree.treeBoxObject;
-      var view = treeBoxObject.view;
+      var view = aTree.view;
       var columnCount = treeBoxObject.columns.count;
 
       for (var idx = 0; idx < columnCount; idx++)
         accTreeForColumns.children.push({ COLUMNHEADER: [ ] });
       if (!aTree.hasAttribute("hidecolumnpicker"))
         accTreeForColumns.children.push({ PUSHBUTTON: [ { MENUPOPUP: [] } ] });
 
       for (var idx = 0; idx < view.rowCount; idx++)
@@ -90,17 +90,17 @@
      * Event queue invoker object to test accessible tree for XUL tree element.
      */
     function treeChecker(aID, aView, aRole)
     {
       this.DOMNode = getNode(aID);
 
       this.invoke = function invoke()
       {
-        this.DOMNode.treeBoxObject.view = aView;
+        this.DOMNode.view = aView;
       }
       this.check = function check(aEvent)
       {
         testAccessibleTreeFor(this.DOMNode, aRole);
       }
       this.getID = function getID()
       {
         return "Tree testing of " + aID;
@@ -175,9 +175,8 @@
         <treechildren/>
       </tree>
 
       <vbox id="debug"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/treeview.js
+++ b/accessible/tests/mochitest/treeview.js
@@ -12,17 +12,17 @@ function loadXULTreeAndDoTest(aDoTestFun
     this.treeNode = getNode(aTreeID);
 
     this.eventSeq = [
       new invokerChecker(EVENT_REORDER, this.treeNode)
     ];
 
     this.invoke = function loadXULTree_invoke()
     {
-      this.treeNode.treeBoxObject.view = aTreeView;
+      this.treeNode.view = aTreeView;
     }
 
     this.getID = function loadXULTree_getID()
     {
       return "Load XUL tree " + prettyName(aTreeID);
     }
   }
 
--- a/accessible/xul/XULTreeAccessible.cpp
+++ b/accessible/xul/XULTreeAccessible.cpp
@@ -194,17 +194,17 @@ XULTreeAccessible::ChildAtPoint(int32_t 
 
   nsIntRect rootRect = rootFrame->GetScreenRect();
 
   int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
   int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
 
   int32_t row = -1;
   nsCOMPtr<nsITreeColumn> column;
-  nsAutoCString childEltUnused;
+  nsAutoString childEltUnused;
   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
                    childEltUnused);
 
   // If we failed to find tree cell for the given point then it might be
   // tree columns.
   if (row == -1 || !column)
     return AccessibleWrap::ChildAtPoint(aX, aY, aWhichChild);
 
@@ -741,17 +741,17 @@ XULTreeItemAccessibleBase::Bounds() cons
 
   nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
   if (!boxObj)
     return nsIntRect();
 
   nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
 
   int32_t x = 0, y = 0, width = 0, height = 0;
-  nsresult rv = mTree->GetCoordsForCellItem(mRow, column, EmptyCString(),
+  nsresult rv = mTree->GetCoordsForCellItem(mRow, column, EmptyString(),
                                             &x, &y, &width, &height);
   if (NS_FAILED(rv))
     return nsIntRect();
 
   boxObj->GetWidth(&width);
 
   int32_t tcX = 0, tcY = 0;
   boxObj->GetScreenX(&tcX);
@@ -991,25 +991,25 @@ XULTreeItemAccessibleBase::DispatchClick
 
   nsCOMPtr<nsITreeColumns> columns;
   mTree->GetColumns(getter_AddRefs(columns));
   if (!columns)
     return;
 
   // Get column and pseudo element.
   nsCOMPtr<nsITreeColumn> column;
-  nsAutoCString pseudoElm;
+  nsAutoString pseudoElm;
 
   if (aActionIndex == eAction_Click) {
     // Key column is visible and clickable.
     columns->GetKeyColumn(getter_AddRefs(column));
   } else {
     // Primary column contains a twisty we should click on.
     columns->GetPrimaryColumn(getter_AddRefs(column));
-    pseudoElm = NS_LITERAL_CSTRING("twisty");
+    pseudoElm = NS_LITERAL_STRING("twisty");
   }
 
   if (column)
     nsCoreUtils::DispatchClickEvent(mTree, mRow, column, pseudoElm);
 }
 
 Accessible*
 XULTreeItemAccessibleBase::GetSiblingAtOffset(int32_t aOffset,
@@ -1191,9 +1191,8 @@ XULTreeColumAccessible::GetSiblingAtOffs
         if (treeAcc)
           return treeAcc->GetTreeItemAccessible(aOffset - 1);
       }
     }
   }
 
   return nullptr;
 }
-
--- a/accessible/xul/XULTreeGridAccessible.cpp
+++ b/accessible/xul/XULTreeGridAccessible.cpp
@@ -336,17 +336,17 @@ XULTreeGridRowAccessible::ChildAtPoint(i
 
   nsIntRect rootRect = rootFrame->GetScreenRect();
 
   int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
   int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
 
   int32_t row = -1;
   nsCOMPtr<nsITreeColumn> column;
-  nsAutoCString childEltUnused;
+  nsAutoString childEltUnused;
   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
                    childEltUnused);
 
   // Return if we failed to find tree cell in the row for the given point.
   if (row != mRow || !column)
     return nullptr;
 
   return GetCellAccessible(column);
@@ -517,17 +517,17 @@ XULTreeGridCellAccessible::Bounds() cons
   // Get bounds for tree cell and add x and y of treechildren element to
   // x and y of the cell.
   nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
   if (!boxObj)
     return nsIntRect();
 
   int32_t x = 0, y = 0, width = 0, height = 0;
   nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn,
-                                            NS_LITERAL_CSTRING("cell"),
+                                            NS_LITERAL_STRING("cell"),
                                             &x, &y, &width, &height);
   if (NS_FAILED(rv))
     return nsIntRect();
 
   int32_t tcX = 0, tcY = 0;
   boxObj->GetScreenX(&tcX);
   boxObj->GetScreenY(&tcY);
   x += tcX;
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -3,17 +3,16 @@ dnl Local autoconf macros used with mozi
 dnl The contents of this file are under the Public Domain.
 dnl
 
 builtin(include, build/autoconf/hotfixes.m4)dnl
 builtin(include, build/autoconf/acwinpaths.m4)dnl
 builtin(include, build/autoconf/hooks.m4)dnl
 builtin(include, build/autoconf/config.status.m4)dnl
 builtin(include, build/autoconf/toolchain.m4)dnl
-builtin(include, build/autoconf/ccache.m4)dnl
 builtin(include, build/autoconf/wrapper.m4)dnl
 builtin(include, build/autoconf/nspr.m4)dnl
 builtin(include, build/autoconf/nspr-build.m4)dnl
 builtin(include, build/autoconf/nss.m4)dnl
 builtin(include, build/autoconf/pkg.m4)dnl
 builtin(include, build/autoconf/codeset.m4)dnl
 builtin(include, build/autoconf/altoptions.m4)dnl
 builtin(include, build/autoconf/mozprog.m4)dnl
--- a/addon-sdk/source/test/jetpack-package.ini
+++ b/addon-sdk/source/test/jetpack-package.ini
@@ -1,16 +1,16 @@
 [DEFAULT]
 support-files =
   buffers/**
   commonjs-test-adapter/**
   event/**
   fixtures/**
   loader/**
-  libs/**
+  lib/**
   modules/**
   private-browsing/**
   sidebar/**
   tabs/**
   traits/**
   windows/**
   zip/**
   fixtures.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -76,16 +76,17 @@ pref("network.http.max-connections", 20)
 pref("network.http.max-persistent-connections-per-server", 6);
 pref("network.http.max-persistent-connections-per-proxy", 20);
 
 // Keep the old default of accepting all cookies,
 // no matter if you already visited the website or not
 pref("network.cookie.cookieBehavior", 0);
 
 // spdy
+pref("network.http.spdy.enabled.http2draft", false);
 pref("network.http.spdy.push-allowance", 32768);
 
 // See bug 545869 for details on why these are set the way they are
 pref("network.buffer.cache.count", 24);
 pref("network.buffer.cache.size",  16384);
 
 // predictive actions
 pref("network.predictor.enable", false); // disabled on b2g
@@ -782,19 +783,24 @@ pref("dom.ipc.reuse_parent_app", false);
 // When a process receives a system message, we hold a CPU wake lock on its
 // behalf for this many seconds, or until it handles the system message,
 // whichever comes first.
 pref("dom.ipc.systemMessageCPULockTimeoutSec", 30);
 
 // Ignore the "dialog=1" feature in window.open.
 pref("dom.disable_window_open_dialog_feature", true);
 
+// Enable before keyboard events and after keyboard events.
+pref("dom.beforeAfterKeyboardEvent.enabled", true);
+
 // Screen reader support
 pref("accessibility.accessfu.activate", 2);
 pref("accessibility.accessfu.quicknav_modes", "Link,Heading,FormElement,Landmark,ListItem");
+// Active quicknav mode, index value of list from quicknav_modes
+pref("accessibility.accessfu.quicknav_index", 0);
 // Setting for an utterance order (0 - description first, 1 - description last).
 pref("accessibility.accessfu.utterance", 1);
 // Whether to skip images with empty alt text
 pref("accessibility.accessfu.skip_empty_images", true);
 
 // Enable hit-target fluffing
 pref("ui.touch.radius.enabled", true);
 pref("ui.touch.radius.leftmm", 3);
@@ -867,16 +873,18 @@ pref("webgl.can-lose-context-in-foregrou
 pref("memory_info_dumper.watch_fifo.enabled", true);
 pref("memory_info_dumper.watch_fifo.directory", "/data/local");
 
 // See ua-update.json.in for the packaged UA override list
 pref("general.useragent.updates.enabled", true);
 pref("general.useragent.updates.url", "https://dynamicua.cdn.mozilla.net/0/%APP_ID%");
 pref("general.useragent.updates.interval", 604800); // 1 week
 pref("general.useragent.updates.retry", 86400); // 1 day
+// Device ID can be composed of letter, numbers, hyphen ("-") and dot (".")
+pref("general.useragent.device_id", "");
 
 // Make <audio> and <video> talk to the AudioChannelService.
 pref("media.useAudioChannelService", true);
 
 pref("b2g.version", @MOZ_B2G_VERSION@);
 pref("b2g.osName", @MOZ_B2G_OS_NAME@);
 
 // Disable console buffering to save memory.
--- a/b2g/chrome/content/content.css
+++ b/b2g/chrome/content/content.css
@@ -173,18 +173,16 @@ input[type="submit"],
 input[type="reset"],
 button {
   border-width: 1px;
   padding: 0 7px 0 7px;
 }
 
 input[type="radio"],
 input[type="checkbox"] {
-  max-width: 14px;
-  max-height: 14px;
   border: 1px solid #a7a7a7 !important;
   padding: 2px 1px 2px 1px;
 }
 
 select > button {
   border-width: 0px !important;
   margin: 0px !important;
   padding: 0px !important;
--- a/b2g/chrome/content/devtools/adb.js
+++ b/b2g/chrome/content/devtools/adb.js
@@ -3,50 +3,46 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 // This file is only loaded on Gonk to manage ADB state
 
+const { utils: Cu } = Components;
+
+const DEBUG = false;
+var debug = function(str) {
+  dump("AdbController: " + str + "\n");
+}
+
 let AdbController = {
-  DEBUG: false,
   locked: undefined,
   remoteDebuggerEnabled: undefined,
   lockEnabled: undefined,
   disableAdbTimer: null,
   disableAdbTimeoutHours: 12,
   umsActive: false,
 
-  debug: function(str) {
-    dump("AdbController: " + str + "\n");
-  },
-
   setLockscreenEnabled: function(value) {
     this.lockEnabled = value;
-    if (this.DEBUG) {
-      this.debug("setLockscreenEnabled = " + this.lockEnabled);
-    }
+    DEBUG && debug("setLockscreenEnabled = " + this.lockEnabled);
     this.updateState();
   },
 
   setLockscreenState: function(value) {
     this.locked = value;
-    if (this.DEBUG) {
-      this.debug("setLockscreenState = " + this.locked);
-    }
+    DEBUG && debug("setLockscreenState = " + this.locked);
     this.updateState();
   },
 
   setRemoteDebuggerState: function(value) {
     this.remoteDebuggerEnabled = value;
-    if (this.DEBUG) {
-      this.debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled);
-    }
+    DEBUG && debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled);
     this.updateState();
   },
 
   startDisableAdbTimer: function() {
     if (this.disableAdbTimer) {
       this.disableAdbTimer.cancel();
     } else {
       this.disableAdbTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
@@ -54,48 +50,42 @@ let AdbController = {
         this.disableAdbTimeoutHours =
           Services.prefs.getIntPref("b2g.adb.timeout-hours");
       } catch (e) {
         // This happens if the pref doesn't exist, in which case
         // disableAdbTimeoutHours will still be set to the default.
       }
     }
     if (this.disableAdbTimeoutHours <= 0) {
-      if (this.DEBUG) {
-        this.debug("Timer to disable ADB not started due to zero timeout");
-      }
+      DEBUG && debug("Timer to disable ADB not started due to zero timeout");
       return;
     }
 
-    if (this.DEBUG) {
-      this.debug("Starting timer to disable ADB in " +
-                 this.disableAdbTimeoutHours + " hours");
-    }
+    DEBUG && debug("Starting timer to disable ADB in " +
+                   this.disableAdbTimeoutHours + " hours");
     let timeoutMilliseconds = this.disableAdbTimeoutHours * 60 * 60 * 1000;
     this.disableAdbTimer.initWithCallback(this, timeoutMilliseconds,
                                           Ci.nsITimer.TYPE_ONE_SHOT);
   },
 
   stopDisableAdbTimer: function() {
-    if (this.DEBUG) {
-      this.debug("Stopping timer to disable ADB");
-    }
+    DEBUG && debug("Stopping timer to disable ADB");
     if (this.disableAdbTimer) {
       this.disableAdbTimer.cancel();
       this.disableAdbTimer = null;
     }
   },
 
   notify: function(aTimer) {
     if (aTimer == this.disableAdbTimer) {
       this.disableAdbTimer = null;
       // The following dump will be the last thing that shows up in logcat,
       // and will at least give the user a clue about why logcat was
       // disconnected, if the user happens to be using logcat.
-      dump("AdbController: ADB timer expired - disabling ADB\n");
+      debug("ADB timer expired - disabling ADB\n");
       navigator.mozSettings.createLock().set(
         {'debugger.remote-mode': 'disabled'});
     }
   },
 
   updateState: function() {
     this.umsActive = false;
     this.storages = navigator.getDeviceStorages('sdcard');
@@ -105,47 +95,40 @@ let AdbController = {
   updateStorageState: function(storageIndex) {
     if (storageIndex >= this.storages.length) {
       // We've iterated through all of the storage objects, now we can
       // really do updateStateInternal.
       this.updateStateInternal();
       return;
     }
     let storage = this.storages[storageIndex];
-    if (this.DEBUG) {
-      this.debug("Checking availability of storage: '" +
-                 storage.storageName);
-    }
+    DEBUG && debug("Checking availability of storage: '" + storage.storageName);
 
     let req = storage.available();
     req.onsuccess = function(e) {
-      if (this.DEBUG) {
-        this.debug("Storage: '" + storage.storageName + "' is '" +
-                   e.target.result);
-      }
+      DEBUG && debug("Storage: '" + storage.storageName + "' is '" + e.target.result);
       if (e.target.result == 'shared') {
         // We've found a storage area that's being shared with the PC.
         // We can stop looking now.
         this.umsActive = true;
         this.updateStateInternal();
         return;
       }
       this.updateStorageState(storageIndex + 1);
     }.bind(this);
     req.onerror = function(e) {
-      dump("AdbController: error querying storage availability for '" +
-           this.storages[storageIndex].storageName + "' (ignoring)\n");
+
+      Cu.reportError("AdbController: error querying storage availability for '" +
+                     this.storages[storageIndex].storageName + "' (ignoring)\n");
       this.updateStorageState(storageIndex + 1);
     }.bind(this);
   },
 
   updateStateInternal: function() {
-    if (this.DEBUG) {
-      this.debug("updateStateInternal: called");
-    }
+    DEBUG && debug("updateStateInternal: called");
 
     if (this.remoteDebuggerEnabled === undefined ||
         this.lockEnabled === undefined ||
         this.locked === undefined) {
       // Part of initializing the settings database will cause the observers
       // to trigger. We want to wait until both have been initialized before
       // we start changing ther adb state. Without this then we can wind up
       // toggling adb off and back on again (or on and back off again).
@@ -157,28 +140,24 @@ let AdbController = {
       // receive the unlock event we haven't yet received the rde event, so
       // we turn adb off momentarily, which disconnects a logcat that might
       // be running. Changing the defaults (in AdbController) just moves the
       // problem to a different phone, which has adb disabled by default and
       // we wind up turning on adb for a short period when we shouldn't.
       //
       // By waiting until both values are properly initialized, we avoid
       // turning adb on or off accidentally.
-      if (this.DEBUG) {
-        this.debug("updateState: Waiting for all vars to be initialized");
-      }
+      DEBUG && debug("updateState: Waiting for all vars to be initialized");
       return;
     }
 
     // Check if we have a remote debugging session going on. If so, we won't
     // disable adb even if the screen is locked.
     let isDebugging = USBRemoteDebugger.isDebugging;
-    if (this.DEBUG) {
-      this.debug("isDebugging=" + isDebugging);
-    }
+    DEBUG && debug("isDebugging=" + isDebugging);
 
     // If USB Mass Storage, USB tethering, or a debug session is active,
     // then we don't want to disable adb in an automatic fashion (i.e.
     // when the screen locks or due to timeout).
     let sysUsbConfig = libcutils.property_get("sys.usb.config");
     let rndisActive = (sysUsbConfig.split(",").indexOf("rndis") >= 0);
     let usbFuncActive = rndisActive || this.umsActive || isDebugging;
 
@@ -194,23 +173,21 @@ let AdbController = {
         // we want adb enabled all of the time.
         enableAdb = true;
         useDisableAdbTimer = false;
       }
     } catch (e) {
       // This means that the pref doesn't exist. Which is fine. We just leave
       // enableAdb alone.
     }
-    if (this.DEBUG) {
-      this.debug("updateState: enableAdb = " + enableAdb +
-                 " remoteDebuggerEnabled = " + this.remoteDebuggerEnabled +
-                 " lockEnabled = " + this.lockEnabled +
-                 " locked = " + this.locked +
-                 " usbFuncActive = " + usbFuncActive);
-    }
+    DEBUG && debug("updateState: enableAdb = " + enableAdb +
+                   " remoteDebuggerEnabled = " + this.remoteDebuggerEnabled +
+                   " lockEnabled = " + this.lockEnabled +
+                   " locked = " + this.locked +
+                   " usbFuncActive = " + usbFuncActive);
 
     // Configure adb.
     let currentConfig = libcutils.property_get("persist.sys.usb.config");
     let configFuncs = currentConfig.split(",");
     let adbIndex = configFuncs.indexOf("adb");
 
     if (enableAdb) {
       // Add adb to the list of functions, if not already present
@@ -220,32 +197,31 @@ let AdbController = {
     } else {
       // Remove adb from the list of functions, if present
       if (adbIndex >= 0) {
         configFuncs.splice(adbIndex, 1);
       }
     }
     let newConfig = configFuncs.join(",");
     if (newConfig != currentConfig) {
-      if (this.DEBUG) {
-        this.debug("updateState: currentConfig = " + currentConfig);
-        this.debug("updateState:     newConfig = " + newConfig);
-      }
+      DEBUG && debug("updateState: currentConfig = " + currentConfig);
+      DEBUG && debug("updateState:     newConfig = " + newConfig);
       try {
         libcutils.property_set("persist.sys.usb.config", newConfig);
       } catch(e) {
-        dump("Error configuring adb: " + e);
+        Cu.reportError("Error configuring adb: " + e);
       }
     }
     if (useDisableAdbTimer) {
       if (enableAdb && !usbFuncActive) {
         this.startDisableAdbTimer();
       } else {
         this.stopDisableAdbTimer();
       }
     }
   }
+
 };
 
 SettingsListener.observe("lockscreen.locked", false,
                          AdbController.setLockscreenState.bind(AdbController));
 SettingsListener.observe("lockscreen.enabled", false,
                          AdbController.setLockscreenEnabled.bind(AdbController));
--- a/b2g/chrome/content/devtools/debugger.js
+++ b/b2g/chrome/content/devtools/debugger.js
@@ -16,16 +16,22 @@ XPCOMUtils.defineLazyGetter(this, "devto
     Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
   return devtools;
 });
 
 XPCOMUtils.defineLazyGetter(this, "discovery", function() {
   return devtools.require("devtools/toolkit/discovery/discovery");
 });
 
+XPCOMUtils.defineLazyGetter(this, "B2GTabList", function() {
+  const { B2GTabList } =
+    devtools.require("resource://gre/modules/DebuggerActors.js");
+  return B2GTabList;
+});
+
 let RemoteDebugger = {
   _promptDone: false,
   _promptAnswer: false,
   _listening: false,
 
   prompt: function() {
     this._listen();
 
@@ -86,25 +92,17 @@ let RemoteDebugger = {
      *
      * * @param connection DebuggerServerConnection
      *        The conection to the client.
      */
     DebuggerServer.createRootActor = function createRootActor(connection)
     {
       let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
       let parameters = {
-        // We do not expose browser tab actors yet,
-        // but we still have to define tabList.getList(),
-        // otherwise, client won't be able to fetch global actors
-        // from listTabs request!
-        tabList: {
-          getList: function() {
-            return promise.resolve([]);
-          }
-        },
+        tabList: new B2GTabList(connection),
         // Use an explicit global actor list to prevent exposing
         // unexpected actors
         globalActorFactories: restrictPrivileges ? {
           webappsActor: DebuggerServer.globalActorFactories.webappsActor,
           deviceActor: DebuggerServer.globalActorFactories.deviceActor,
         } : DebuggerServer.globalActorFactories
       };
       let { RootActor } = devtools.require("devtools/server/actors/root");
--- a/b2g/chrome/content/devtools/hud.js
+++ b/b2g/chrome/content/devtools/hud.js
@@ -24,17 +24,17 @@ XPCOMUtils.defineLazyGetter(this, 'WebCo
 XPCOMUtils.defineLazyGetter(this, 'EventLoopLagFront', function() {
   return devtools.require('devtools/server/actors/eventlooplag').EventLoopLagFront;
 });
 
 XPCOMUtils.defineLazyGetter(this, 'MemoryFront', function() {
   return devtools.require('devtools/server/actors/memory').MemoryFront;
 });
 
-Cu.import('resource://gre/modules/AppFrames.jsm');
+Cu.import('resource://gre/modules/Frames.jsm');
 
 /**
  * The Developer HUD is an on-device developer tool that displays widgets,
  * showing visual debug information about apps. Each widget corresponds to a
  * metric as tracked by a metric watcher (e.g. consoleWatcher).
  */
 let developerHUD = {
 
@@ -75,19 +75,20 @@ let developerHUD = {
     this._client = new DebuggerClient(transport);
 
     for (let w of this._watchers) {
       if (w.init) {
         w.init(this._client);
       }
     }
 
-    AppFrames.addObserver(this);
+    Frames.addObserver(this);
 
-    for (let frame of AppFrames.list()) {
+    let appFrames = Frames.list().filter(frame => frame.getAttribute('mozapp'));
+    for (let frame of appFrames) {
       this.trackFrame(frame);
     }
 
     SettingsListener.observe('hud.logging', this._logging, enabled => {
       this._logging = enabled;
     });
   },
 
@@ -95,17 +96,17 @@ let developerHUD = {
     if (!this._client) {
       return;
     }
 
     for (let frame of this._targets.keys()) {
       this.untrackFrame(frame);
     }
 
-    AppFrames.removeObserver(this);
+    Frames.removeObserver(this);
 
     this._client.close();
     delete this._client;
   },
 
   /**
    * This method will ask all registered watchers to track and update metrics
    * on an app frame.
@@ -132,21 +133,29 @@ let developerHUD = {
         w.untrackTarget(target);
       }
 
       target.destroy();
       this._targets.delete(frame);
     }
   },
 
-  onAppFrameCreated: function (frame, isFirstAppFrame) {
+  onFrameCreated: function (frame, isFirstAppFrame) {
+    let mozapp = frame.getAttribute('mozapp');
+    if (!mozapp) {
+      return;
+    }
     this.trackFrame(frame);
   },
 
-  onAppFrameDestroyed: function (frame, isLastAppFrame) {
+  onFrameDestroyed: function (frame, isLastAppFrame) {
+    let mozapp = frame.getAttribute('mozapp');
+    if (!mozapp) {
+      return;
+    }
     this.untrackFrame(frame);
   },
 
   log: function dwp_log(message) {
     if (this._logging) {
       dump(DEVELOPER_HUD_LOG_PREFIX + ': ' + message + '\n');
     }
   }
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -452,16 +452,26 @@ SettingsListener.observe("theme.selected
     Services.prefs.setCharPref('dom.mozApps.selected_theme', newTheme);
     Services.prefs.savePrefFile(null);
     Services.obs.notifyObservers(null, 'app-theme-changed', newTheme);
   }
 });
 
 // =================== Various simple mapping  ======================
 let settingsToObserve = {
+  'accessibility.screenreader_quicknav_modes': {
+    prefName: 'accessibility.accessfu.quicknav_modes',
+    resetToPref: true,
+    defaultValue: ''
+  },
+  'accessibility.screenreader_quicknav_index': {
+    prefName: 'accessibility.accessfu.quicknav_index',
+    resetToPref: true,
+    defaultValue: 0
+  },
   'app.update.channel': {
     resetToPref: true
   },
   'app.update.interval': 86400,
   'app.update.url': {
     resetToPref: true
   },
   'apz.force-enable': {
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -319,25 +319,28 @@ var shell = {
     // Capture all key events so we can filter out hardware buttons
     // And send them to Gaia via mozChromeEvents.
     // Ideally, hardware buttons wouldn't generate key events at all, or
     // if they did, they would use keycodes that conform to DOM 3 Events.
     // See discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=762362
     chromeEventHandler.addEventListener('keydown', this, true);
     chromeEventHandler.addEventListener('keypress', this, true);
     chromeEventHandler.addEventListener('keyup', this, true);
+    chromeEventHandler.addEventListener('mozbrowserbeforekeydown', this, true);
+    chromeEventHandler.addEventListener('mozbrowserbeforekeyup', this, true);
 
     window.addEventListener('MozApplicationManifest', this);
     window.addEventListener('mozfullscreenchange', this);
     window.addEventListener('MozAfterPaint', this);
     window.addEventListener('sizemodechange', this);
     window.addEventListener('unload', this);
     this.contentBrowser.addEventListener('mozbrowserloadstart', this, true);
     this.contentBrowser.addEventListener('mozbrowserselectionchange', this, true);
     this.contentBrowser.addEventListener('mozbrowserscrollviewchange', this, true);
+    this.contentBrowser.addEventListener('mozbrowsertouchcarettap', this, true);
 
     CustomEventManager.init();
     WebappsHelper.init();
     UserAgentOverrides.init();
     IndexedDBPromptHelper.init();
     CaptivePortalLoginHelper.init();
 
     this.contentBrowser.src = homeURL;
@@ -350,22 +353,25 @@ var shell = {
     ppmm.addMessageListener("file-picker", this);
   },
 
   stop: function shell_stop() {
     window.removeEventListener('unload', this);
     window.removeEventListener('keydown', this, true);
     window.removeEventListener('keypress', this, true);
     window.removeEventListener('keyup', this, true);
+    window.removeEventListener('mozbrowserbeforekeydown', this, true);
+    window.removeEventListener('mozbrowserbeforekeyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('mozfullscreenchange', this);
     window.removeEventListener('sizemodechange', this);
     this.contentBrowser.removeEventListener('mozbrowserloadstart', this, true);
     this.contentBrowser.removeEventListener('mozbrowserselectionchange', this, true);
     this.contentBrowser.removeEventListener('mozbrowserscrollviewchange', this, true);
+    this.contentBrowser.removeEventListener('mozbrowsertouchcarettap', this, true);
     ppmm.removeMessageListener("content-handler", this);
 
     UserAgentOverrides.uninit();
     IndexedDBPromptHelper.uninit();
   },
 
   // If this key event actually represents a hardware button, filter it here
   // and send a mozChromeEvent with detail.type set to xxx-button-press or
@@ -413,27 +419,24 @@ var shell = {
       isMediaKey = true;
       type = mediaKeys[evt.key];
     }
 
     if (!type) {
       return;
     }
 
-    // If we didn't return, then the key event represents a hardware key
-    // and we need to prevent it from propagating to Gaia
-    evt.stopImmediatePropagation();
-    evt.preventDefault(); // Prevent keypress events (when #501496 is fixed).
-
     // If it is a key down or key up event, we send a chrome event to Gaia.
     // If it is a keypress event we just ignore it.
     switch (evt.type) {
+      case 'mozbrowserbeforekeydown':
       case 'keydown':
         type = type + '-press';
         break;
+      case 'mozbrowserbeforekeyup':
       case 'keyup':
         type = type + '-release';
         break;
       case 'keypress':
         return;
     }
 
     // Let applications receive the headset button key press/release event.
@@ -466,16 +469,18 @@ var shell = {
   visibleNormalAudioActive: false,
 
   handleEvent: function shell_handleEvent(evt) {
     let content = this.contentBrowser.contentWindow;
     switch (evt.type) {
       case 'keydown':
       case 'keyup':
       case 'keypress':
+      case 'mozbrowserbeforekeydown':
+      case 'mozbrowserbeforekeyup':
         this.filterHardwareKeys(evt);
         break;
       case 'mozfullscreenchange':
         // When the screen goes fullscreen make sure to set the focus to the
         // main window so noboby can prevent the ESC key to get out fullscreen
         // mode
         if (document.mozFullScreen)
           Services.fm.focusedWindow = window;
@@ -503,16 +508,22 @@ var shell = {
         this.notifyContentStart();
        break;
       case 'mozbrowserscrollviewchange':
         this.sendChromeEvent({
           type: 'scrollviewchange',
           detail: evt.detail,
         });
         break;
+      case 'mozbrowsertouchcarettap':
+        this.sendChromeEvent({
+          type: 'touchcarettap',
+          detail: evt.detail,
+        });
+        break;
       case 'mozbrowserselectionchange':
         // The mozbrowserselectionchange event, may have crossed the chrome-content boundary.
         // This event always dispatch to shell.js. But the offset we got from this event is
         // based on tab's coordinate. So get the actual offsets between shell and evt.target.
         let elt = evt.target;
         let win = elt.ownerDocument.defaultView;
         let offsetX = win.mozInnerScreenX - window.mozInnerScreenX;
         let offsetY = win.mozInnerScreenY - window.mozInnerScreenY;
new file mode 100644
--- /dev/null
+++ b/b2g/components/DebuggerActors.js
@@ -0,0 +1,83 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- /
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const { Cu } = require("chrome");
+const DevToolsUtils = require("devtools/toolkit/DevToolsUtils.js");
+const promise = require("promise");
+const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
+const { BrowserTabList } = require("devtools/server/actors/webbrowser");
+
+XPCOMUtils.defineLazyGetter(this, "Frames", function() {
+  const { Frames } =
+    Cu.import("resource://gre/modules/Frames.jsm", {});
+  return Frames;
+});
+
+/**
+ * Unlike the original BrowserTabList which iterates over XUL windows, we
+ * override many portions to refer to Frames for the info needed here.
+ */
+function B2GTabList(connection) {
+  BrowserTabList.call(this, connection);
+  this._listening = false;
+}
+
+B2GTabList.prototype = Object.create(BrowserTabList.prototype);
+
+B2GTabList.prototype._getBrowsers = function() {
+  return Frames.list().filter(frame => {
+    // Ignore app frames
+    return !frame.getAttribute("mozapp");
+  });
+};
+
+B2GTabList.prototype._getSelectedBrowser = function() {
+  return this._getBrowsers().find(frame => {
+    // Find the one visible browser (if any)
+    return !frame.classList.contains("hidden");
+  });
+};
+
+B2GTabList.prototype._checkListening = function() {
+  // The conditions from BrowserTabList are merged here, since we must listen to
+  // all events with our observer design.
+  this._listenForEventsIf(this._onListChanged && this._mustNotify ||
+                          this._actorByBrowser.size > 0);
+};
+
+B2GTabList.prototype._listenForEventsIf = function(shouldListen) {
+  if (this._listening != shouldListen) {
+    let op = shouldListen ? "addObserver" : "removeObserver";
+    Frames[op](this);
+    this._listening = shouldListen;
+  }
+};
+
+B2GTabList.prototype.onFrameCreated = function(frame) {
+  let mozapp = frame.getAttribute("mozapp");
+  if (mozapp) {
+    // Ignore app frames
+    return;
+  }
+  this._notifyListChanged();
+  this._checkListening();
+};
+
+B2GTabList.prototype.onFrameDestroyed = function(frame) {
+  let mozapp = frame.getAttribute("mozapp");
+  if (mozapp) {
+    // Ignore app frames
+    return;
+  }
+  let actor = this._actorByBrowser.get(frame);
+  if (actor) {
+    this._handleActorClose(actor, frame);
+  }
+};
+
+exports.B2GTabList = B2GTabList;
rename from b2g/components/AppFrames.jsm
rename to b2g/components/Frames.jsm
--- a/b2g/components/AppFrames.jsm
+++ b/b2g/components/Frames.jsm
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
-this.EXPORTED_SYMBOLS = ['AppFrames'];
+this.EXPORTED_SYMBOLS = ['Frames'];
 
 const Cu = Components.utils;
 const Ci = Components.interfaces;
 
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/SystemAppProxy.jsm');
 
 const listeners = [];
@@ -22,21 +22,23 @@ const Observer = {
   // Also save current number of iframes opened by app
   _apps: new Map(),
 
   start: function () {
     Services.obs.addObserver(this, 'remote-browser-shown', false);
     Services.obs.addObserver(this, 'inprocess-browser-shown', false);
     Services.obs.addObserver(this, 'message-manager-disconnect', false);
 
-    SystemAppProxy.getAppFrames().forEach((frame) => {
+    SystemAppProxy.getFrames().forEach(frame => {
       let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
       this._frames.set(mm, frame);
       let mozapp = frame.getAttribute('mozapp');
-      this._apps.set(mozapp, (this._apps.get(mozapp) || 0) + 1);
+      if (mozapp) {
+        this._apps.set(mozapp, (this._apps.get(mozapp) || 0) + 1);
+      }
     });
   },
 
   stop: function () {
     Services.obs.removeObserver(this, 'remote-browser-shown');
     Services.obs.removeObserver(this, 'inprocess-browser-shown');
     Services.obs.removeObserver(this, 'message-manager-disconnect');
     this._frames.clear();
@@ -63,58 +65,66 @@ const Observer = {
         this.onMessageManagerDestroyed(subject);
         break;
     }
   },
 
   onMessageManagerCreated: function (mm, frame) {
     this._frames.set(mm, frame);
 
+    let isFirstAppFrame = null;
     let mozapp = frame.getAttribute('mozapp');
-    let count = (this._apps.get(mozapp) || 0) + 1;
-    this._apps.set(mozapp, count);
+    if (mozapp) {
+      let count = (this._apps.get(mozapp) || 0) + 1;
+      this._apps.set(mozapp, count);
+      isFirstAppFrame = (count === 1);
+    }
 
-    let isFirstAppFrame = (count === 1);
     listeners.forEach(function (listener) {
       try {
-        listener.onAppFrameCreated(frame, isFirstAppFrame);
+        listener.onFrameCreated(frame, isFirstAppFrame);
       } catch(e) {
-        dump('Exception while calling Frames.jsm listener:' + e + '\n' + e.stack + '\n');
+        dump('Exception while calling Frames.jsm listener:' + e + '\n' +
+             e.stack + '\n');
       }
     });
   },
 
   onMessageManagerDestroyed: function (mm) {
     let frame = this._frames.get(mm);
     if (!frame) {
-      // We receive an event for a non mozapp message manager
+      // We received an event for an unknown message manager
       return;
     }
 
     this._frames.delete(mm);
 
+    let isLastAppFrame = null;
     let mozapp = frame.getAttribute('mozapp');
-    let count = (this._apps.get(mozapp) || 0) - 1;
-    this._apps.set(mozapp, count);
+    if (mozapp) {
+      let count = (this._apps.get(mozapp) || 0) - 1;
+      this._apps.set(mozapp, count);
+      isLastAppFrame = (count === 0);
+    }
 
-    let isLastAppFrame = (count === 0);
     listeners.forEach(function (listener) {
       try {
-        listener.onAppFrameDestroyed(frame, isLastAppFrame);
+        listener.onFrameDestroyed(frame, isLastAppFrame);
       } catch(e) {
-        dump('Exception while calling Frames.jsm listener:' + e + '\n' + e.stack + '\n');
+        dump('Exception while calling Frames.jsm listener:' + e + '\n' +
+             e.stack + '\n');
       }
     });
   }
 
 };
 
-let AppFrames = this.AppFrames = {
+let Frames = this.Frames = {
 
-  list: () => SystemAppProxy.getAppFrames(),
+  list: () => SystemAppProxy.getFrames(),
 
   addObserver: function (listener) {
     if (listeners.indexOf(listener) !== -1) {
       return;
     }
 
     listeners.push(listener);
     if (listeners.length == 1) {
--- a/b2g/components/SystemAppProxy.jsm
+++ b/b2g/components/SystemAppProxy.jsm
@@ -112,30 +112,23 @@ let SystemAppProxy = {
     } else {
       this._pendingListeners = this._pendingListeners.filter(
         args => {
           return args[0] != name || args[1] != listener;
         });
     }
   },
 
-  getAppFrames: function systemApp_getAppFrames() {
+  getFrames: function systemApp_getFrames() {
     let systemAppFrame = this._frame;
     if (!systemAppFrame) {
       return [];
     }
-
     let list = [systemAppFrame];
-
-    // List all app frames hosted in the system app: the homescreen,
-    // all regular apps, activities, rocket bar, attention screen and the keyboard.
-    // Bookmark apps and other system app internal frames like captive portal
-    // are also hosted in system app, but they are not using mozapp attribute.
-    let frames = systemAppFrame.contentDocument.querySelectorAll("iframe[mozapp]");
+    let frames = systemAppFrame.contentDocument.querySelectorAll('iframe');
     for (let i = 0; i < frames.length; i++) {
       list.push(frames[i]);
     }
-
     return list;
   }
 };
 this.SystemAppProxy = SystemAppProxy;
 
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -43,19 +43,20 @@ EXTRA_PP_COMPONENTS += [
 
 if CONFIG['MOZ_UPDATER']:
     EXTRA_PP_COMPONENTS += [
         'UpdatePrompt.js',
     ]
 
 EXTRA_JS_MODULES += [
     'AlertsHelper.jsm',
-    'AppFrames.jsm',
     'ContentRequestHelper.jsm',
+    'DebuggerActors.js',
     'ErrorPage.jsm',
+    'Frames.jsm',
     'FxAccountsMgmtService.jsm',
     'LogCapture.jsm',
     'LogParser.jsm',
     'LogShake.jsm',
     'SignInToWebsite.jsm',
     'SystemAppProxy.jsm',
     'TelURIParser.jsm',
     'WebappsUpdater.jsm',
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
@@ -128,16 +128,16 @@
   <project name="platform/external/icu4c" path="external/icu4c" revision="2bb01561780583cc37bc667f0ea79f48a122d8a2"/>
   <!-- dolphin specific things -->
   <project name="device/sprd" path="device/sprd" revision="3a0f1b51e3b27b36b9df484f3c286b6099889f6e"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="4e58336019b5cbcfd134caf55b142236cf986618"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="4387fe988e5a1001f29ce05fcfda03ed2d32137b"/>
   <project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
   <project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
-  <project name="kernel/common" path="kernel" revision="250294fb70e018b0966402f744ff9705109f8635"/>
+  <project name="kernel/common" path="kernel" revision="310657b79caae2c89e6375a4185fe35fde089c39"/>
   <project name="platform/system/core" path="system/core" revision="53d584d4a4b4316e4de9ee5f210d662f89b44e7e"/>
   <project name="u-boot" path="u-boot" revision="982c1fd67b89d5573317c1796cf5b0143de44e8a"/>
   <project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="6974f8e771d4d8e910357a6739ab124768891e8f"/>
   <project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="1d4697b16ed039fd1de0a23bda150523e743e2ad"/>
   <project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
   <project name="vendor/sprd/proprietories" path="vendor/sprd/proprietories" revision="d2466593022f7078aaaf69026adf3367c2adb7bb"/>
 </manifest>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
@@ -129,12 +129,12 @@
   <project name="android-development" path="development" remote="b2g" revision="dab55669da8f48b6e57df95d5af9f16b4a87b0b1"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="197cd9492b9fadaa915c5daf36ff557f8f4a8d1c"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="libnfcemu" path="external/libnfcemu" remote="b2g" revision="125ccf9bd5986c7728ea44508b3e1d1185ac028b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d259117b4976decbe2f76eeed85218bf0109190f"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
@@ -128,17 +128,17 @@
   <remove-project name="platform/external/bluetooth/bluedroid"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="54c32c2ddef066fbdf611d29e4b7c47e0363599e"/>
   <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="52c909e821d107d414f851e267dedcd7aae2cebf"/>
-  <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="1072f7d31dc0bf3a2adc64177b1104da9f4ce4b6"/>
+  <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="7731d63c809dbca4da408e1de0c1a044f0765e52"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="30b96dfca99cb384bf520a16b81f3aba56f09907"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="ea2f399b3ca0a23524d2828f85f69902caefc22e"/>
   <project name="platform/frameworks/base" path="frameworks/base" revision="6b58ab45e3e56c1fc20708cc39fa2264c52558df"/>
   <project name="platform/frameworks/native" path="frameworks/native" revision="a46a9f1ac0ed5662d614c277cbb14eb3f332f365"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="7196881a0e9dd7bfbbcf0af64c8064e70f0fa094"/>
@@ -146,13 +146,13 @@
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="2a1ded216a91bf62a72b1640cf01ab4998f37028"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="e5a971282719907f73fb1da964ca40aad67a3be0"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="9883ea57b0668d8f60dba025d4522dfa69a1fbfa"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="a558dc844bf5144fc38603fd8f4df8d9557052a5"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
   <project name="platform/system/core" path="system/core" revision="350eac5403124dacb2a5fd9e28ac290a59fc3b8e"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
   <project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
   <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="7704e16da545f4207812e593743d6743e1afb9c5"/>
 </manifest>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
@@ -140,13 +140,13 @@
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="5e110615212302c5d798a3c223dcee458817651c"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="fa9ffd47948eb24466de227e48fe9c4a7c5e7711"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="cd76b19aafd4229ccf83853d02faef8c51ca8b34"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="8a0d0b0d9889ef99c4c6317c810db4c09295f15a"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
   <project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
   <project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
   <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
 </manifest>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "eeeae73691f91cd5042660b0f19c84747ebc7be2", 
+    "revision": "8017299c3eb7b82bdaee1334994f546c11eb16ab", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,22 +12,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/mozconfigs/win32_gecko/debug
+++ b/b2g/config/mozconfigs/win32_gecko/debug
@@ -10,17 +10,17 @@ ac_add_options --enable-debug
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
-  . $topsrcdir/build/win32/mozconfig.vs2010-win64
+  . $topsrcdir/build/win32/mozconfig.vs2013-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # B2G Options
 ac_add_options --enable-application=b2g
 ENABLE_MARIONETTE=1
 
--- a/b2g/config/mozconfigs/win32_gecko/nightly
+++ b/b2g/config/mozconfigs/win32_gecko/nightly
@@ -9,17 +9,17 @@ ac_add_options --enable-signmar
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
-  . $topsrcdir/build/win32/mozconfig.vs2010-win64
+  . $topsrcdir/build/win32/mozconfig.vs2013-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # B2G Options
 ac_add_options --enable-application=b2g
 export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
 
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
@@ -124,17 +124,17 @@
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
   <!-- Nexus 4 specific things -->
   <project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="85e864c4abc80e08bc82f0ac53c042e0d27839b0"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="b0a528d839cfd9d170d092fe3743b5252b4243a6"/>
   <project name="platform/hardware/qcom/bt" path="hardware/qcom/bt" revision="380945eaa249a2dbdde0daa4c8adb8ca325edba6"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="6f3b0272cefaffeaed2a7d2bb8f633059f163ddc"/>
   <project name="platform/hardware/qcom/keymaster" path="hardware/qcom/keymaster" revision="16da8262c997a5a0d797885788a64a0771b26910"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="689b476ba3eb46c34b81343295fe144a0e81a18e"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,22 +12,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cc5da7b055e2b06fdeb46fa94970550392ee571d"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="5c636a7a54b2c86d8ff6bc1aa1e5f9594c7bc586"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="6ca2008ac50b163d31244ef9f036cb224f4f229b"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -1,16 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOZ_APP_BASENAME=B2G
 MOZ_APP_VENDOR=Mozilla
 
-MOZ_APP_VERSION=35.0a1
+MOZ_APP_VERSION=36.0a1
 MOZ_APP_UA_NAME=Firefox
 
 MOZ_UA_OS_AGNOSTIC=1
 
 MOZ_B2G_VERSION=2.2.0.0-prerelease
 MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -110,17 +110,16 @@
 #ifndef MOZ_FOLD_LIBS
 @BINPATH@/@DLL_PREFIX@mozsqlite3@DLL_SUFFIX@
 #endif
 @BINPATH@/blocklist.xml
 @BINPATH@/ua-update.json
 #ifdef XP_UNIX
 #ifndef XP_MACOSX
 @BINPATH@/run-mozilla.sh
-@BINPATH@/mozilla-xremote-client
 #endif
 #endif
 
 ; [Components]
 @BINPATH@/components/components.manifest
 @BINPATH@/components/alerts.xpt
 #ifdef ACCESSIBILITY
 #ifdef XP_WIN32
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1412277891000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1412711894000">
   <emItems>
       <emItem  blockID="i454" id="sqlmoz@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                                 <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
@@ -995,16 +995,22 @@
               </prefs>
     </emItem>
       <emItem  blockID="i172" id="info@bflix.info">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
+      <emItem  blockID="i722" id="{9802047e-5a84-4da3-b103-c55995d147d1}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="3">
+                    </versionRange>
+                    <prefs>
+              </prefs>
+    </emItem>
       <emItem  blockID="i525" id="/^({65f9f6b7-2dae-46fc-bfaf-f88e4af1beca}|{9ed31f84-c8b3-4926-b950-dff74047ff79}|{0134af61-7a0c-4649-aeca-90d776060cb3}|{02edb56b-9b33-435b-b7df-b2843273a694}|{da51d4f6-3e7e-4ef8-b400-9198e0874606}|{b24577db-155e-4077-bb37-3fdd3c302bb5})$/">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i485" id="/^brasilescape.*\@facebook\.com$//">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -269,20 +269,17 @@ static int do_main(int argc, char* argv[
     if (NS_FAILED(rv)) {
       Output("Couldn't find the application directory.\n");
       return 255;
     }
 
     nsCOMPtr<nsIFile> greDir;
     exeFile->GetParent(getter_AddRefs(greDir));
 #ifdef XP_MACOSX
-    nsCOMPtr<nsIFile> parent;
-    greDir->GetParent(getter_AddRefs(parent));
-    greDir = parent.forget();
-    greDir->AppendNative(NS_LITERAL_CSTRING(kOSXResourcesFolder));
+    greDir->SetNativeLeafName(NS_LITERAL_CSTRING(kOSXResourcesFolder));
 #endif
     nsCOMPtr<nsIFile> appSubdir;
     greDir->Clone(getter_AddRefs(appSubdir));
     appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
 
     SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get()));
     // xreDirectory already has a refcount from NS_NewLocalFile
     appData.xreDirectory = xreDirectory;
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1287,16 +1287,17 @@ pref("services.sync.prefs.sync.security.
 pref("services.sync.prefs.sync.security.tls.version.max", true);
 pref("services.sync.prefs.sync.signon.rememberSignons", true);
 pref("services.sync.prefs.sync.spellchecker.dictionary", true);
 pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
 #endif
 
 // Developer edition preferences
 pref("browser.devedition.theme.enabled", false);
+pref("browser.devedition.theme.showCustomizeButton", false);
 
 // Disable the error console
 pref("devtools.errorconsole.enabled", false);
 
 // Developer toolbar and GCLI preferences
 pref("devtools.toolbar.enabled", true);
 pref("devtools.toolbar.visible", false);
 pref("devtools.commands.dir", "");
@@ -1374,16 +1375,23 @@ pref("devtools.debugger.ui.panes-visible
 pref("devtools.debugger.ui.variables-sorting-enabled", true);
 pref("devtools.debugger.ui.variables-only-enum-visible", false);
 pref("devtools.debugger.ui.variables-searchbox-visible", false);
 
 // Enable the Profiler and the Timeline
 pref("devtools.profiler.enabled", true);
 pref("devtools.timeline.enabled", false);
 
+// Enable perftools via build command
+#ifdef MOZ_DEVTOOLS_PERFTOOLS
+  pref("devtools.performance_dev.enabled", true);
+#else
+  pref("devtools.performance_dev.enabled", false);
+#endif
+
 // The default Profiler UI settings
 pref("devtools.profiler.ui.show-platform-data", false);
 
 // The default cache UI setting
 pref("devtools.cache.disabled", false);
 
 // Enable the Network Monitor
 pref("devtools.netmonitor.enabled", true);
@@ -1411,17 +1419,17 @@ pref("devtools.scratchpad.recentFilesMax
 pref("devtools.scratchpad.showTrailingSpace", false);
 pref("devtools.scratchpad.enableAutocompletion", true);
 
 // Enable the Storage Inspector
 pref("devtools.storage.enabled", false);
 
 // Enable the Style Editor.
 pref("devtools.styleeditor.enabled", true);
-pref("devtools.styleeditor.source-maps-enabled", false);
+pref("devtools.styleeditor.source-maps-enabled", true);
 pref("devtools.styleeditor.autocompletion-enabled", true);
 pref("devtools.styleeditor.showMediaSidebar", true);
 pref("devtools.styleeditor.mediaSidebarWidth", 238);
 pref("devtools.styleeditor.navSidebarWidth", 245);
 pref("devtools.styleeditor.transitions", true);
 
 // Enable the Shader Editor.
 pref("devtools.shadereditor.enabled", false);
@@ -1547,17 +1555,17 @@ pref("browser.newtabpage.enabled", true)
 
 // number of rows of newtab grid
 pref("browser.newtabpage.rows", 3);
 
 // number of columns of newtab grid
 pref("browser.newtabpage.columns", 5);
 
 // directory tiles download URL
-pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v2/links/fetch");
+pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v2/links/fetch/%LOCALE%");
 
 // endpoint to send newtab click and view pings
 pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v2/links/");
 
 // Enable the DOM fullscreen API.
 pref("full-screen-api.enabled", true);
 
 // True if the fullscreen API requires approval upon a domain entering fullscreen.
--- a/browser/base/content/aboutDialog.xul
+++ b/browser/base/content/aboutDialog.xul
@@ -123,17 +123,17 @@
             <description class="text-blurb" id="communityExperimentalDesc">
               &community.exp.start;<label class="text-link" href="http://www.mozilla.org/">&community.exp.mozillaLink;</label>&community.exp.middle;<label class="text-link" href="about:credits">&community.exp.creditsLink;</label>&community.exp.end;
             </description>
           </vbox>
           <description class="text-blurb" id="communityDesc">
             &community.start2;<label class="text-link" href="http://www.mozilla.org/">&community.mozillaLink;</label>&community.middle2;<label class="text-link" href="about:credits">&community.creditsLink;</label>&community.end3;
           </description>
           <description class="text-blurb" id="contributeDesc">
-            &contribute.start;<label class="text-link" href="http://www.mozilla.org/contribute/">&contribute.getInvolvedLink;</label>&contribute.end;
+              &helpus.start;<label class="text-link" href="https://sendto.mozilla.org/page/contribute/Give-Now?source=mozillaorg_default_footer&#38;ref=firefox_about&#38;utm_campaign=firefox_about&#38;tm_source=firefox&#38;tm_medium=referral&#38;utm_content=20140929_FireFoxAbout">&helpus.donateLink;</label>&helpus.middle;<label class="text-link" href="http://www.mozilla.org/contribute/">&helpus.getInvolvedLink;</label>&helpus.end;
           </description>
         </vbox>
       </vbox>
     </hbox>
     <vbox id="bottomBox">
       <hbox pack="center">
         <label class="text-link bottom-link" href="about:license">&bottomLinks.license;</label>
         <label class="text-link bottom-link" href="about:rights">&bottomLinks.rights;</label>
--- a/browser/base/content/aboutaccounts/aboutaccounts.js
+++ b/browser/base/content/aboutaccounts/aboutaccounts.js
@@ -285,32 +285,32 @@ function getStarted() {
 }
 
 function openPrefs() {
   window.openPreferences("paneSync");
 }
 
 function init() {
   fxAccounts.getSignedInUser().then(user => {
+    // tests in particular might cause the window to start closing before
+    // getSignedInUser has returned.
+    if (window.closed) {
+      return;
+    }
     // If the url contains an entrypoint query parameter, extract it into a variable
     // to append it to the accounts URI resource.
     // Works for the following cases:
     // - about:accounts?entrypoint="abouthome"
     // - about:accounts?entrypoint=abouthome&action=signup
     let entryPointQParam = "entrypoint=";
     let entryPointPos = window.location.href.indexOf(entryPointQParam);
     let entryPoint = "";
     if (entryPointPos >= 0) {
       entryPoint = window.location.href.substring(entryPointPos).split("&")[0];
     }
-    // tests in particular might cause the window to start closing before
-    // getSignedInUser has returned.
-    if (window.closed) {
-      return;
-    }
     if (window.location.href.contains("action=signin")) {
       if (user) {
         // asking to sign-in when already signed in just shows manage.
         show("stage", "manage");
       } else {
         show("remote");
         wrapper.init(fxAccounts.getAccountsSignInURI(), entryPoint);
       }
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -703,23 +703,22 @@ var BookmarksEventHandler = {
 
   fillInBHTooltip: function BEH_fillInBHTooltip(aDocument, aEvent) {
     var node;
     var cropped = false;
     var targetURI;
 
     if (aDocument.tooltipNode.localName == "treechildren") {
       var tree = aDocument.tooltipNode.parentNode;
-      var row = {}, column = {};
       var tbo = tree.treeBoxObject;
-      tbo.getCellAt(aEvent.clientX, aEvent.clientY, row, column, {});
-      if (row.value == -1)
+      var cell = tbo.getCellAt(aEvent.clientX, aEvent.clientY);
+      if (cell.row == -1)
         return false;
-      node = tree.view.nodeForTreeIndex(row.value);
-      cropped = tbo.isCellCropped(row.value, column.value);
+      node = tree.view.nodeForTreeIndex(cell.row);
+      cropped = tbo.isCellCropped(cell.row, cell.col);
     }
     else {
       // Check whether the tooltipNode is a Places node.
       // In such a case use it, otherwise check for targetURI attribute.
       var tooltipNode = aDocument.tooltipNode;
       if (tooltipNode._placesNode)
         node = tooltipNode._placesNode;
       else {
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -246,23 +246,29 @@ var gPluginHandler = {
       pluginData = new Map();
     }
 
     for (var pluginInfo of plugins) {
       if (pluginData.has(pluginInfo.permissionString)) {
         continue;
       }
 
-      let url;
-      // TODO: allow the blocklist to specify a better link, bug 873093
+      // If a block contains an infoURL, we should always prefer that to the default
+      // URL that we construct in-product, even for other blocklist types.
+      let url = Services.blocklist.getPluginInfoURL(pluginInfo.pluginTag);
+
       if (pluginInfo.blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE) {
-        url = Services.urlFormatter.formatURLPref("plugins.update.url");
+        if (!url) {
+          url = Services.urlFormatter.formatURLPref("plugins.update.url");
+        }
       }
       else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
-        url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
+        if (!url) {
+          url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
+        }
       }
       else {
         url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "clicktoplay";
       }
       pluginInfo.detailsLink = url;
 
       pluginData.set(pluginInfo.permissionString, pluginInfo);
     }
--- a/browser/base/content/newtab/newTab.css
+++ b/browser/base/content/newtab/newTab.css
@@ -56,16 +56,20 @@ input[type=button] {
   top: 15px;
 }
 
 #newtab-intro-what:-moz-locale-dir(rtl) {
   left: 55px;
   right: auto;
 }
 
+#newtab-scrollbox[page-disabled] #newtab-intro-what {
+  display: none;
+}
+
 #newtab-intro-panel {
   color: #6a7b86;
   font-size: 15px;
   line-height: 19px;
   width: 520px;
 }
 
 #newtab-intro-panel h1 {
--- a/browser/base/content/newtab/updater.js
+++ b/browser/base/content/newtab/updater.js
@@ -149,32 +149,29 @@ let gUpdater = {
 
   /**
    * Tries to fill empty cells with new links if available.
    * @param aLinks The array of links.
    * @param aCallback The callback to call when finished.
    */
   _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
     let {cells, sites} = gGrid;
-    let batch = [];
 
     // Find empty cells and fill them.
-    sites.forEach(function (aSite, aIndex) {
+    Promise.all(sites.map((aSite, aIndex) => {
       if (aSite || !aLinks[aIndex])
-        return;
+        return null;
 
-      batch.push(new Promise(resolve => {
+      return new Promise(resolve => {
         // Create the new site and fade it in.
         let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
 
         // Set the site's initial opacity to zero.
         site.node.style.opacity = 0;
 
         // Flush all style changes for the dynamically inserted site to make
         // the fade-in transition work.
         window.getComputedStyle(site.node).opacity;
         gTransformation.showSite(site, resolve);
-      }));
-    });
-
-    Promise.all(batch).then(aCallback);
+      });
+    })).then(aCallback).catch(console.exception);
   }
 };
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -503,17 +503,17 @@ function makeGeneralTab()
     metaGroup.collapsed = true;
   else {
     var metaTagsCaption = document.getElementById("metaTagsCaption");
     if (length == 1)
       metaTagsCaption.label = gBundle.getString("generalMetaTag");
     else
       metaTagsCaption.label = gBundle.getFormattedString("generalMetaTags", [length]);
     var metaTree = document.getElementById("metatree");
-    metaTree.treeBoxObject.view = gMetaView;
+    metaTree.view = gMetaView;
 
     for (var i = 0; i < length; i++)
       gMetaView.addRow([metaNodes[i].name || metaNodes[i].httpEquiv, metaNodes[i].content]);
 
     metaGroup.collapsed = false;
   }
 
   // get the date of last modification
--- a/browser/base/content/pageinfo/permissions.js
+++ b/browser/base/content/pageinfo/permissions.js
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource:///modules/SitePermissions.jsm");
+Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
 
 const nsIQuotaManager = Components.interfaces.nsIQuotaManager;
 
 var gPermURI;
 var gUsageRequest;
 
 var gPermissions = SitePermissions.listPermissions();
 gPermissions.push("plugins");
@@ -226,30 +227,16 @@ function onIndexedDBUsageCallback(uri, u
     status.value =
       gBundle.getFormattedString("indexedDBUsage",
                                  DownloadUtils.convertByteUnits(usage));
     status.removeAttribute("hidden");
     button.removeAttribute("hidden");
   }
 }
 
-// XXX copied this from browser-plugins.js - is there a way to share?
-function makeNicePluginName(aName) {
-  if (aName == "Shockwave Flash")
-    return "Adobe Flash";
-
-  // Clean up the plugin name by stripping off any trailing version numbers
-  // or "plugin". EG, "Foo Bar Plugin 1.23_02" --> "Foo Bar"
-  // Do this by first stripping the numbers, etc. off the end, and then
-  // removing "Plugin" (and then trimming to get rid of any whitespace).
-  // (Otherwise, something like "Java(TM) Plug-in 1.7.0_07" gets mangled)
-  let newName = aName.replace(/[\s\d\.\-\_\(\)]+$/, "").replace(/\bplug-?in\b/i, "").trim();
-  return newName;
-}
-
 function fillInPluginPermissionTemplate(aPluginName, aPermissionString) {
   let permPluginTemplate = document.getElementById("permPluginTemplate").cloneNode(true);
   permPluginTemplate.setAttribute("permString", aPermissionString);
   let attrs = [
     [ ".permPluginTemplateLabel", "value", aPluginName ],
     [ ".permPluginTemplateRadioGroup", "id", aPermissionString + "RadioGroup" ],
     [ ".permPluginTemplateRadioDefault", "id", aPermissionString + "#0" ],
     [ ".permPluginTemplateRadioAsk", "id", aPermissionString + "#3" ],
@@ -283,17 +270,17 @@ function initPluginsRow() {
 
   for (let plugin of pluginHost.getPluginTags()) {
     if (plugin.disabled) {
       continue;
     }
     for (let mimeType of plugin.getMimeTypes()) {
       let permString = pluginHost.getPermissionStringForType(mimeType);
       if (!permissionMap.has(permString)) {
-        var name = makeNicePluginName(plugin.name);
+        let name = BrowserUtils.makeNicePluginName(plugin.name);
         if (permString.startsWith("plugin-vulnerable:")) {
           name += " \u2014 " + vulnerableLabel;
         }
         permissionMap.set(permString, name);
       }
     }
   }
 
--- a/browser/base/content/popup-notifications.inc
+++ b/browser/base/content/popup-notifications.inc
@@ -54,8 +54,14 @@
     </popupnotification>
 
     <popupnotification id="pointerLock-notification" hidden="true">
       <popupnotificationcontent orient="vertical" align="start">
         <separator class="thin"/>
         <label id="pointerLock-cancel" value="&pointerLock.notification.message;"/>
       </popupnotificationcontent>
     </popupnotification>
+
+#ifdef E10S_TESTING_ONLY
+    <popupnotification id="enable-e10s-notification" hidden="true">
+      <popupnotificationcontent orient="vertical"/>
+    </popupnotification>
+#endif
--- a/browser/base/content/safeMode.js
+++ b/browser/base/content/safeMode.js
@@ -67,17 +67,16 @@ function onExtra1() {
 }
 
 function onLoad() {
   let dialog = document.documentElement;
   if (appStartup.automaticSafeModeNecessary) {
     document.getElementById("autoSafeMode").hidden = false;
     document.getElementById("safeMode").hidden = true;
     if (ResetProfile.resetSupported()) {
-      populateResetPane("resetProfileItems");
       document.getElementById("resetProfile").hidden = false;
     } else {
       // Hide the reset button is it's not supported.
       document.documentElement.getButton("extra1").hidden = true;
     }
   } else {
     if (!ResetProfile.resetSupported()) {
       // Hide the reset button and text if it's not supported.
--- a/browser/base/content/safeMode.xul
+++ b/browser/base/content/safeMode.xul
@@ -16,47 +16,36 @@
 <?xml-stylesheet href="chrome://global/skin/"?>
 <?xml-stylesheet href="chrome://browser/content/safeMode.css"?>
 
 <dialog id="safeModeDialog"
             xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
             title="&safeModeDialog.title;"
             buttons="accept,extra1"
             buttonlabelaccept="&startSafeMode.label;"
-            buttonlabelextra1="&resetProfile.label;"
+            buttonlabelextra1="&refreshProfile.label;"
             maxwidth="&window.maxWidth;"
             ondialogaccept="return onDefaultButton()"
             ondialogcancel="onCancel();"
             ondialogextra1="return onExtra1()"
             onload="onLoad()">
 
   <script type="application/javascript" src="chrome://global/content/resetProfile.js"/>
   <script type="application/javascript" src="chrome://browser/content/safeMode.js"/>
 
   <vbox id="autoSafeMode" hidden="true">
-    <description>&autoSafeModeDescription2.label;</description>
+    <description>&autoSafeModeDescription3.label;</description>
   </vbox>
 
-  <vbox id ="safeMode">
+  <vbox id="safeMode">
     <label>&safeModeDescription3.label;</label>
     <separator class="thin"/>
     <label>&safeModeDescription4.label;</label>
     <separator class="thin"/>
-    <label id="resetProfileInstead">&resetProfileInstead.label;</label>
+    <label id="resetProfileInstead">&refreshProfileInstead.label;</label>
   </vbox>
 
   <vbox id="resetProfile" hidden="true">
-    <label>&resetProfile.dialog.items2.label;</label>
-
-    <vbox id="resetProfileItems" class="indent">
-    </vbox>
-
-    <separator class="thin"/>
-
-    <label id="resetProfileFooter">&resetProfileFooter.label;</label>
-
-    <label>&safeModeInstead.label;</label>
-
-    <separator/>
+    <label id="resetProfileInstead">&refreshProfileInstead.label;</label>
   </vbox>
 
   <separator class="thin"/>
 </dialog>
--- a/browser/base/content/sanitize.js
+++ b/browser/base/content/sanitize.js
@@ -389,35 +389,50 @@ Sanitizer.prototype = {
         return true;
       }
     },
 
     siteSettings: {
       clear: function ()
       {
         // Clear site-specific permissions like "Allow this site to open popups"
+        // we ignore the "end" range and hope it is now() - none of the
+        // interfaces used here support a true range anyway.
+        let startDateMS = this.range == null ? null : this.range[0] / 1000;
         var pm = Components.classes["@mozilla.org/permissionmanager;1"]
                            .getService(Components.interfaces.nsIPermissionManager);
-        pm.removeAll();
+        if (startDateMS == null) {
+          pm.removeAll();
+        } else {
+          pm.removeAllSince(startDateMS);
+        }
 
         // Clear site-specific settings like page-zoom level
         var cps = Components.classes["@mozilla.org/content-pref/service;1"]
                             .getService(Components.interfaces.nsIContentPrefService2);
-        cps.removeAllDomains(null);
+        if (startDateMS == null) {
+          cps.removeAllDomains(null);
+        } else {
+          cps.removeAllDomainsSince(startDateMS, null);
+        }
 
         // Clear "Never remember passwords for this site", which is not handled by
         // the permission manager
+        // (Note the login manager doesn't support date ranges yet, and bug
+        //  1058438 is calling for loginSaving stuff to end up in the
+        // permission manager)
         var pwmgr = Components.classes["@mozilla.org/login-manager;1"]
                               .getService(Components.interfaces.nsILoginManager);
         var hosts = pwmgr.getAllDisabledHosts();
         for each (var host in hosts) {
           pwmgr.setLoginSavingEnabled(host, true);
         }
 
-        // Clear site security settings
+        // Clear site security settings - no support for ranges in this
+        // interface either, so we clearAll().
         var sss = Cc["@mozilla.org/ssservice;1"]
                     .getService(Ci.nsISiteSecurityService);
         sss.clearAll();
       },
 
       get canClear()
       {
         return true;
--- a/browser/base/content/searchSuggestionUI.js
+++ b/browser/base/content/searchSuggestionUI.js
@@ -296,16 +296,17 @@ SearchSuggestionUIController.prototype =
   _speculativeConnect: function () {
     if (this.engineName) {
       this._sendMsg("SpeculativeConnect", this.engineName);
     }
   },
 
   _makeTableRow: function (type, suggestionStr, currentRow, searchWords) {
     let row = document.createElementNS(HTML_NS, "tr");
+    row.dir = "auto";
     row.classList.add("searchSuggestionRow");
     row.classList.add(type);
     row.setAttribute("role", "presentation");
     row.addEventListener("mousemove", this);
     row.addEventListener("mousedown", this);
 
     let entry = document.createElementNS(HTML_NS, "td");
     entry.classList.add("searchSuggestionEntry");
@@ -360,17 +361,16 @@ SearchSuggestionUIController.prototype =
     }
     return row.rowIndex;
   },
 
   _makeTable: function (id) {
     this._table = document.createElementNS(HTML_NS, "table");
     this._table.id = id;
     this._table.hidden = true;
-    this._table.dir = "auto";
     this._table.classList.add("searchSuggestionTable");
     this._table.setAttribute("role", "listbox");
     return this._table;
   },
 
   _sendMsg: function (type, data=null) {
     dispatchEvent(new CustomEvent("ContentSearchClient", {
       detail: {
--- a/browser/base/content/sync/quota.js
+++ b/browser/base/content/sync/quota.js
@@ -156,20 +156,19 @@ let gUsageTreeView = {
 
   /*
    * Handle click events on the tree.
    */
   onTreeClick: function onTreeClick(event) {
     if (event.button == 2)
       return;
 
-    let row = {}, col = {};
-    this.treeBox.getCellAt(event.clientX, event.clientY, row, col, {});
-    if (col.value && col.value.id == "enabled")
-      this.toggle(row.value);
+    let cell = this.treeBox.getCellAt(event.clientX, event.clientY);
+    if (cell.col && cell.col.id == "enabled")
+      this.toggle(cell.row);
   },
 
   /*
    * Toggle enabled state of an engine.
    */
   toggle: function toggle(row) {
     // Update the tree
     let collection = this._collections[row];
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1157,56 +1157,61 @@
                 // Since the user is switching away from a tab that has
                 // a beforeunload prompt active, we remove the prompt.
                 // This prevents confusing user flows like the following:
                 //   1. User attempts to close Firefox
                 //   2. User switches tabs (ingoring a beforeunload prompt)
                 //   3. User returns to tab, presses "Leave page"
                 let promptBox = this.getTabModalPromptBox(oldBrowser);
                 let prompts = promptBox.listPrompts();
-                // NB: This code assumes that the beforeunload prompt
-                //     is the top-most prompt on the tab.
-                promptBox.removePrompt(prompts[prompts.length - 1]);
+                // There might not be any prompts here if the tab was closed
+                // while in an onbeforeunload prompt, which will have
+                // destroyed aforementioned prompt already, so check there's
+                // something to remove, first:
+                if (prompts.length) {
+                  // NB: This code assumes that the beforeunload prompt
+                  //     is the top-most prompt on the tab.
+                  promptBox.removePrompt(prompts[prompts.length - 1]);
+                }
+              }
+
+              oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
+              if (this.isFindBarInitialized(oldTab)) {
+                let findBar = this.getFindBar(oldTab);
+                oldTab._findBarFocused = (!findBar.hidden &&
+                  findBar._findField.getAttribute("focused") == "true");
+              }
+
+              // If focus is in the tab bar, retain it there.
+              if (document.activeElement == oldTab) {
+                // We need to explicitly focus the new tab, because
+                // tabbox.xml does this only in some cases.
+                this.mCurrentTab.focus();
               }
 
               if (!gMultiProcessBrowser)
-                this._adjustFocusAfterTabSwitch(this.mCurrentTab, oldTab);
+                this._adjustFocusAfterTabSwitch(this.mCurrentTab);
             }
 
             this.tabContainer._setPositionalAttributes();
 
             if (!aForceUpdate)
               TelemetryStopwatch.finish("FX_TAB_SWITCH_UPDATE_MS");
           ]]>
         </body>
       </method>
 
       <method name="_adjustFocusAfterTabSwitch">
         <parameter name="newTab"/>
-        <parameter name="oldTab"/>
         <body><![CDATA[
         let newBrowser = this.getBrowserForTab(newTab);
-        let oldBrowser = this.getBrowserForTab(oldTab);
-
-        if (oldBrowser) {
-          oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
-          if (this.isFindBarInitialized(oldTab)) {
-            let findBar = this.getFindBar(oldTab);
-            oldTab._findBarFocused = (!findBar.hidden &&
-              findBar._findField.getAttribute("focused") == "true");
-          }
-        }
-
-        // When focus is in the tab bar, retain it there.
-        if (document.activeElement == oldTab) {
-          // We need to explicitly focus the new tab, because
-          // tabbox.xml does this only in some cases.
-          this.mCurrentTab.focus();
+
+        // Don't steal focus from the tab bar.
+        if (document.activeElement == newTab)
           return;
-        }
 
         // If there's a tabmodal prompt showing, focus it.
         if (newBrowser.hasAttribute("tabmodalPromptShowing")) {
           let XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
           let prompts = newBrowser.parentNode.getElementsByTagNameNS(XUL_NS, "tabmodalprompt");
           let prompt = prompts[prompts.length - 1];
           prompt.Dialog.setDefaultFocus();
           return;
@@ -1936,33 +1941,35 @@
       <method name="_beginRemoveTab">
         <parameter name="aTab"/>
         <parameter name="aTabWillBeMoved"/>
         <parameter name="aCloseWindowWithLastTab"/>
         <parameter name="aCloseWindowFastpath"/>
         <body>
           <![CDATA[
             if (aTab.closing ||
-                aTab._pendingPermitUnload ||
                 this._windowIsClosing)
               return false;
 
             var browser = this.getBrowserForTab(aTab);
-
-            if (!aTabWillBeMoved) {
+            if (!aTab._pendingPermitUnload && !aTabWillBeMoved) {
               let ds = browser.docShell;
               if (ds && ds.contentViewer) {
                 // We need to block while calling permitUnload() because it
                 // processes the event queue and may lead to another removeTab()
                 // call before permitUnload() even returned.
                 aTab._pendingPermitUnload = true;
                 let permitUnload = ds.contentViewer.permitUnload();
                 delete aTab._pendingPermitUnload;
-
-                if (!permitUnload) {
+                // If we were closed during onbeforeunload, we return false now
+                // so we don't (try to) close the same tab again. Of course, we
+                // also stop if the unload was cancelled by the user:
+                if (aTab.closing || !permitUnload) {
+                  // NB: deliberately keep the _closedDuringPermitUnload set to
+                  // true so we keep exiting early in case of multiple calls.
                   return false;
                 }
               }
             }
 
             var closeWindow = false;
             var newTab = false;
             if (this.tabs.length - this._removingTabs.length == 1) {
@@ -3309,17 +3316,17 @@
           }
         ]]></body>
       </method>
 
       <method name="_finalizeTabSwitch">
         <parameter name="toTab"/>
         <parameter name="fromTab"/>
         <body><![CDATA[
-          this._adjustFocusAfterTabSwitch(toTab, fromTab);
+          this._adjustFocusAfterTabSwitch(toTab);
           this._deactivateContent(fromTab);
 
           let toBrowser = this.getBrowserForTab(toTab);
           toBrowser.setAttribute("type", "content-primary");
 
           let fromBrowser = this.getBrowserForTab(fromTab);
           // It's possible that the tab we're switching from closed
           // before we were able to finalize, in which case, fromBrowser
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -50,16 +50,17 @@ support-files =
   file_bug906190_redirected.html
   file_bug906190.js
   file_bug906190.sjs
   file_bug970276_popup1.html
   file_bug970276_popup2.html
   file_bug970276_favicon1.ico
   file_bug970276_favicon2.ico
   file_dom_notifications.html
+  file_double_close_tab.html
   file_favicon_change.html
   file_fullscreen-window-open.html
   get_user_media.html
   head.js
   healthreport_testRemoteCommands.html
   moz.png
   offlineQuotaNotification.cacheManifest
   offlineQuotaNotification.html
@@ -311,16 +312,18 @@ skip-if = e10s
 run-if = datareporting
 [browser_devedition.js]
 [browser_devices_get_user_media.js]
 skip-if = buildapp == 'mulet' || (os == "linux" && debug) || e10s # linux: bug 976544; e10s: Bug 973001 - appears user media notifications only happen in the child and don't make their way to the parent?
 [browser_devices_get_user_media_about_urls.js]
 skip-if = e10s # Bug 973001 - appears user media notifications only happen in the child and don't make their way to the parent?
 [browser_discovery.js]
 skip-if = e10s # Bug 918663 - DOMLinkAdded events don't make their way to chrome
+[browser_double_close_tab.js]
+skip-if = e10s
 [browser_duplicateIDs.js]
 [browser_drag.js]
 skip-if = true # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
 [browser_favicon_change.js]
 skip-if = e10s
 [browser_findbarClose.js]
 skip-if = e10s # Bug ?????? - test directly manipulates content (tries to grab an iframe directly from content)
 [browser_fullscreen-window-open.js]
--- a/browser/base/content/test/general/browser_aboutAccounts.js
+++ b/browser/base/content/test/general/browser_aboutAccounts.js
@@ -1,12 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: window.location is null");
+
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
   "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "fxAccounts",
   "resource://gre/modules/FxAccounts.jsm");
 
 const CHROME_BASE = "chrome://mochitests/content/browser/browser/base/content/test/general/";
--- a/browser/base/content/test/general/browser_aboutHome.js
+++ b/browser/base/content/test/general/browser_aboutHome.js
@@ -1,12 +1,20 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: Assert is null");
+
+
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
   "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
   "resource:///modules/AboutHome.jsm");
 
 const TEST_CONTENT_HELPER = "chrome://mochitests/content/browser/browser/base/content/test/general/aboutHome_content_script.js";
--- a/browser/base/content/test/general/browser_aboutSupport_newtab_security_state.js
+++ b/browser/base/content/test/general/browser_aboutSupport_newtab_security_state.js
@@ -1,11 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: window.location is null");
+
+
 add_task(function* checkIdentityOfAboutSupport() {
   let tab = gBrowser.loadOneTab("about:support", {
     referrerURI: null,
     inBackground: false,
     allowThirdPartyFixup: false,
     relatedToCurrent: false,
     skipAnimation: true,
     allowMixedContent: false
--- a/browser/base/content/test/general/browser_action_searchengine.js
+++ b/browser/base/content/test/general/browser_action_searchengine.js
@@ -38,14 +38,16 @@ add_task(function* () {
       gBrowser.removeTab(tab);
     } catch(ex) { /* tab may have already been closed in case of failure */ }
 
     return promiseClearHistory();
   });
 
   let result = yield promise_first_result("open a search");
   isnot(result, null, "Should have a result");
+  is(result.hasAttribute("image"), false, "Result shouldn't have an image attribute");
+
   let tabPromise = promiseTabLoaded(gBrowser.selectedTab);
   EventUtils.synthesizeMouseAtCenter(result, {});
   yield tabPromise;
 
   is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search");
 });
--- a/browser/base/content/test/general/browser_action_searchengine_alias.js
+++ b/browser/base/content/test/general/browser_action_searchengine_alias.js
@@ -1,42 +1,48 @@
 /**
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  **/
 
- let gOriginalEngine;
+let gOriginalEngine;
 
 add_task(function* () {
-  // This test is only relevant if UnifiedComplete is enabled.
-  if (!Services.prefs.getBoolPref("browser.urlbar.unifiedcomplete"))
-    return;
+  Services.prefs.setBoolPref("browser.urlbar.unifiedcomplete", true);
 
-  Services.search.addEngineWithDetails("MozSearch", "", "moz", "", "GET",
+  let iconURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC";
+  Services.search.addEngineWithDetails("MozSearch", iconURI, "moz", "", "GET",
                                        "http://example.com/?q={searchTerms}");
   let engine = Services.search.getEngineByName("MozSearch");
   gOriginalEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
 
   let tab = gBrowser.selectedTab = gBrowser.addTab();
 
   registerCleanupFunction(() => {
     Services.search.currentEngine = gOriginalEngine;
     let engine = Services.search.getEngineByName("MozSearch");
     Services.search.removeEngine(engine);
+    Services.prefs.clearUserPref("browser.urlbar.unifiedcomplete");
 
     try {
       gBrowser.removeTab(tab);
     } catch(ex) { /* tab may have already been closed in case of failure */ }
 
     return promiseClearHistory();
   });
 
   gURLBar.focus();
   gURLBar.value = "moz open a searc";
   EventUtils.synthesizeKey("h" , {});
   yield promiseSearchComplete();
 
+  let result = gURLBar.popup.richlistbox.children[0];
+  ok(result.hasAttribute("image"), "Result should have an image attribute");
+  // Image attribute gets a suffix (-moz-resolution) added in the value.
+  ok(result.getAttribute("image").startsWith(engine.iconURI.spec),
+     "Image attribute should have the search engine's icon");
+
   EventUtils.synthesizeKey("VK_RETURN" , { });
   yield promiseTabLoaded(gBrowser.selectedTab);
 
   is(gBrowser.selectedBrowser.currentURI.spec, "http://example.com/?q=open+a+search");
 });
--- a/browser/base/content/test/general/browser_devedition.js
+++ b/browser/base/content/test/general/browser_devedition.js
@@ -19,17 +19,19 @@ registerCleanupFunction(() => {
 });
 
 function test() {
   waitForExplicitFinish();
   startTests();
 }
 
 function startTests() {
-  ok (!DevEdition.styleSheet, "There is no devedition style sheet by default.");
+  info ("Setting browser.devedition.theme.enabled to false.");
+  Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, false);
+  ok (!DevEdition.styleSheet, "There is no devedition style sheet when the pref is false.");
 
   info ("Setting browser.devedition.theme.enabled to true.");
   Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, true);
   ok (DevEdition.styleSheet, "There is a devedition stylesheet when no themes are applied and pref is set.");
 
   info ("Adding a lightweight theme.");
   Services.prefs.setBoolPref(PREF_LWTHEME, true);
   ok (!DevEdition.styleSheet, "The devedition stylesheet has been removed when a lightweight theme is applied.");
@@ -48,16 +50,17 @@ function startTests() {
   Services.prefs.clearUserPref(PREF_THEME);
   ok (DevEdition.styleSheet, "The devedition stylesheet is still here when a complete theme is removed.");
 
   info ("Setting browser.devedition.theme.enabled to false.");
   Services.prefs.setBoolPref(PREF_DEVEDITION_THEME, false);
   ok (!DevEdition.styleSheet, "The devedition stylesheet has been removed.");
 
   info ("Checking :root attributes based on devtools theme.");
+  Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light");
   is (document.documentElement.getAttribute("devtoolstheme"), "light",
     "The documentElement has an attribute based on devtools theme.");
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "dark");
   is (document.documentElement.getAttribute("devtoolstheme"), "dark",
     "The documentElement has an attribute based on devtools theme.");
   Services.prefs.setCharPref(PREF_DEVTOOLS_THEME, "light");
   is (document.documentElement.getAttribute("devtoolstheme"), "light",
     "The documentElement has an attribute based on devtools theme.");
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_double_close_tab.js
@@ -0,0 +1,80 @@
+"use strict";
+const TEST_PAGE = "http://mochi.test:8888/browser/browser/base/content/test/general/file_double_close_tab.html";
+let testTab;
+
+function waitForDialog(callback) {
+  function onTabModalDialogLoaded(node) {
+    Services.obs.removeObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded");
+    callback(node);
+  }
+
+  // Listen for the dialog being created
+  Services.obs.addObserver(onTabModalDialogLoaded, "tabmodal-dialog-loaded", false);
+}
+
+function waitForDialogDestroyed(node, callback) {
+  // Now listen for the dialog going away again...
+  let observer = new MutationObserver(function(muts) {
+    if (!node.parentNode) {
+      ok(true, "Dialog is gone");
+      done();
+    }
+  });
+  observer.observe(node.parentNode, {childList: true});
+  let failureTimeout = setTimeout(function() {
+    ok(false, "Dialog should have been destroyed");
+    done();
+  }, 10000);
+
+  function done() {
+    clearTimeout(failureTimeout);
+    observer.disconnect();
+    observer = null;
+    callback();
+  }
+}
+
+add_task(function*() {
+  testTab = gBrowser.selectedTab = gBrowser.addTab();
+  yield promiseTabLoadEvent(testTab, TEST_PAGE);
+  //XXXgijs the reason this has nesting and callbacks rather than promises is
+  // that DOM promises resolve on the next tick. So they're scheduled
+  // in an event queue. So when we spin a new event queue for a modal dialog...
+  // everything gets messed up and the promise's .then callbacks never get
+  // called, despite resolve() being called just fine.
+  let dialogNode = yield new Promise(resolveOuter => {
+    waitForDialog(dialogNode => {
+      waitForDialogDestroyed(dialogNode, () => {
+        let doCompletion = () => setTimeout(resolveOuter, 0);
+        info("Now checking if dialog is destroyed");
+        ok(!dialogNode.parentNode, "onbeforeunload dialog should be gone.");
+        if (dialogNode.parentNode) {
+          // Failed to remove onbeforeunload dialog, so do it ourselves:
+          let leaveBtn = dialogNode.ui.button0;
+          waitForDialogDestroyed(dialogNode, doCompletion);
+          EventUtils.synthesizeMouseAtCenter(leaveBtn, {});
+          return;
+        }
+        doCompletion();
+      });
+      // Click again:
+      document.getAnonymousElementByAttribute(testTab, "anonid", "close-button").click();
+    });
+    // Click once:
+    document.getAnonymousElementByAttribute(testTab, "anonid", "close-button").click();
+  });
+  yield promiseWaitForCondition(() => !testTab.parentNode);
+  ok(!testTab.parentNode, "Tab should be closed completely");
+});
+
+registerCleanupFunction(function() {
+  if (testTab.parentNode) {
+    // Remove the handler, or closing this tab will prove tricky:
+    try {
+      testTab.linkedBrowser.contentWindow.onbeforeunload = null;
+    } catch (ex) {}
+    gBrowser.removeTab(testTab);
+  }
+});
+
+
--- a/browser/base/content/test/general/browser_fxa_oauth.js
+++ b/browser/base/content/test/general/browser_fxa_oauth.js
@@ -1,12 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.docShell is null");
+
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsOAuthClient",
   "resource://gre/modules/FxAccountsOAuthClient.jsm");
 
 const HTTP_PATH = "http://example.com";
 const HTTP_ENDPOINT = "/browser/browser/base/content/test/general/browser_fxa_oauth.html";
--- a/browser/base/content/test/general/browser_notification_tab_switching.js
+++ b/browser/base/content/test/general/browser_notification_tab_switching.js
@@ -1,58 +1,95 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-"use strict";
-
-let tab;
-let notification;
-let notificationURL = "http://example.org/browser/browser/base/content/test/general/file_dom_notifications.html";
-
-function test () {
-  waitForExplicitFinish();
-
-  let pm = Services.perms;
-  registerCleanupFunction(function() {
-    pm.remove(notificationURL, "desktop-notification");
-    gBrowser.removeTab(tab);
-    window.restore();
-  });
-
-  pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
-
-  tab = gBrowser.addTab(notificationURL);
-  tab.linkedBrowser.addEventListener("load", onLoad, true);
-}
-
-function onLoad() {
-  isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
-  tab.linkedBrowser.removeEventListener("load", onLoad, true);
-  let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
-  notification = win.showNotification();
-  notification.addEventListener("show", onAlertShowing);
-}
-
-function onAlertShowing() {
-  info("Notification alert showing");
-  notification.removeEventListener("show", onAlertShowing);
-
-  let alertWindow = findChromeWindowByURI("chrome://global/content/alerts/alert.xul");
-  if (!alertWindow) {
-    todo(false, "Notifications don't use XUL windows on all platforms.");
-    notification.close();
-    finish();
-    return;
-  }
-  gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect);
-  EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), {}, alertWindow);
-  info("Clicked on notification");
-  alertWindow.close();
-}
-
-function onTabSelect() {
-  gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
-  is(gBrowser.selectedTab.linkedBrowser.contentWindow.location.href, notificationURL,
-     "Notification tab should be selected.");
-
-  finish();
-}
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+"use strict";
+
+let tab;
+let notification;
+let notificationURL = "http://example.org/browser/browser/base/content/test/general/file_dom_notifications.html";
+let newWindowOpenedFromTab;
+
+function test () {
+  waitForExplicitFinish();
+
+  let pm = Services.perms;
+  registerCleanupFunction(function() {
+    pm.remove(notificationURL, "desktop-notification");
+    gBrowser.removeTab(tab);
+    window.restore();
+  });
+
+  pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
+
+  tab = gBrowser.addTab(notificationURL);
+  tab.linkedBrowser.addEventListener("load", onLoad, true);
+}
+
+function onLoad() {
+  isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
+  tab.linkedBrowser.removeEventListener("load", onLoad, true);
+  let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
+  win.newWindow = win.open("about:blank", "", "height=100,width=100");
+  newWindowOpenedFromTab = win.newWindow;
+  win.newWindow.addEventListener("load", function() {
+    info("new window loaded");
+    win.newWindow.addEventListener("blur", function b() {
+      info("new window got blur");
+      win.newWindow.removeEventListener("blur", b);
+      notification = win.showNotification1();
+      win.newWindow.addEventListener("focus", onNewWindowFocused);
+      notification.addEventListener("show", onAlertShowing);
+    });
+
+    function waitUntilNewWindowHasFocus() {
+      if (!win.newWindow.document.hasFocus()) {
+        setTimeout(waitUntilNewWindowHasFocus, 50);
+      } else {
+        // Focus another window so that new window gets blur event.
+        gBrowser.selectedTab.linkedBrowser.contentWindow.focus();
+      }
+    }
+    win.newWindow.focus();
+    waitUntilNewWindowHasFocus();
+  });
+}
+
+function onAlertShowing() {
+  info("Notification alert showing");
+  notification.removeEventListener("show", onAlertShowing);
+
+  let alertWindow = findChromeWindowByURI("chrome://global/content/alerts/alert.xul");
+  if (!alertWindow) {
+    todo(false, "Notifications don't use XUL windows on all platforms.");
+    notification.close();
+    newWindowOpenedFromTab.close();
+    finish();
+    return;
+  }
+  gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect);
+  EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), {}, alertWindow);
+  info("Clicked on notification");
+  alertWindow.close();
+}
+
+function onNewWindowFocused(event) {
+  event.target.close();
+  isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
+  // Using timeout to test that something do *not* happen!
+  setTimeout(openSecondNotification, 50);
+}
+
+function openSecondNotification() {
+  isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
+  let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
+  notification = win.showNotification2();
+  notification.addEventListener("show", onAlertShowing);
+}
+
+function onTabSelect() {
+  gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
+  is(gBrowser.selectedTab.linkedBrowser.contentWindow.location.href, notificationURL,
+     "Notification tab should be selected.");
+
+  finish();
+}
--- a/browser/base/content/test/general/browser_scope.js
+++ b/browser/base/content/test/general/browser_scope.js
@@ -1,4 +1,11 @@
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: this.docShell is null");
+
 function test() {
   ok(!!gBrowser, "gBrowser exists");
   is(gBrowser, getBrowser(), "both ways of getting tabbrowser work");
 }
--- a/browser/base/content/test/general/browser_tabs_owner.js
+++ b/browser/base/content/test/general/browser_tabs_owner.js
@@ -1,8 +1,22 @@
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: gBrowser._finalizeTabSwitch is not a function");
+
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: gBrowser._finalizeTabSwitch is not a function");
+
 function test() {
   gBrowser.addTab();
   gBrowser.addTab();
   gBrowser.addTab();
 
   var tabs = gBrowser.tabs;
   var owner;
 
--- a/browser/base/content/test/general/browser_zbug569342.js
+++ b/browser/base/content/test/general/browser_zbug569342.js
@@ -1,12 +1,19 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("");
+
 var gTab = null;
 
 function load(url, cb) {
   gTab = gBrowser.addTab(url);
   gBrowser.addEventListener("load", function (event) {
     if (event.target.location != url)
       return;
 
--- a/browser/base/content/test/general/file_dom_notifications.html
+++ b/browser/base/content/test/general/file_dom_notifications.html
@@ -1,23 +1,40 @@
-<html>
-<head>
-<script>
-"use strict";
-
-function showNotification() {
-  var options = {
-      dir: undefined,
-      lang: undefined,
-      body: "Test body",
-      tag: "Test tag",
-      icon: undefined,
-  };
-  return new Notification("Test title", options);
-}
-</script>
-</head>
-<body>
-<form id="notificationForm" onsubmit="showNotification();">
-  <input type="submit" value="Show notification" id="submit"/>
-</form>
-</body>
-</html>
+<html>
+<head>
+<script>
+"use strict";
+
+function showNotification1() {
+  var options = {
+      dir: undefined,
+      lang: undefined,
+      body: "Test body",
+      tag: "Test tag",
+      icon: undefined,
+  };
+  var n = new Notification("Test title", options);
+  n.addEventListener("click", function(event) {
+    event.preventDefault();
+    dump("Should focus new window.");
+    newWindow.focus();
+  });
+  return n;
+}
+
+function showNotification2() {
+  var options = {
+      dir: undefined,
+      lang: undefined,
+      body: "Test body",
+      tag: "Test tag",
+      icon: undefined,
+  };
+  return new Notification("Test title", options);
+}
+</script>
+</head>
+<body>
+<form id="notificationForm" onsubmit="showNotification();">
+  <input type="submit" value="Show notification" id="submit"/>
+</form>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/file_double_close_tab.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Test for bug 1050638 - clicking tab close button twice should close tab even in beforeunload case</title>
+  </head>
+  <body>
+    This page will block beforeunload. It should still be user-closable at all times.
+    <script>
+      window.onbeforeunload = function() {
+        return "stop";
+      };
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/plugins/blockPluginInfoURL.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1336406310000">
+  <emItems>
+  </emItems>
+  <pluginItems>
+    <pluginItem blockID="p9999">
+      <match name="filename" exp="libnptest\.so|nptest\.dll|Test\.plugin" />
+      <versionRange severity="2"></versionRange>
+      <infoURL>http://test.url.com/</infoURL>
+    </pluginItem>
+  </pluginItems>
+</blocklist>
--- a/browser/base/content/test/plugins/browser.ini
+++ b/browser/base/content/test/plugins/browser.ini
@@ -4,16 +4,17 @@
 # * Bug 921916 - no plugin events
 # * Bug XXXXX - no plugins in content processes ("Error: You cannot use the AddonManager in child processes!")
 # * Bug 866413 - PageInfo doesn't work in e10s [browser_pageInfo_plugins.js]
 # * Bug 921957 - remote webprogress doesn't supply originalURI attribute on the request object [browser_clearplugindata.js]
 skip-if = buildapp == "mulet" || e10s
 support-files =
   blockNoPlugins.xml
   blockPluginHard.xml
+  blockPluginInfoURL.xml
   blockPluginVulnerableNoUpdate.xml
   blockPluginVulnerableUpdatable.xml
   browser_clearplugindata.html
   browser_clearplugindata_noage.html
   head.js
   plugin_add_dynamically.html
   plugin_alternate_content.html
   plugin_big.html
--- a/browser/base/content/test/plugins/browser_pluginnotification.js
+++ b/browser/base/content/test/plugins/browser_pluginnotification.js
@@ -56,16 +56,19 @@ TabOpenListener.prototype = {
 
 function test() {
   waitForExplicitFinish();
   SimpleTest.requestCompleteLog();
   requestLongerTimeout(2);
   registerCleanupFunction(function() {
     clearAllPluginPermissions();
     Services.prefs.clearUserPref("extensions.blocklist.suppressUI");
+    return new Promise(resolve => {
+      setAndUpdateBlocklist(gHttpTestRoot + "blockNoPlugins.xml", resolve);
+    });
   });
   Services.prefs.setBoolPref("extensions.blocklist.suppressUI", true);
 
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY);
   setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Second Test Plug-in");
 
   var newTab = gBrowser.addTab();
   gBrowser.selectedTab = newTab;
@@ -816,10 +819,51 @@ function test24d() {
   }, "Test 24d, plugin should be activated");
 }
 
 function test25() {
   let notification = PopupNotifications.getNotification("click-to-play-plugins");
   ok(notification, "Test 25: There should be a plugin notification even if the plugin was immediately removed");
   ok(notification.dismissed, "Test 25: The notification should be dismissed by default");
 
+  prepareTest26();
+}
+
+function prepareTest26() {
+  info("prepareTest26");
+  let plugin = getTestPlugin();
+  plugin.enabledState = Ci.nsIPluginTag.STATE_ENABLED;
+  setAndUpdateBlocklist(gHttpTestRoot + "blockPluginInfoURL.xml",
+    function() {
+      info("prepareTest26 callback");
+      prepareTest(runAfterPluginBindingAttached(test26), gTestRoot + "plugin_test.html");
+  });
+}
+
+// Tests a page with a blocked plugin in it and make sure the
+// infoURL property from the blocklist file gets used.
+function test26() {
+  info("test26 - Test infoURL");
+  let notification = PopupNotifications.getNotification("click-to-play-plugins");
+
+  // Since the plugin notification is dismissed by default, reshow it.
+  notification.reshow();
+
+  let pluginNode = gTestBrowser.contentDocument.getElementById("test");
+  ok(pluginNode, "Test 26, Found plugin in page");
+  let objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
+  is(objLoadingContent.pluginFallbackType,
+     Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED,
+     "Test 26, plugin fallback type should be PLUGIN_BLOCKLISTED");
+
+  const testUrl = "http://test.url.com/";
+
+  let doc = gTestBrowser.contentDocument;
+  let firstPanelChild = PopupNotifications.panel.firstChild;
+
+  let infoLink = doc.getAnonymousElementByAttribute(
+    firstPanelChild, "anonid", "click-to-play-plugins-notification-link");
+
+  is(infoLink.href, testUrl,
+    "Test 26, the notification URL needs to match the infoURL from the blocklist file.");
+
   finishTest();
 }
--- a/browser/base/content/test/social/browser.ini
+++ b/browser/base/content/test/social/browser.ini
@@ -44,16 +44,17 @@ skip-if = e10s # Bug 915547 (social prov
 skip-if = e10s # Bug 915547 (social providers don't install)
 [browser_social_errorPage.js]
 [browser_social_flyout.js]
 skip-if = e10s # when we backed out bug 1047603, this test broke.
 [browser_social_isVisible.js]
 [browser_social_marks.js]
 skip-if = e10s # Bug 915547 (social providers don't install)
 [browser_social_multiprovider.js]
+skip-if = e10s # Bug 1069162 - lots of orange
 [browser_social_multiworker.js]
 [browser_social_perwindowPB.js]
 [browser_social_sidebar.js]
 [browser_social_status.js]
 skip-if = e10s # Bug 915547 (social providers don't install)
 [browser_social_window.js]
 [browser_social_workercrash.js]
 skip-if = !crashreporter
--- a/browser/base/content/test/social/browser_social_activation.js
+++ b/browser/base/content/test/social/browser_social_activation.js
@@ -1,12 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+///////////////////
+//
+// Whitelisting this test.
+// As part of bug 1077403, the leaking uncaught rejection should be fixed.
+//
+thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: Assert is null");
+
+
 let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
 
 let tabsToRemove = [];
 
 
 function removeAllProviders(callback) {
   // all the providers may have been added.
   function removeProviders() {
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -32,16 +32,17 @@ XPCOMUtils.defineLazyServiceGetter(this,
 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const kSpecialWidgetPfx = "customizableui-special-";
 
 const kPrefCustomizationState        = "browser.uiCustomization.state";
 const kPrefCustomizationAutoAdd      = "browser.uiCustomization.autoAdd";
 const kPrefCustomizationDebug        = "browser.uiCustomization.debug";
 const kPrefDrawInTitlebar            = "browser.tabs.drawInTitlebar";
+const kPrefDeveditionTheme           = "browser.devedition.theme.enabled";
 
 /**
  * The keys are the handlers that are fired when the event type (the value)
  * is fired on the subview. A widget that provides a subview has the option
  * of providing onViewShowing and onViewHiding event handlers.
  */
 const kSubviewEvents = [
   "ViewShowing",
@@ -134,16 +135,17 @@ let gBuildWindows = new Map();
 let gNewElementCount = 0;
 let gGroupWrapperCache = new Map();
 let gSingleWrapperCache = new WeakMap();
 let gListeners = new Set();
 
 let gUIStateBeforeReset = {
   uiCustomizationState: null,
   drawInTitlebar: null,
+  gUIStateBeforeReset: null,
 };
 
 let gModuleName = "[CustomizableUI]";
 #include logging.js
 
 let CustomizableUIInternal = {
   initialize: function() {
     LOG("Initializing");
@@ -2294,23 +2296,25 @@ let CustomizableUIInternal = {
     this._rebuildRegisteredAreas();
 
     gResetting = false;
   },
 
   _resetUIState: function() {
     try {
       gUIStateBeforeReset.drawInTitlebar = Services.prefs.getBoolPref(kPrefDrawInTitlebar);
+      gUIStateBeforeReset.deveditionTheme = Services.prefs.getBoolPref(kPrefDeveditionTheme);
       gUIStateBeforeReset.uiCustomizationState = Services.prefs.getCharPref(kPrefCustomizationState);
     } catch(e) { }
 
     this._resetExtraToolbars();
 
     Services.prefs.clearUserPref(kPrefCustomizationState);
     Services.prefs.clearUserPref(kPrefDrawInTitlebar);
+    Services.prefs.clearUserPref(kPrefDeveditionTheme);
     LOG("State reset");
 
     // Reset placements to make restoring default placements possible.
     gPlacements = new Map();
     gDirtyAreaCache = new Set();
     gSeenWidgets = new Set();
     // Clear the saved state to ensure that defaults will be used.
     gSavedState = null;
@@ -2362,30 +2366,33 @@ let CustomizableUIInternal = {
     }
   },
 
   /**
    * Undoes a previous reset, restoring the state of the UI to the state prior to the reset.
    */
   undoReset: function() {
     if (gUIStateBeforeReset.uiCustomizationState == null ||
-        gUIStateBeforeReset.drawInTitlebar == null) {
+        gUIStateBeforeReset.drawInTitlebar == null ||
+        gUIStateBeforeReset.deveditionTheme == null) {
       return;
     }
     gUndoResetting = true;
 
     let uiCustomizationState = gUIStateBeforeReset.uiCustomizationState;
     let drawInTitlebar = gUIStateBeforeReset.drawInTitlebar;
+    let deveditionTheme = gUIStateBeforeReset.deveditionTheme;
 
     // Need to clear the previous state before setting the prefs
     // because pref observers may check if there is a previous UI state.
     this._clearPreviousUIState();
 
     Services.prefs.setCharPref(kPrefCustomizationState, uiCustomizationState);
     Services.prefs.setBoolPref(kPrefDrawInTitlebar, drawInTitlebar);
+    Services.prefs.setBoolPref(kPrefDeveditionTheme, deveditionTheme);
     this.loadSavedState();
     // If the user just customizes toolbar/titlebar visibility, gSavedState will be null
     // and we don't need to do anything else here:
     if (gSavedState) {
       for (let areaId of Object.keys(gSavedState.placements)) {
         let placements = gSavedState.placements[areaId];
         gPlacements.set(areaId, placements);
       }
@@ -2553,16 +2560,20 @@ let CustomizableUIInternal = {
         }
       }
     }
 
     if (Services.prefs.prefHasUserValue(kPrefDrawInTitlebar)) {
       LOG(kPrefDrawInTitlebar + " pref is non-default");
       return false;
     }
+    if (Services.prefs.prefHasUserValue(kPrefDeveditionTheme)) {
+      LOG(kPrefDeveditionTheme + " pref is non-default");
+      return false;
+    }
 
     return true;
   },
 
   setToolbarVisibility: function(aToolbarId, aIsVisible) {
     // We only persist the attribute the first time.
     let isFirstChangedToolbar = true;
     for (let window of CustomizableUI.windows) {
@@ -3253,17 +3264,18 @@ this.CustomizableUI = {
   /**
    * Can the last Restore Defaults operation be undone.
    *
    * @return A boolean stating whether an undo of the
    *         Restore Defaults can be performed.
    */
   get canUndoReset() {
     return gUIStateBeforeReset.uiCustomizationState != null ||
-           gUIStateBeforeReset.drawInTitlebar != null;
+           gUIStateBeforeReset.drawInTitlebar != null ||
+           gUIStateBeforeReset.deveditionTheme != null;
   },
 
   /**
    * Get the placement of a widget. This is by far the best way to obtain
    * information about what the state of your widget is. The internals of
    * this call are cheap (no DOM necessary) and you will know where the user
    * has put your widget.
    *
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -918,17 +918,17 @@ const CustomizableWidgets = [
     tooltiptext: "email-link-button.tooltiptext3",
     onCommand: function(aEvent) {
       let win = aEvent.view;
       win.MailIntegration.sendLinkForWindow(win.content);
     }
   }, {
     id: "loop-call-button",
     type: "custom",
-    label: "loop-call-button2.label",
+    label: "loop-call-button3.label",
     tooltiptext: "loop-call-button2.tooltiptext",
     defaultArea: CustomizableUI.AREA_NAVBAR,
     introducedInVersion: 1,
     onBuild: function(aDocument) {
       let node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
       node.setAttribute("id", this.id);
       node.classList.add("toolbarbutton-1");
       node.classList.add("chromeclass-toolbar-additional");
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -12,16 +12,18 @@ const kPrefCustomizationDebug = "browser
 const kPrefCustomizationAnimation = "browser.uiCustomization.disableAnimation";
 const kPaletteId = "customization-palette";
 const kAboutURI = "about:customizing";
 const kDragDataTypePrefix = "text/toolbarwrapper-id/";
 const kPlaceholderClass = "panel-customization-placeholder";
 const kSkipSourceNodePref = "browser.uiCustomization.skipSourceNodeCheck";
 const kToolbarVisibilityBtn = "customization-toolbar-visibility-button";
 const kDrawInTitlebarPref = "browser.tabs.drawInTitlebar";
+const kDeveditionThemePref = "browser.devedition.theme.enabled";
+const kDeveditionButtonPref = "browser.devedition.theme.showCustomizeButton";
 const kMaxTransitionDurationMs = 2000;
 
 const kPanelItemContextMenu = "customizationPanelItemContextMenu";
 const kPaletteItemContextMenu = "customizationPaletteItemContextMenu";
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/CustomizableUI.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -64,18 +66,21 @@ function CustomizeMode(aWindow) {
   this.tipPanel = this.document.getElementById("customization-tipPanel");
   let lwthemeButton = this.document.getElementById("customization-lwtheme-button");
   if (Services.prefs.getCharPref("general.skins.selectedSkin") != "classic/1.0") {
     lwthemeButton.setAttribute("hidden", "true");
   }
 #ifdef CAN_DRAW_IN_TITLEBAR
   this._updateTitlebarButton();
   Services.prefs.addObserver(kDrawInTitlebarPref, this, false);
+#endif
+  this._updateDevEditionThemeButton();
+  Services.prefs.addObserver(kDeveditionButtonPref, this, false);
+  Services.prefs.addObserver(kDeveditionThemePref, this, false);
   this.window.addEventListener("unload", this);
-#endif
 };
 
 CustomizeMode.prototype = {
   _changed: false,
   _transitioning: false,
   window: null,
   document: null,
   // areas is used to cache the customizable areas when in customization mode.
@@ -100,16 +105,18 @@ CustomizeMode.prototype = {
   get _handler() {
     return this.window.CustomizationHandler;
   },
 
   uninit: function() {
 #ifdef CAN_DRAW_IN_TITLEBAR
     Services.prefs.removeObserver(kDrawInTitlebarPref, this);
 #endif
+    Services.prefs.removeObserver(kDeveditionButtonPref, this);
+    Services.prefs.removeObserver(kDeveditionThemePref, this);
   },
 
   toggle: function() {
     if (this._handler.isEnteringCustomizeMode || this._handler.isExitingCustomizeMode) {
       this._wantToBeInCustomizeMode = !this._wantToBeInCustomizeMode;
       return;
     }
     if (this._customizing) {
@@ -1442,32 +1449,31 @@ CustomizeMode.prototype = {
       case "mouseup":
         this._onMouseUp(aEvent);
         break;
       case "keypress":
         if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
           this.exit();
         }
         break;
-#ifdef CAN_DRAW_IN_TITLEBAR
       case "unload":
         this.uninit();
         break;
-#endif
     }
   },
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "nsPref:changed":
         this._updateResetButton();
         this._updateUndoResetButton();
 #ifdef CAN_DRAW_IN_TITLEBAR
         this._updateTitlebarButton();
 #endif
+        this._updateDevEditionThemeButton();
         break;
       case "lightweight-theme-window-updated":
         if (aSubject == this.window) {
           aData = JSON.parse(aData);
           if (!aData) {
             this.removeLWTStyling();
           } else {
             this.updateLWTStyling(aData);
@@ -1493,16 +1499,39 @@ CustomizeMode.prototype = {
   },
 
   toggleTitlebar: function(aShouldShowTitlebar) {
     // Drawing in the titlebar means not showing the titlebar, hence the negation:
     Services.prefs.setBoolPref(kDrawInTitlebarPref, !aShouldShowTitlebar);
   },
 #endif
 
+  _updateDevEditionThemeButton: function() {
+    let button = this.document.getElementById("customization-devedition-theme-button");
+
+    let themeEnabled = Services.prefs.getBoolPref(kDeveditionThemePref);
+    if (themeEnabled) {
+      button.setAttribute("checked", "true");
+    } else {
+      button.removeAttribute("checked");
+    }
+
+    let buttonVisible = Services.prefs.getBoolPref(kDeveditionButtonPref);
+    if (buttonVisible) {
+      button.removeAttribute("hidden");
+    } else {
+      button.setAttribute("hidden", "true");
+    }
+  },
+  toggleDevEditionTheme: function() {
+    let button = this.document.getElementById("customization-devedition-theme-button");
+    let preferenceValue = button.hasAttribute("checked");
+    Services.prefs.setBoolPref(kDeveditionThemePref, preferenceValue);
+  },
+
   _onDragStart: function(aEvent) {
     __dumpDragData(aEvent);
     let item = aEvent.target;
     while (item && item.localName != "toolbarpaletteitem") {
       if (item.localName == "toolbar") {
         return;
       }
       item = item.parentNode;
@@ -1871,18 +1900,24 @@ CustomizeMode.prototype = {
     if (!aEvent.dataTransfer.mozTypesAt(0)) {
       return;
     }
 
     let draggedItemId =
       aEvent.dataTransfer.mozGetDataAt(kDragDataTypePrefix + documentId, 0);
 
     let draggedWrapper = document.getElementById("wrapper-" + draggedItemId);
-    draggedWrapper.hidden = false;
-    draggedWrapper.removeAttribute("mousedown");
+
+    // DraggedWrapper might no longer available if a widget node is
+    // destroyed after starting (but before stopping) a drag.
+    if (draggedWrapper) {
+      draggedWrapper.hidden = false;
+      draggedWrapper.removeAttribute("mousedown");
+    }
+
     if (this._dragOverItem) {
       this._cancelDragActive(this._dragOverItem);
       this._dragOverItem = null;
     }
     this._updateToolbarCustomizationOutline(this.window);
     this._showPanelCustomizationPlaceholders();
     DragPositionManager.stop();
   },
--- a/browser/components/customizableui/content/customizeMode.inc.xul
+++ b/browser/components/customizableui/content/customizeMode.inc.xul
@@ -47,16 +47,24 @@
             <toolbarbutton class="customization-lwtheme-menu-footeritem"
                            label="&customizeMode.lwthemes.menuGetMore;"
                            accesskey="&customizeMode.lwthemes.menuGetMore.accessKey;"
                            tabindex="0"
                            oncommand="gCustomizeMode.getMoreThemes(event);"/>
           </hbox>
         </panel>
       </button>
+
+      <button id="customization-devedition-theme-button"
+              class="customizationmode-button"
+              hidden="true"
+              label="&customizeMode.deveditionTheme.label;"
+              oncommand="gCustomizeMode.toggleDevEditionTheme()"
+              type="checkbox" />
+
       <spacer id="customization-footer-spacer"/>
       <button id="customization-undo-reset-button"
               class="customizationmode-button"
               hidden="true"
               oncommand="gCustomizeMode.undoReset();"
               label="&undoCmd.label;"/>
       <button id="customization-reset-button"
               oncommand="gCustomizeMode.reset();"
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -183,17 +183,17 @@
       <vbox class="panel-subview-body">
         <hbox id="PanelUI-panic-timeframe">
           <image id="PanelUI-panic-timeframe-icon" alt=""/>
           <vbox flex="1">
             <hbox id="PanelUI-panic-header">
               <image id="PanelUI-panic-timeframe-icon-small" alt=""/>
               <description id="PanelUI-panic-mainDesc" flex="1">&panicButton.view.mainTimeframeDesc;</description>
             </hbox>
-            <radiogroup id="PanelUI-panic-timeSpan" aria-labelledby="PanelUI-panic-mainDesc">
+            <radiogroup id="PanelUI-panic-timeSpan" aria-labelledby="PanelUI-panic-mainDesc" closemenu="none">
               <radio id="PanelUI-panic-5min" label="&panicButton.view.5min;" selected="true"
                      value="5" class="subviewradio"/>
               <radio id="PanelUI-panic-2hr" label="&panicButton.view.2hr;"
                      value="2" class="subviewradio"/>
               <radio id="PanelUI-panic-day" label="&panicButton.view.day;"
                      value="6" class="subviewradio"/>
             </radiogroup>
           </vbox>
--- a/browser/components/customizableui/test/browser_970511_undo_restore_default.js
+++ b/browser/components/customizableui/test/browser_970511_undo_restore_default.js
@@ -96,12 +96,50 @@ add_task(function() {
   is(Services.prefs.getBoolPref(prefName), !defaultValue, "Undo-reset goes back to previous pref value");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden after undo-reset clicked");
 
   Services.prefs.clearUserPref(prefName);
   ok(CustomizableUI.inDefaultState, "In default state after pref cleared");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden at end of test");
 });
 
+// Bug 1082108 - Restore Defaults should clear user pref for devedition theme
+add_task(function() {
+  let prefName = "browser.devedition.theme.enabled";
+  Services.prefs.setBoolPref("browser.devedition.theme.showCustomizeButton", true);
+  let defaultValue = Services.prefs.getBoolPref(prefName);
+  let restoreDefaultsButton = document.getElementById("customization-reset-button");
+  let deveditionThemeButton = document.getElementById("customization-devedition-theme-button");
+  let undoResetButton = document.getElementById("customization-undo-reset-button");
+  ok(CustomizableUI.inDefaultState, "Should be in default state at start of test");
+  ok(restoreDefaultsButton.disabled, "Restore defaults button should be disabled when in default state");
+  is(deveditionThemeButton.hasAttribute("checked"), defaultValue, "Devedition theme button should reflect pref value");
+  is(undoResetButton.hidden, true, "Undo reset button should be hidden at start of test");
+  Services.prefs.setBoolPref(prefName, !defaultValue);
+  ok(!restoreDefaultsButton.disabled, "Restore defaults button should be enabled when pref changed");
+  is(deveditionThemeButton.hasAttribute("checked"), !defaultValue, "Devedition theme button should reflect changed pref value");
+  ok(!CustomizableUI.inDefaultState, "With devedition theme flipped, no longer default");
+  is(undoResetButton.hidden, true, "Undo reset button should be hidden after pref change");
+
+  yield gCustomizeMode.reset();
+  ok(restoreDefaultsButton.disabled, "Restore defaults button should be disabled after reset");
+  is(deveditionThemeButton.hasAttribute("checked"), defaultValue, "devedition theme button should reflect default value after reset");
+  is(Services.prefs.getBoolPref(prefName), defaultValue, "Reset should reset devedition.theme.enabled");
+  ok(CustomizableUI.inDefaultState, "In default state after devedition theme reset");
+  is(undoResetButton.hidden, false, "Undo reset button should be visible after reset");
+  ok(!undoResetButton.disabled, "Undo reset button should be enabled after reset");
+
+  yield gCustomizeMode.undoReset();
+  ok(!restoreDefaultsButton.disabled, "Restore defaults button should be enabled after undo-reset");
+  is(deveditionThemeButton.hasAttribute("checked"), !defaultValue, "devedition theme button should reflect undo-reset value");
+  ok(!CustomizableUI.inDefaultState, "No longer in default state after undo");
+  is(Services.prefs.getBoolPref(prefName), !defaultValue, "Undo-reset goes back to previous pref value");
+  is(undoResetButton.hidden, true, "Undo reset button should be hidden after undo-reset clicked");
+
+  Services.prefs.clearUserPref(prefName);
+  ok(CustomizableUI.inDefaultState, "In default state after pref cleared");
+  is(undoResetButton.hidden, true, "Undo reset button should be hidden at end of test");
+});
+
 add_task(function asyncCleanup() {
   yield gCustomizeMode.reset();
   yield endCustomizing();
 });
--- a/browser/components/downloads/DownloadsCommon.jsm
+++ b/browser/components/downloads/DownloadsCommon.jsm
@@ -62,16 +62,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "RecentWindow",
                                   "resource:///modules/RecentWindow.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
                                   "resource://gre/modules/Promise.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "Task",
+                                  "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DownloadsLogger",
                                   "resource:///modules/DownloadsLogger.jsm");
 
 const nsIDM = Ci.nsIDownloadManager;
 
 const kDownloadsStringBundleUrl =
   "chrome://browser/locale/downloads/downloads.properties";
 
@@ -138,16 +140,23 @@ PrefObserver.register({
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadsCommon
 
 /**
  * This object is exposed directly to the consumers of this JavaScript module,
  * and provides shared methods for all the instances of the user interface.
  */
 this.DownloadsCommon = {
+  /**
+   * Constants with the different types of unblock messages.
+   */
+  BLOCK_VERDICT_MALWARE: "Malware",
+  BLOCK_VERDICT_POTENTIALLY_UNWANTED: "PotentiallyUnwanted",
+  BLOCK_VERDICT_UNCOMMON: "Uncommon",
+
   log: function DC_log(...aMessageArgs) {
     delete this.log;
     this.log = function DC_log(...aMessageArgs) {
       if (!PrefObserver.debug) {
         return;
       }
       DownloadsLogger.log.apply(DownloadsLogger, aMessageArgs);
     }
@@ -506,17 +515,79 @@ this.DownloadsCommon = {
           // If launch also fails (probably because it's not implemented), let
           // the OS handler try to open the parent.
           Cc["@mozilla.org/uriloader/external-protocol-service;1"]
             .getService(Ci.nsIExternalProtocolService)
             .loadUrl(NetUtil.newURI(parent));
         }
       }
     }
-  }
+  },
+
+  /**
+   * Displays an alert message box which asks the user if they want to
+   * unblock the downloaded file or not.
+   *
+   * @param aType
+   *        The type of malware the downloaded file contains.
+   * @param aOwnerWindow
+   *        The window with which this action is associated.
+   *
+   * @return True to unblock the file, false to keep the user safe and
+   *         cancel the operation.
+   */
+  confirmUnblockDownload: Task.async(function* DP_confirmUnblockDownload(aType, aOwnerWindow) {
+    let s = DownloadsCommon.strings;
+    let title = s.unblockHeader;
+    let buttonFlags = (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
+                      (Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1);
+    let type = "";
+    let message = s.unblockTip;
+    let okButton = s.unblockButtonContinue;
+    let cancelButton = s.unblockButtonCancel;
+
+    switch (aType) {
+      case this.BLOCK_VERDICT_MALWARE:
+        type = s.unblockTypeMalware;
+        break;
+      case this.BLOCK_VERDICT_POTENTIALLY_UNWANTED:
+        type = s.unblockTypePotentiallyUnwanted;
+        break;
+      case this.BLOCK_VERDICT_UNCOMMON:
+        type = s.unblockTypeUncommon;
+        break;
+    }
+
+    if (type) {
+      message = type + "\n\n" + message;
+    }
+
+    Services.ww.registerNotification(function onOpen(subj, topic) {
+      if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
+        // Make sure to listen for "DOMContentLoaded" because it is fired
+        // before the "load" event.
+        subj.addEventListener("DOMContentLoaded", function onLoad() {
+          subj.removeEventListener("DOMContentLoaded", onLoad);
+          if (subj.document.documentURI ==
+              "chrome://global/content/commonDialog.xul") {
+            Services.ww.unregisterNotification(onOpen);
+            let dialog = subj.document.getElementById("commonDialog");
+            if (dialog) {
+              // Change the dialog to use a warning icon.
+              dialog.classList.add("alert-dialog");
+            }
+          }
+        });
+      }
+    });
+
+    let rv = Services.prompt.confirmEx(aOwnerWindow, title, message, buttonFlags,
+                                       cancelButton, okButton, null, null, {});
+    return (rv == 1);
+  }),
 };
 
 /**
  * Returns true if we are executing on Windows Vista or a later version.
  */
 XPCOMUtils.defineLazyGetter(DownloadsCommon, "isWinVistaOrHigher", function () {
   let os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
   if (os != "WINNT") {
--- a/browser/components/downloads/test/browser/browser.ini
+++ b/browser/components/downloads/test/browser/browser.ini
@@ -2,8 +2,9 @@
 support-files = head.js
 
 [browser_basic_functionality.js]
 skip-if = buildapp == "mulet" || e10s
 [browser_first_download_panel.js]
 skip-if = os == "linux" # Bug 949434
 [browser_overflow_anchor.js]
 skip-if = os == "linux" # Bug 952422
+[browser_confirm_unblock_download.js]
--- a/browser/components/downloads/test/browser/browser_basic_functionality.js
+++ b/browser/components/downloads/test/browser/browser_basic_functionality.js
@@ -1,57 +1,55 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+registerCleanupFunction(function*() {
+  yield task_resetState();
+});
+
 /**
  * Make sure the downloads panel can display items in the right order and
  * contains the expected data.
  */
-function test_task()
-{
+add_task(function* test_basic_functionality() {
   // Display one of each download state.
   const DownloadData = [
     { state: nsIDM.DOWNLOAD_NOTSTARTED },
     { state: nsIDM.DOWNLOAD_PAUSED },
     { state: nsIDM.DOWNLOAD_FINISHED },
     { state: nsIDM.DOWNLOAD_FAILED },
     { state: nsIDM.DOWNLOAD_CANCELED },
   ];
 
-  try {
-    // Wait for focus first
-    yield promiseFocus();
+  // Wait for focus first
+  yield promiseFocus();
 
-    // Ensure that state is reset in case previous tests didn't finish.
-    yield task_resetState();
+  // Ensure that state is reset in case previous tests didn't finish.
+  yield task_resetState();
 
-    // For testing purposes, show all the download items at once.
-    var originalCountLimit = DownloadsView.kItemCountLimit;
-    DownloadsView.kItemCountLimit = DownloadData.length;
-    registerCleanupFunction(function () {
-      DownloadsView.kItemCountLimit = originalCountLimit;
-    });
+  // For testing purposes, show all the download items at once.
+  var originalCountLimit = DownloadsView.kItemCountLimit;
+  DownloadsView.kItemCountLimit = DownloadData.length;
+  registerCleanupFunction(function () {
+    DownloadsView.kItemCountLimit = originalCountLimit;
+  });
 
-    // Populate the downloads database with the data required by this test.
-    yield task_addDownloads(DownloadData);
+  // Populate the downloads database with the data required by this test.
+  yield task_addDownloads(DownloadData);
 
-    // Open the user interface and wait for data to be fully loaded.
-    yield task_openPanel();
+  // Open the user interface and wait for data to be fully loaded.
+  yield task_openPanel();
 
-    // Test item data and count.  This also tests the ordering of the display.
-    let richlistbox = document.getElementById("downloadsListBox");
-/* disabled for failing intermittently (bug 767828)
+  // Test item data and count.  This also tests the ordering of the display.
+  let richlistbox = document.getElementById("downloadsListBox");
+  /* disabled for failing intermittently (bug 767828)
     is(richlistbox.children.length, DownloadData.length,
        "There is the correct number of richlistitems");
-*/
-    let itemCount = richlistbox.children.length;
-    for (let i = 0; i < itemCount; i++) {
-      let element = richlistbox.children[itemCount - i - 1];
-      let dataItem = new DownloadsViewItemController(element).dataItem;
-      is(dataItem.state, DownloadData[i].state, "Download states match up");
-    }
-  } finally {
-    // Clean up when the test finishes.
-    yield task_resetState();
+  */
+  let itemCount = richlistbox.children.length;
+  for (let i = 0; i < itemCount; i++) {
+    let element = richlistbox.children[itemCount - i - 1];
+    let dataItem = new DownloadsViewItemController(element).dataItem;
+    is(dataItem.state, DownloadData[i].state, "Download states match up");
   }
-}
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/downloads/test/browser/browser_confirm_unblock_download.js
@@ -0,0 +1,46 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests the dialog which allows the user to unblock a downloaded file.
+
+registerCleanupFunction(() => {});
+
+function addDialogOpenObserver(buttonAction) {
+  Services.ww.registerNotification(function onOpen(subj, topic, data) {
+    if (topic == "domwindowopened" && subj instanceof Ci.nsIDOMWindow) {
+      // The test listens for the "load" event which guarantees that the alert
+      // class has already been added (it is added when "DOMContentLoaded" is
+      // fired).
+      subj.addEventListener("load", function onLoad() {
+        subj.removeEventListener("load", onLoad);
+        if (subj.document.documentURI ==
+            "chrome://global/content/commonDialog.xul") {
+          Services.ww.unregisterNotification(onOpen);
+
+          let dialog = subj.document.getElementById("commonDialog");
+          ok(dialog.classList.contains("alert-dialog"),
+             "The dialog element should contain an alert class.");
+
+          let doc = subj.document.documentElement;
+          doc.getButton(buttonAction).click();
+        }
+      });
+    }
+  });
+}
+
+add_task(function* test_confirm_unblock_dialog_unblock() {
+  addDialogOpenObserver("cancel");
+  let result = yield DownloadsCommon.confirmUnblockDownload(DownloadsCommon.UNBLOCK_MALWARE,
+                                                            window);
+  ok(result, "Should return true when the user clicks on `Unblock` button.");
+});
+
+add_task(function* test_confirm_unblock_dialog_keep_safe() {
+  addDialogOpenObserver("accept");
+  let result = yield DownloadsCommon.confirmUnblockDownload(DownloadsCommon.UNBLOCK_MALWARE,
+                                                            window);
+  ok(!result, "Should return false when the user clicks on `Keep me safe` button.");
+});
--- a/browser/components/downloads/test/browser/browser_first_download_panel.js
+++ b/browser/components/downloads/test/browser/browser_first_download_panel.js
@@ -3,63 +3,55 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Make sure the downloads panel only opens automatically on the first
  * download it notices. All subsequent downloads, even across sessions, should
  * not open the panel automatically.
  */
-function test_task()
-{
+add_task(function* test_first_download_panel() {
   // Clear the download panel has shown preference first as this test is used to
   // verify this preference's behaviour.
-  let oldPrefValue = true;
-  try {
-    oldPrefValue = Services.prefs.getBoolPref("browser.download.panel.shown");
-  } catch(ex) { }
+  let oldPrefValue = Services.prefs.getBoolPref("browser.download.panel.shown");
   Services.prefs.setBoolPref("browser.download.panel.shown", false);
 
-  try {
-    // Ensure that state is reset in case previous tests didn't finish.
+  registerCleanupFunction(function*() {
+    // Clean up when the test finishes.
     yield task_resetState();
 
-    // With this set to false, we should automatically open the panel the first
-    // time a download is started.
-    DownloadsCommon.getData(window).panelHasShownBefore = false;
-
-    let promise = promisePanelOpened();
-    DownloadsCommon.getData(window)._notifyDownloadEvent("start");
-    yield promise;
-
-    // If we got here, that means the panel opened.
-    DownloadsPanel.hidePanel();
-
-    ok(DownloadsCommon.getData(window).panelHasShownBefore,
-       "Should have recorded that the panel was opened on a download.")
-
-    // Next, make sure that if we start another download, we don't open the
-    // panel automatically.
-    let originalOnPopupShown = DownloadsPanel.onPopupShown;
-    DownloadsPanel.onPopupShown = function () {
-      originalOnPopupShown.apply(this, arguments);
-      ok(false, "Should not have opened the downloads panel.");
-    };
-
-    try {
-      DownloadsCommon.getData(window)._notifyDownloadEvent("start");
-
-      // Wait 2 seconds to ensure that the panel does not open.
-      let deferTimeout = Promise.defer();
-      setTimeout(deferTimeout.resolve, 2000);
-      yield deferTimeout.promise;
-    } finally {
-      DownloadsPanel.onPopupShown = originalOnPopupShown;
-    }
-  } finally {
-    // Clean up when the test finishes.
-    yield task_resetState();
     // Set the preference instead of clearing it afterwards to ensure the
     // right value is used no matter what the default was. This ensures the
     // panel doesn't appear and affect other tests.
     Services.prefs.setBoolPref("browser.download.panel.shown", oldPrefValue);
-  }
-}
+  });
+
+  // Ensure that state is reset in case previous tests didn't finish.
+  yield task_resetState();
+
+  // With this set to false, we should automatically open the panel the first
+  // time a download is started.
+  DownloadsCommon.getData(window).panelHasShownBefore = false;
+
+  let promise = promisePanelOpened();
+  DownloadsCommon.getData(window)._notifyDownloadEvent("start");
+  yield promise;
+
+  // If we got here, that means the panel opened.
+  DownloadsPanel.hidePanel();
+
+  ok(DownloadsCommon.getData(window).panelHasShownBefore,
+     "Should have recorded that the panel was opened on a download.")
+
+  // Next, make sure that if we start another download, we don't open the
+  // panel automatically.
+  let originalOnPopupShown = DownloadsPanel.onPopupShown;
+  DownloadsPanel.onPopupShown = function () {
+    originalOnPopupShown.apply(this, arguments);
+    ok(false, "Should not have opened the downloads panel.");
+  };
+
+  DownloadsCommon.getData(window)._notifyDownloadEvent("start");
+
+  // Wait 2 seconds to ensure that the panel does not open.
+  yield new Promise(resolve => setTimeout(resolve, 2000));
+  DownloadsPanel.onPopupShown = originalOnPopupShown;
+});
--- a/browser/components/downloads/test/browser/browser_overflow_anchor.js
+++ b/browser/components/downloads/test/browser/browser_overflow_anchor.js
@@ -1,74 +1,74 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+registerCleanupFunction(function*() {
+  // Clean up when the test finishes.
+  yield task_resetState();
+});
+
 /**
  * Make sure the downloads button and indicator overflows into the nav-bar
  * chevron properly, and then when those buttons are clicked in the overflow
  * panel that the downloads panel anchors to the chevron.
  */
-function test_task() {
-  try {
-    // Ensure that state is reset in case previous tests didn't finish.
-    yield task_resetState();
+add_task(function* test_overflow_anchor() {
+  // Ensure that state is reset in case previous tests didn't finish.
+  yield task_resetState();
 
-    // Record the original width of the window so we can put it back when
-    // this test finishes.
-    let oldWidth = window.outerWidth;
+  // Record the original width of the window so we can put it back when
+  // this test finishes.
+  let oldWidth = window.outerWidth;
 
-    // The downloads button should not be overflowed to begin with.
-    let button = CustomizableUI.getWidget("downloads-button")
-                               .forWindow(window);
-    ok(!button.overflowed, "Downloads button should not be overflowed.");
+  // The downloads button should not be overflowed to begin with.
+  let button = CustomizableUI.getWidget("downloads-button")
+                             .forWindow(window);
+  ok(!button.overflowed, "Downloads button should not be overflowed.");
 
-    // Hack - we lock the size of the default flex-y items in the nav-bar,
-    // namely, the URL and search inputs. That way we can resize the
-    // window without worrying about them flexing.
-    const kFlexyItems = ["urlbar-container", "search-container"];
-    registerCleanupFunction(() => unlockWidth(kFlexyItems));
-    lockWidth(kFlexyItems);
+  // Hack - we lock the size of the default flex-y items in the nav-bar,
+  // namely, the URL and search inputs. That way we can resize the
+  // window without worrying about them flexing.
+  const kFlexyItems = ["urlbar-container", "search-container"];
+  registerCleanupFunction(() => unlockWidth(kFlexyItems));
+  lockWidth(kFlexyItems);
 
-    // Resize the window to half of its original size. That should
-    // be enough to overflow the downloads button.
-    window.resizeTo(oldWidth / 2, window.outerHeight);
-    yield waitForOverflowed(button, true);
+  // Resize the window to half of its original size. That should
+  // be enough to overflow the downloads button.
+  window.resizeTo(oldWidth / 2, window.outerHeight);
+  yield waitForOverflowed(button, true);
 
-    let promise = promisePanelOpened();
-    button.node.doCommand();
-    yield promise;
-
-    let panel = DownloadsPanel.panel;
-    let chevron = document.getElementById("nav-bar-overflow-button");
-    is(panel.anchorNode, chevron, "Panel should be anchored to the chevron.");
+  let promise = promisePanelOpened();
+  button.node.doCommand();
+  yield promise;
 
-    DownloadsPanel.hidePanel();
+  let panel = DownloadsPanel.panel;
+  let chevron = document.getElementById("nav-bar-overflow-button");
+  is(panel.anchorNode, chevron, "Panel should be anchored to the chevron.");
 
-    // Unlock the widths on the flex-y items.
-    unlockWidth(kFlexyItems);
+  DownloadsPanel.hidePanel();
 
-    // Put the window back to its original dimensions.
-    window.resizeTo(oldWidth, window.outerHeight);
+  // Unlock the widths on the flex-y items.
+  unlockWidth(kFlexyItems);
 
-    // The downloads button should eventually be un-overflowed.
-    yield waitForOverflowed(button, false);
+  // Put the window back to its original dimensions.
+  window.resizeTo(oldWidth, window.outerHeight);
 
-    // Now try opening the panel again.
-    promise = promisePanelOpened();
-    button.node.doCommand();
-    yield promise;
+  // The downloads button should eventually be un-overflowed.
+  yield waitForOverflowed(button, false);
 
-    is(panel.anchorNode.id, "downloads-indicator-anchor");
+  // Now try opening the panel again.
+  promise = promisePanelOpened();
+  button.node.doCommand();
+  yield promise;
 
-    DownloadsPanel.hidePanel();
-  } finally {
-    // Clean up when the test finishes.
-    yield task_resetState();
-  }
-}
+  is(panel.anchorNode.id, "downloads-indicator-anchor");
+
+  DownloadsPanel.hidePanel();
+});
 
 /**
  * For some node IDs, finds the nodes and sets their min-width's to their
  * current width, preventing them from flex-shrinking.
  *
  * @param aItemIDs an array of item IDs to set min-width on.
  */
 function lockWidth(aItemIDs) {
--- a/browser/components/downloads/test/browser/head.js
+++ b/browser/components/downloads/test/browser/head.js
@@ -24,25 +24,16 @@ const nsIDM = Ci.nsIDownloadManager;
 
 let gTestTargetFile = FileUtils.getFile("TmpD", ["dm-ui-test.file"]);
 gTestTargetFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
 registerCleanupFunction(function () {
   gTestTargetFile.remove(false);
 });
 
 ////////////////////////////////////////////////////////////////////////////////
-//// Infrastructure
-
-function test()
-{
-  waitForExplicitFinish();
-  Task.spawn(test_task).then(null, ex => ok(false, ex)).then(finish);
-}
-
-////////////////////////////////////////////////////////////////////////////////
 //// Asynchronous support subroutines
 
 function promiseFocus()
 {
   let deferred = Promise.defer();
   waitForFocus(deferred.resolve);
   return deferred.promise;
 }
--- a/browser/components/feeds/FeedWriter.js
+++ b/browser/components/feeds/FeedWriter.js
@@ -853,17 +853,16 @@ FeedWriter.prototype = {
            * Application" item is being selected with the keyboard. We do this
            * by ignoring command events while the dropdown is closed (user
            * arrowing through the combobox), but handling them while the
            * combobox dropdown is open (user pressed enter when an item was
            * selected). If we don't show the filepicker here, it will be shown
            * when clicking "Subscribe Now".
            */
           var popupbox = this._handlersMenuList.firstChild.boxObject;
-          popupbox.QueryInterface(Components.interfaces.nsIPopupBoxObject);
           if (popupbox.popupState == "hiding") {
             this._chooseClientApp(function(aResult) {
               if (!aResult) {
                 // Select the (per-prefs) selected handler if no application
                 // was selected
                 this._setSelectedHandler(this._getFeedType());
               }
             }.bind(this));
--- a/browser/components/loop/GoogleImporter.jsm
+++ b/browser/components/loop/GoogleImporter.jsm
@@ -446,17 +446,17 @@ this.GoogleImporter.prototype = {
     // Process telephone numbers.
     let phoneNodes = entry.getElementsByTagNameNS(kNS_GD, "phoneNumber");
     if (phoneNodes.length) {
       contact.tel = [];
       for (let [,phoneNode] of Iterator(phoneNodes)) {
         contact.tel.push({
           pref: (phoneNode.getAttribute("primary") == "true"),
           type: [getFieldType(phoneNode)],
-          value: phoneNode.firstChild.nodeValue
+          value: phoneNode.getAttribute("uri").replace("tel:", "")
         });
       }
     }
 
     let orgNodes = entry.getElementsByTagNameNS(kNS_GD, "organization");
     if (orgNodes.length) {
       contact.org = [];
       contact.jobTitle = [];
@@ -496,17 +496,17 @@ this.GoogleImporter.prototype = {
           try {
             email = getPreferred(contact);
           } catch (ex) {}
           if (email) {
             contact.name = [email.value];
           } else {
             let tel;
             try {
-              tel = getPreferred(contact, "phone");
+              tel = getPreferred(contact, "tel");
             } catch (ex) {}
             if (tel) {
               contact.name = [tel.value];
             }
           }
         }
       }
     }
--- a/browser/components/loop/MozLoopAPI.jsm
+++ b/browser/components/loop/MozLoopAPI.jsm
@@ -5,18 +5,21 @@
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://services-common/utils.js");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource:///modules/loop/MozLoopService.jsm");
-Cu.import("resource:///modules/loop/LoopContacts.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "LoopContacts",
+                                        "resource:///modules/loop/LoopContacts.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "LoopStorage",
+                                        "resource:///modules/loop/LoopStorage.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "hookWindowCloseForPanelClose",
                                         "resource://gre/modules/MozSocialAPI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
                                         "resource://gre/modules/PluralForm.jsm");
 XPCOMUtils.defineLazyGetter(this, "appInfo", function() {
   return Cc["@mozilla.org/xre/app-info;1"]
            .getService(Ci.nsIXULAppInfo)
            .QueryInterface(Ci.nsIXULRuntime);
@@ -35,17 +38,27 @@ this.EXPORTED_SYMBOLS = ["injectLoopAPI"
  * object.
  *
  * @param {Error}        error        Error object to copy
  * @param {nsIDOMWindow} targetWindow The content window to attach the API
  */
 const cloneErrorObject = function(error, targetWindow) {
   let obj = new targetWindow.Error();
   for (let prop of Object.getOwnPropertyNames(error)) {
-    obj[prop] = String(error[prop]);
+    let value = error[prop];
+    if (typeof value != "string" && typeof value != "number") {
+      value = String(value);
+    }
+
+    Object.defineProperty(Cu.waiveXrays(obj), prop, {
+      configurable: false,
+      enumerable: true,
+      value: value,
+      writable: false
+    });
   }
   return obj;
 };
 
 /**
  * Makes an object or value available to an unprivileged target window.
  *
  * Primitives are returned as they are, while objects are cloned into the
@@ -216,16 +229,22 @@ function injectLoopAPI(targetWindow) {
      * @returns {Object} The contacts API object
      */
     contacts: {
       enumerable: true,
       get: function() {
         if (contactsAPI) {
           return contactsAPI;
         }
+
+        // Make a database switch when a userProfile is active already.
+        let profile = MozLoopService.userProfile;
+        if (profile) {
+          LoopStorage.switchDatabase(profile.uid);
+        }
         return contactsAPI = injectObjectAPI(LoopContacts, targetWindow);
       }
     },
 
     /**
      * Import a list of (new) contacts from an external data source.
      *
      * @param {Object}   options  Property bag of options for the importer
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -1600,21 +1600,31 @@ this.MozLoopService = {
 
     // clearError calls notifyStatusChanged so should be done last when the
     // state is clean.
     MozLoopServiceInternal.clearError("registration");
     MozLoopServiceInternal.clearError("login");
     MozLoopServiceInternal.clearError("profile");
   }),
 
-  openFxASettings: function() {
-    let url = new URL("/settings", gFxAOAuthClient.parameters.content_uri);
-    let win = Services.wm.getMostRecentWindow("navigator:browser");
-    win.switchToTabHavingURI(url.toString(), true);
-  },
+  openFxASettings: Task.async(function() {
+    try {
+      let fxAOAuthClient = yield MozLoopServiceInternal.promiseFxAOAuthClient();
+      if (!fxAOAuthClient) {
+        log.error("Could not get the OAuth client");
+        return;
+      }
+
+      let url = new URL("/settings", fxAOAuthClient.parameters.content_uri);
+      let win = Services.wm.getMostRecentWindow("navigator:browser");
+      win.switchToTabHavingURI(url.toString(), true);
+    } catch (ex) {
+      log.error("Error opening FxA settings", ex);
+    }
+  }),
 
   /**
    * Performs a hawk based request to the loop server.
    *
    * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for the request.
    *                                        One of the LOOP_SESSION_TYPE members.
    * @param {String} path The path to make the request to.
    * @param {String} method The request method, e.g. 'POST', 'GET'.
--- a/browser/components/loop/content/conversation.html
+++ b/browser/components/loop/content/conversation.html
@@ -15,30 +15,32 @@
 
     <div id="messages"></div>
 
     <div id="main"></div>
 
     <script type="text/javascript" src="loop/libs/l10n.js"></script>
     <script type="text/javascript" src="loop/js/otconfig.js"></script>
     <script type="text/javascript" src="loop/libs/sdk.js"></script>
-    <script type="text/javascript" src="loop/shared/libs/react-0.11.1.js"></script>
+    <script type="text/javascript" src="loop/shared/libs/react-0.11.2.js"></script>
     <script type="text/javascript" src="loop/shared/libs/jquery-2.1.0.js"></script>
     <script type="text/javascript" src="loop/shared/libs/lodash-2.4.1.js"></script>
     <script type="text/javascript" src="loop/shared/libs/backbone-1.1.2.js"></script>
 
     <script type="text/javascript" src="loop/shared/js/utils.js"></script>
     <script type="text/javascript" src="loop/shared/js/models.js"></script>
     <script type="text/javascript" src="loop/shared/js/mixins.js"></script>
     <script type="text/javascript" src="loop/shared/js/views.js"></script>
     <script type="text/javascript" src="loop/shared/js/feedbackApiClient.js"></script>
     <script type="text/javascript" src="loop/shared/js/actions.js"></script>
     <script type="text/javascript" src="loop/shared/js/validate.js"></script>
     <script type="text/javascript" src="loop/shared/js/dispatcher.js"></script>
     <script type="text/javascript" src="loop/shared/js/otSdkDriver.js"></script>
     <script type="text/javascript" src="loop/shared/js/conversationStore.js"></script>
+    <script type="text/javascript" src="loop/shared/js/localRoomStore.js"></script>
     <script type="text/javascript" src="loop/js/conversationViews.js"></script>
     <script type="text/javascript" src="loop/shared/js/websocket.js"></script>
     <script type="text/javascript" src="loop/js/client.js"></script>
     <script type="text/javascript" src="loop/js/conversationViews.js"></script>
+    <script type="text/javascript" src="loop/js/roomViews.js"></script>
     <script type="text/javascript" src="loop/js/conversation.js"></script>
   </body>
 </html>
--- a/browser/components/loop/content/js/conversation.js
+++ b/browser/components/loop/content/js/conversation.js
@@ -9,17 +9,21 @@
 
 var loop = loop || {};
 loop.conversation = (function(mozL10n) {
   "use strict";
 
   var sharedViews = loop.shared.views;
   var sharedMixins = loop.shared.mixins;
   var sharedModels = loop.shared.models;
+  var sharedActions = loop.shared.actions;
+
   var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
+  var CallIdentifierView = loop.conversationViews.CallIdentifierView;
+  var EmptyRoomView = loop.roomViews.EmptyRoomView;
 
   var IncomingCallView = React.createClass({displayName: 'IncomingCallView',
     mixins: [sharedMixins.DropdownMenuMixin],
 
     propTypes: {
       model: React.PropTypes.object.isRequired,
       video: React.PropTypes.bool.isRequired
     },
@@ -89,19 +93,24 @@ loop.conversation = (function(mozL10n) {
 
     render: function() {
       /* jshint ignore:start */
       var dropdownMenuClassesDecline = React.addons.classSet({
         "native-dropdown-menu": true,
         "conversation-window-dropdown": true,
         "visually-hidden": !this.state.showMenu
       });
+
       return (
         React.DOM.div({className: "call-window"}, 
-          React.DOM.h2(null, mozL10n.get("incoming_call_title2")), 
+          CallIdentifierView({video: this.props.video, 
+            peerIdentifier: this.props.model.getCallIdentifier(), 
+            urlCreationDate: this.props.model.get("urlCreationDate"), 
+            showIcons: true}), 
+
           React.DOM.div({className: "btn-group call-action-group"}, 
 
             React.DOM.div({className: "fx-embedded-call-button-spacer"}), 
 
             React.DOM.div({className: "btn-chevron-menu-group"}, 
               React.DOM.div({className: "btn-group-chevron"}, 
                 React.DOM.div({className: "btn-group"}, 
 
@@ -224,18 +233,17 @@ loop.conversation = (function(mozL10n) {
           return (
             IncomingCallView({
               model: this.props.conversation, 
               video: this.props.conversation.hasVideoStream("incoming")}
             )
           );
         }
         case "connected": {
-          // XXX This should be the caller id (bug 1020449)
-          document.title = mozL10n.get("incoming_call_title2");
+          document.title = this.props.conversation.getCallIdentifier();
 
           var callType = this.props.conversation.get("selectedCallType");
 
           return (
             sharedViews.ConversationView({
               initiate: true, 
               sdk: this.props.sdk, 
               model: this.props.conversation, 
@@ -381,17 +389,18 @@ loop.conversation = (function(mozL10n) {
      * @param {Object} progressData The progress data from the websocket.
      * @param {String} previousState The previous state from the websocket.
      */
     _handleWebSocketProgress: function(progressData, previousState) {
       // We only care about the terminated state at the moment.
       if (progressData.state !== "terminated")
         return;
 
-      if (progressData.reason === "cancel") {
+      if (progressData.reason === "cancel" ||
+          progressData.reason === "closed") {
         this._abortIncomingCall();
         return;
       }
 
       if (progressData.reason === "timeout" &&
           (previousState === "init" || previousState === "alerting")) {
         this._abortIncomingCall();
       }
@@ -469,40 +478,52 @@ loop.conversation = (function(mozL10n) {
       console.error("Failed initiating the call session.");
     },
   });
 
   /**
    * Master controller view for handling if incoming or outgoing calls are
    * in progress, and hence, which view to display.
    */
-  var ConversationControllerView = React.createClass({displayName: 'ConversationControllerView',
+  var AppControllerView = React.createClass({displayName: 'AppControllerView',
     propTypes: {
       // XXX Old types required for incoming call view.
       client: React.PropTypes.instanceOf(loop.Client).isRequired,
       conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
                          .isRequired,
       sdk: React.PropTypes.object.isRequired,
 
       // XXX New types for OutgoingConversationView
       store: React.PropTypes.instanceOf(loop.store.ConversationStore).isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
+
+      // if not passed, this is not a room view
+      localRoomStore: React.PropTypes.instanceOf(loop.store.LocalRoomStore)
     },
 
     getInitialState: function() {
       return this.props.store.attributes;
     },
 
     componentWillMount: function() {
       this.props.store.on("change:outgoing", function() {
         this.setState(this.props.store.attributes);
       }, this);
     },
 
     render: function() {
+      if (this.props.localRoomStore) {
+        return (
+          EmptyRoomView({
+            mozLoop: navigator.mozLoop, 
+            localRoomStore: this.props.localRoomStore}
+          )
+        );
+      }
+
       // Don't display anything, until we know what type of call we are.
       if (this.state.outgoing === undefined) {
         return null;
       }
 
       if (this.state.outgoing) {
         return (OutgoingConversationView({
           store: this.props.store, 
@@ -558,53 +579,72 @@ loop.conversation = (function(mozL10n) {
       {sdk: window.OT}   // Model dependencies
     );
 
     // Obtain the callId and pass it through
     var helper = new loop.shared.utils.Helper();
     var locationHash = helper.locationHash();
     var callId;
     var outgoing;
+    var localRoomStore;
 
-    var hash = locationHash.match(/\#incoming\/(.*)/);
+    // XXX removeMe, along with noisy comment at the beginning of
+    // conversation_test.js "when locationHash begins with #room".
+    if (navigator.mozLoop.getLoopBoolPref("test.alwaysUseRooms")) {
+      locationHash = "#room/32";
+    }
+
+    var hash = locationHash.match(/#incoming\/(.*)/);
     if (hash) {
       callId = hash[1];
       outgoing = false;
+    } else if (hash = locationHash.match(/#room\/(.*)/)) {
+      localRoomStore = new loop.store.LocalRoomStore({
+        dispatcher: dispatcher,
+        mozLoop: navigator.mozLoop
+      });
     } else {
-      hash = locationHash.match(/\#outgoing\/(.*)/);
+      hash = locationHash.match(/#outgoing\/(.*)/);
       if (hash) {
         callId = hash[1];
         outgoing = true;
       }
     }
 
     conversation.set({callId: callId});
 
     window.addEventListener("unload", function(event) {
       // Handle direct close of dialog box via [x] control.
       navigator.mozLoop.releaseCallData(callId);
     });
 
     document.body.classList.add(loop.shared.utils.getTargetPlatform());
 
-    React.renderComponent(ConversationControllerView({
+    React.renderComponent(AppControllerView({
+      localRoomStore: localRoomStore, 
       store: conversationStore, 
       client: client, 
       conversation: conversation, 
       dispatcher: dispatcher, 
       sdk: window.OT}
     ), document.querySelector('#main'));
 
+   if (localRoomStore) {
+      dispatcher.dispatch(
+        new sharedActions.SetupEmptyRoom({localRoomId: hash[1]}));
+      return;
+    }
+
     dispatcher.dispatch(new loop.shared.actions.GatherCallData({
       callId: callId,
       outgoing: outgoing
     }));
   }
 
   return {
-    ConversationControllerView: ConversationControllerView,
+    AppControllerView: AppControllerView,
     IncomingConversationView: IncomingConversationView,
     IncomingCallView: IncomingCallView,
     init: init
   };
 })(document.mozL10n);
 
 document.addEventListener('DOMContentLoaded', loop.conversation.init);
--- a/browser/components/loop/content/js/conversation.jsx
+++ b/browser/components/loop/content/js/conversation.jsx
@@ -9,17 +9,21 @@
 
 var loop = loop || {};
 loop.conversation = (function(mozL10n) {
   "use strict";
 
   var sharedViews = loop.shared.views;
   var sharedMixins = loop.shared.mixins;
   var sharedModels = loop.shared.models;
+  var sharedActions = loop.shared.actions;
+
   var OutgoingConversationView = loop.conversationViews.OutgoingConversationView;
+  var CallIdentifierView = loop.conversationViews.CallIdentifierView;
+  var EmptyRoomView = loop.roomViews.EmptyRoomView;
 
   var IncomingCallView = React.createClass({
     mixins: [sharedMixins.DropdownMenuMixin],
 
     propTypes: {
       model: React.PropTypes.object.isRequired,
       video: React.PropTypes.bool.isRequired
     },
@@ -89,19 +93,24 @@ loop.conversation = (function(mozL10n) {
 
     render: function() {
       /* jshint ignore:start */
       var dropdownMenuClassesDecline = React.addons.classSet({
         "native-dropdown-menu": true,
         "conversation-window-dropdown": true,
         "visually-hidden": !this.state.showMenu
       });
+
       return (
         <div className="call-window">
-          <h2>{mozL10n.get("incoming_call_title2")}</h2>
+          <CallIdentifierView video={this.props.video}
+            peerIdentifier={this.props.model.getCallIdentifier()}
+            urlCreationDate={this.props.model.get("urlCreationDate")}
+            showIcons={true} />
+
           <div className="btn-group call-action-group">
 
             <div className="fx-embedded-call-button-spacer"></div>
 
             <div className="btn-chevron-menu-group">
               <div className="btn-group-chevron">
                 <div className="btn-group">
 
@@ -224,18 +233,17 @@ loop.conversation = (function(mozL10n) {
           return (
             <IncomingCallView
               model={this.props.conversation}
               video={this.props.conversation.hasVideoStream("incoming")}
             />
           );
         }
         case "connected": {
-          // XXX This should be the caller id (bug 1020449)
-          document.title = mozL10n.get("incoming_call_title2");
+          document.title = this.props.conversation.getCallIdentifier();
 
           var callType = this.props.conversation.get("selectedCallType");
 
           return (
             <sharedViews.ConversationView
               initiate={true}
               sdk={this.props.sdk}
               model={this.props.conversation}
@@ -381,17 +389,18 @@ loop.conversation = (function(mozL10n) {
      * @param {Object} progressData The progress data from the websocket.
      * @param {String} previousState The previous state from the websocket.
      */
     _handleWebSocketProgress: function(progressData, previousState) {
       // We only care about the terminated state at the moment.
       if (progressData.state !== "terminated")
         return;
 
-      if (progressData.reason === "cancel") {
+      if (progressData.reason === "cancel" ||
+          progressData.reason === "closed") {
         this._abortIncomingCall();
         return;
       }
 
       if (progressData.reason === "timeout" &&
           (previousState === "init" || previousState === "alerting")) {
         this._abortIncomingCall();
       }
@@ -469,40 +478,52 @@ loop.conversation = (function(mozL10n) {
       console.error("Failed initiating the call session.");
     },
   });
 
   /**
    * Master controller view for handling if incoming or outgoing calls are
    * in progress, and hence, which view to display.
    */
-  var ConversationControllerView = React.createClass({
+  var AppControllerView = React.createClass({
     propTypes: {
       // XXX Old types required for incoming call view.
       client: React.PropTypes.instanceOf(loop.Client).isRequired,
       conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
                          .isRequired,
       sdk: React.PropTypes.object.isRequired,
 
       // XXX New types for OutgoingConversationView
       store: React.PropTypes.instanceOf(loop.store.ConversationStore).isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
+
+      // if not passed, this is not a room view
+      localRoomStore: React.PropTypes.instanceOf(loop.store.LocalRoomStore)
     },
 
     getInitialState: function() {
       return this.props.store.attributes;
     },
 
     componentWillMount: function() {
       this.props.store.on("change:outgoing", function() {
         this.setState(this.props.store.attributes);
       }, this);
     },
 
     render: function() {
+      if (this.props.localRoomStore) {
+        return (
+          <EmptyRoomView
+            mozLoop={navigator.mozLoop}
+            localRoomStore={this.props.localRoomStore}
+          />
+        );
+      }
+
       // Don't display anything, until we know what type of call we are.
       if (this.state.outgoing === undefined) {
         return null;
       }
 
       if (this.state.outgoing) {
         return (<OutgoingConversationView
           store={this.props.store}
@@ -558,53 +579,72 @@ loop.conversation = (function(mozL10n) {
       {sdk: window.OT}   // Model dependencies
     );
 
     // Obtain the callId and pass it through
     var helper = new loop.shared.utils.Helper();
     var locationHash = helper.locationHash();
     var callId;
     var outgoing;
+    var localRoomStore;
 
-    var hash = locationHash.match(/\#incoming\/(.*)/);
+    // XXX removeMe, along with noisy comment at the beginning of
+    // conversation_test.js "when locationHash begins with #room".
+    if (navigator.mozLoop.getLoopBoolPref("test.alwaysUseRooms")) {
+      locationHash = "#room/32";
+    }
+
+    var hash = locationHash.match(/#incoming\/(.*)/);
     if (hash) {
       callId = hash[1];
       outgoing = false;
+    } else if (hash = locationHash.match(/#room\/(.*)/)) {
+      localRoomStore = new loop.store.LocalRoomStore({
+        dispatcher: dispatcher,
+        mozLoop: navigator.mozLoop
+      });
     } else {
-      hash = locationHash.match(/\#outgoing\/(.*)/);
+      hash = locationHash.match(/#outgoing\/(.*)/);
       if (hash) {
         callId = hash[1];
         outgoing = true;
       }
     }
 
     conversation.set({callId: callId});
 
     window.addEventListener("unload", function(event) {
       // Handle direct close of dialog box via [x] control.
       navigator.mozLoop.releaseCallData(callId);
     });
 
     document.body.classList.add(loop.shared.utils.getTargetPlatform());
 
-    React.renderComponent(<ConversationControllerView
+    React.renderComponent(<AppControllerView
+      localRoomStore={localRoomStore}
       store={conversationStore}
       client={client}
       conversation={conversation}
       dispatcher={dispatcher}
       sdk={window.OT}
     />, document.querySelector('#main'));
 
+   if (localRoomStore) {
+      dispatcher.dispatch(
+        new sharedActions.SetupEmptyRoom({localRoomId: hash[1]}));
+      return;
+    }
+
     dispatcher.dispatch(new loop.shared.actions.GatherCallData({
       callId: callId,
       outgoing: outgoing
     }));
   }
 
   return {
-    ConversationControllerView: ConversationControllerView,
+    AppControllerView: AppControllerView,
     IncomingConversationView: IncomingConversationView,
     IncomingCallView: IncomingCallView,
     init: init
   };
 })(document.mozL10n);
 
 document.addEventListener('DOMContentLoaded', loop.conversation.init);
--- a/browser/components/loop/content/js/conversationViews.js
+++ b/browser/components/loop/content/js/conversationViews.js
@@ -10,16 +10,83 @@ var loop = loop || {};
 loop.conversationViews = (function(mozL10n) {
 
   var CALL_STATES = loop.store.CALL_STATES;
   var CALL_TYPES = loop.shared.utils.CALL_TYPES;
   var sharedActions = loop.shared.actions;
   var sharedViews = loop.shared.views;
 
   /**
+   * Displays information about the call
+   * Caller avatar, name & conversation creation date
+   */
+  var CallIdentifierView = React.createClass({displayName: 'CallIdentifierView',
+    propTypes: {
+      peerIdentifier: React.PropTypes.string,
+      showIcons: React.PropTypes.bool.isRequired,
+      urlCreationDate: React.PropTypes.string,
+      video: React.PropTypes.bool
+    },
+
+    getDefaultProps: function() {
+      return {
+        peerIdentifier: "",
+        showLinkDetail: true,
+        urlCreationDate: "",
+        video: true
+      };
+    },
+
+    getInitialState: function() {
+      return {timestamp: 0};
+    },
+
+    /**
+     * Gets and formats the incoming call creation date
+     */
+    formatCreationDate: function() {
+      if (!this.props.urlCreationDate) {
+        return "";
+      }
+
+      var timestamp = this.props.urlCreationDate;
+      return "(" + loop.shared.utils.formatDate(timestamp) + ")";
+    },
+
+    render: function() {
+      var iconVideoClasses = React.addons.classSet({
+        "fx-embedded-tiny-video-icon": true,
+        "muted": !this.props.video
+      });
+      var callDetailClasses = React.addons.classSet({
+        "fx-embedded-call-detail": true,
+        "hide": !this.props.showIcons
+      });
+
+      return (
+        React.DOM.div({className: "fx-embedded-call-identifier"}, 
+          React.DOM.div({className: "fx-embedded-call-identifier-avatar fx-embedded-call-identifier-item"}), 
+          React.DOM.div({className: "fx-embedded-call-identifier-info fx-embedded-call-identifier-item"}, 
+            React.DOM.div({className: "fx-embedded-call-identifier-text overflow-text-ellipsis"}, 
+              this.props.peerIdentifier
+            ), 
+            React.DOM.div({className: callDetailClasses}, 
+              React.DOM.span({className: "fx-embedded-tiny-audio-icon"}), 
+              React.DOM.span({className: iconVideoClasses}), 
+              React.DOM.span({className: "fx-embedded-conversation-timestamp"}, 
+                this.formatCreationDate()
+              )
+            )
+          )
+        )
+      );
+    }
+  });
+
+  /**
    * Displays details of the incoming/outgoing conversation
    * (name, link, audio/video type etc).
    *
    * Allows the view to be extended with different buttons and progress
    * via children properties.
    */
   var ConversationDetailView = React.createClass({displayName: 'ConversationDetailView',
     propTypes: {
@@ -46,17 +113,19 @@ loop.conversationViews = (function(mozL1
       } else {
         contactName = this._getPreferredEmail(this.props.contact).value;
       }
 
       document.title = contactName;
 
       return (
         React.DOM.div({className: "call-window"}, 
-          React.DOM.h2(null, contactName), 
+          CallIdentifierView({
+            peerIdentifier: contactName, 
+            showIcons: false}), 
           React.DOM.div(null, this.props.children)
         )
       );
     }
   });
 
   /**
    * View for pending conversations. Displays a cancel button and appropriate
@@ -210,19 +279,21 @@ loop.conversationViews = (function(mozL1
       // height set to 100%" to fix video layout on Google Chrome
       // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1020445
       return {
         insertMode: "append",
         width: "100%",
         height: "100%",
         publishVideo: this.props.video.enabled,
         style: {
+          audioLevelDisplayMode: "off",
           bugDisplayMode: "off",
           buttonDisplayMode: "off",
-          nameDisplayMode: "off"
+          nameDisplayMode: "off",
+          videoDisabledDisplayMode: "off"
         }
       }
     },
 
     /**
      * Used to update the video container whenever the orientation or size of the
      * display area changes.
      */
@@ -377,15 +448,16 @@ loop.conversationViews = (function(mozL1
           ))
         }
       }
     },
   });
 
   return {
     PendingConversationView: PendingConversationView,
+    CallIdentifierView: CallIdentifierView,
     ConversationDetailView: ConversationDetailView,
     CallFailedView: CallFailedView,
     OngoingConversationView: OngoingConversationView,
     OutgoingConversationView: OutgoingConversationView
   };
 
 })(document.mozL10n || navigator.mozL10n);
--- a/browser/components/loop/content/js/conversationViews.jsx
+++ b/browser/components/loop/content/js/conversationViews.jsx
@@ -10,16 +10,83 @@ var loop = loop || {};
 loop.conversationViews = (function(mozL10n) {
 
   var CALL_STATES = loop.store.CALL_STATES;
   var CALL_TYPES = loop.shared.utils.CALL_TYPES;
   var sharedActions = loop.shared.actions;
   var sharedViews = loop.shared.views;
 
   /**
+   * Displays information about the call
+   * Caller avatar, name & conversation creation date
+   */
+  var CallIdentifierView = React.createClass({
+    propTypes: {
+      peerIdentifier: React.PropTypes.string,
+      showIcons: React.PropTypes.bool.isRequired,
+      urlCreationDate: React.PropTypes.string,
+      video: React.PropTypes.bool
+    },
+
+    getDefaultProps: function() {
+      return {
+        peerIdentifier: "",
+        showLinkDetail: true,
+        urlCreationDate: "",
+        video: true
+      };
+    },
+
+    getInitialState: function() {
+      return {timestamp: 0};
+    },
+
+    /**
+     * Gets and formats the incoming call creation date
+     */
+    formatCreationDate: function() {
+      if (!this.props.urlCreationDate) {
+        return "";
+      }
+
+      var timestamp = this.props.urlCreationDate;
+      return "(" + loop.shared.utils.formatDate(timestamp) + ")";
+    },
+
+    render: function() {
+      var iconVideoClasses = React.addons.classSet({
+        "fx-embedded-tiny-video-icon": true,
+        "muted": !this.props.video
+      });
+      var callDetailClasses = React.addons.classSet({
+        "fx-embedded-call-detail": true,
+        "hide": !this.props.showIcons
+      });
+
+      return (
+        <div className="fx-embedded-call-identifier">
+          <div className="fx-embedded-call-identifier-avatar fx-embedded-call-identifier-item"/>
+          <div className="fx-embedded-call-identifier-info fx-embedded-call-identifier-item">
+            <div className="fx-embedded-call-identifier-text overflow-text-ellipsis">
+              {this.props.peerIdentifier}
+            </div>
+            <div className={callDetailClasses}>
+              <span className="fx-embedded-tiny-audio-icon"></span>
+              <span className={iconVideoClasses}></span>
+              <span className="fx-embedded-conversation-timestamp">
+                {this.formatCreationDate()}
+              </span>
+            </div>
+          </div>
+        </div>
+      );
+    }
+  });
+
+  /**
    * Displays details of the incoming/outgoing conversation
    * (name, link, audio/video type etc).
    *
    * Allows the view to be extended with different buttons and progress
    * via children properties.
    */
   var ConversationDetailView = React.createClass({
     propTypes: {
@@ -46,17 +113,19 @@ loop.conversationViews = (function(mozL1
       } else {
         contactName = this._getPreferredEmail(this.props.contact).value;
       }
 
       document.title = contactName;
 
       return (
         <div className="call-window">
-          <h2>{contactName}</h2>
+          <CallIdentifierView
+            peerIdentifier={contactName}
+            showIcons={false} />
           <div>{this.props.children}</div>
         </div>
       );
     }
   });
 
   /**
    * View for pending conversations. Displays a cancel button and appropriate
@@ -210,19 +279,21 @@ loop.conversationViews = (function(mozL1
       // height set to 100%" to fix video layout on Google Chrome
       // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1020445
       return {
         insertMode: "append",
         width: "100%",
         height: "100%",
         publishVideo: this.props.video.enabled,
         style: {
+          audioLevelDisplayMode: "off",
           bugDisplayMode: "off",
           buttonDisplayMode: "off",
-          nameDisplayMode: "off"
+          nameDisplayMode: "off",
+          videoDisabledDisplayMode: "off"
         }
       }
     },
 
     /**
      * Used to update the video container whenever the orientation or size of the
      * display area changes.
      */
@@ -377,15 +448,16 @@ loop.conversationViews = (function(mozL1
           />)
         }
       }
     },
   });
 
   return {
     PendingConversationView: PendingConversationView,
+    CallIdentifierView: CallIdentifierView,
     ConversationDetailView: ConversationDetailView,
     CallFailedView: CallFailedView,
     OngoingConversationView: OngoingConversationView,
     OutgoingConversationView: OutgoingConversationView
   };
 
 })(document.mozL10n || navigator.mozL10n);
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -303,41 +303,34 @@ loop.panel = (function(_, mozL10n) {
     /**
      * Provided by DocumentVisibilityMixin. Schedules retrieval of a new call
      * URL everytime the panel is reopened.
      */
     onDocumentVisible: function() {
       this._fetchCallUrl();
     },
 
-    /**
-    * Returns a random 5 character string used to identify
-    * the conversation.
-    * XXX this will go away once the backend changes
-    */
-    conversationIdentifier: function() {
-      return Math.random().toString(36).substring(5);
-    },
-
     componentDidMount: function() {
       // If we've already got a callURL, don't bother requesting a new one.
       // As of this writing, only used for visual testing in the UI showcase.
       if (this.state.callUrl.length) {
         return;
       }
 
       this._fetchCallUrl();
     },
 
     /**
      * Fetches a call URL.
      */
     _fetchCallUrl: function() {
       this.setState({pending: true});
-      this.props.client.requestCallUrl(this.conversationIdentifier(),
+      // XXX This is an empty string as a conversation identifier. Bug 1015938 implements
+      // a user-set string.
+      this.props.client.requestCallUrl("",
                                        this._onCallUrlReceived);
     },
 
     _onCallUrlReceived: function(err, callUrlData) {
       if (err) {
         if (err.code != 401) {
           // 401 errors are already handled in hawkRequest and show an error
           // message about the session.
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -303,41 +303,34 @@ loop.panel = (function(_, mozL10n) {
     /**
      * Provided by DocumentVisibilityMixin. Schedules retrieval of a new call
      * URL everytime the panel is reopened.
      */
     onDocumentVisible: function() {
       this._fetchCallUrl();
     },
 
-    /**
-    * Returns a random 5 character string used to identify
-    * the conversation.
-    * XXX this will go away once the backend changes
-    */
-    conversationIdentifier: function() {
-      return Math.random().toString(36).substring(5);
-    },
-
     componentDidMount: function() {
       // If we've already got a callURL, don't bother requesting a new one.
       // As of this writing, only used for visual testing in the UI showcase.
       if (this.state.callUrl.length) {
         return;
       }
 
       this._fetchCallUrl();
     },
 
     /**
      * Fetches a call URL.
      */
     _fetchCallUrl: function() {
       this.setState({pending: true});
-      this.props.client.requestCallUrl(this.conversationIdentifier(),
+      // XXX This is an empty string as a conversation identifier. Bug 1015938 implements
+      // a user-set string.
+      this.props.client.requestCallUrl("",
                                        this._onCallUrlReceived);
     },
 
     _onCallUrlReceived: function(err, callUrlData) {
       if (err) {
         if (err.code != 401) {
           // 401 errors are already handled in hawkRequest and show an error
           // message about the session.
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/js/roomViews.js
@@ -0,0 +1,109 @@
+/** @jsx React.DOM */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* global loop:true, React */
+
+var loop = loop || {};
+loop.roomViews = (function(mozL10n) {
+  "use strict";
+
+  /**
+   * Root object, by default set to window.
+   * @type {DOMWindow|Object}
+   */
+  var rootObject = window;
+
+  /**
+   * Sets a new root object. This is useful for testing native DOM events so we
+   * can fake them.
+   *
+   * @param {Object}
+   */
+  function setRootObject(obj) {
+    rootObject = obj;
+  }
+
+  var EmptyRoomView = React.createClass({displayName: 'EmptyRoomView',
+    mixins: [Backbone.Events],
+
+    propTypes: {
+      mozLoop:
+        React.PropTypes.object.isRequired,
+      localRoomStore:
+        React.PropTypes.instanceOf(loop.store.LocalRoomStore).isRequired,
+    },
+
+    getInitialState: function() {
+      return this.props.localRoomStore.getStoreState();
+    },
+
+    componentWillMount: function() {
+      this.listenTo(this.props.localRoomStore, "change",
+        this._onLocalRoomStoreChanged);
+    },
+
+    componentDidMount: function() {
+      // XXXremoveMe (just the conditional itself) in patch 2 for bug 1074686,
+      // once the addCallback stuff lands
+      if (this.props.mozLoop.rooms && this.props.mozLoop.rooms.addCallback) {
+        this.props.mozLoop.rooms.addCallback(
+          this.state.localRoomId,
+          "RoomCreationError", this.onCreationError);
+      }
+    },
+
+    /**
+     * Attached to the "RoomCreationError" with mozLoop.rooms.addCallback,
+     * which is fired mozLoop.rooms.createRoom from the panel encounters an
+     * error while attempting to create the room for this view.
+     *
+     * @param {Error} err - JS Error object with info about the problem
+     */
+    onCreationError: function(err) {
+      // XXX put up a user friendly error instead of this
+      rootObject.console.error("EmptyRoomView creation error: ", err);
+    },
+
+    /**
+     * Handles a "change" event on the localRoomStore, and updates this.state
+     * to match the store.
+     *
+     * @private
+     */
+    _onLocalRoomStoreChanged: function() {
+      this.setState(this.props.localRoomStore.getStoreState());
+    },
+
+    componentWillUnmount: function() {
+      this.stopListening(this.props.localRoomStore);
+
+      // XXXremoveMe (just the conditional itself) in patch 2 for bug 1074686,
+      // once the addCallback stuff lands
+      if (this.props.mozLoop.rooms && this.props.mozLoop.rooms.removeCallback) {
+        this.props.mozLoop.rooms.removeCallback(
+          this.state.localRoomId,
+          "RoomCreationError", this.onCreationError);
+      }
+    },
+
+    render: function() {
+      // XXX switch this to use the document title mixin once bug 1081079 lands
+      if (this.state.serverData && this.state.serverData.roomName) {
+        rootObject.document.title = this.state.serverData.roomName;
+      }
+
+      return (
+        React.DOM.div({className: "goat"})
+      );
+    }
+  });
+
+  return {
+    setRootObject: setRootObject,
+    EmptyRoomView: EmptyRoomView
+  };
+
+})(document.mozL10n || navigator.mozL10n);;
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/js/roomViews.jsx
@@ -0,0 +1,109 @@
+/** @jsx React.DOM */
+
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* global loop:true, React */
+
+var loop = loop || {};
+loop.roomViews = (function(mozL10n) {
+  "use strict";
+
+  /**
+   * Root object, by default set to window.
+   * @type {DOMWindow|Object}
+   */
+  var rootObject = window;
+
+  /**
+   * Sets a new root object. This is useful for testing native DOM events so we
+   * can fake them.
+   *
+   * @param {Object}
+   */
+  function setRootObject(obj) {
+    rootObject = obj;
+  }
+
+  var EmptyRoomView = React.createClass({
+    mixins: [Backbone.Events],
+
+    propTypes: {
+      mozLoop:
+        React.PropTypes.object.isRequired,
+      localRoomStore:
+        React.PropTypes.instanceOf(loop.store.LocalRoomStore).isRequired,
+    },
+
+    getInitialState: function() {
+      return this.props.localRoomStore.getStoreState();
+    },
+
+    componentWillMount: function() {
+      this.listenTo(this.props.localRoomStore, "change",
+        this._onLocalRoomStoreChanged);
+    },
+
+    componentDidMount: function() {
+      // XXXremoveMe (just the conditional itself) in patch 2 for bug 1074686,
+      // once the addCallback stuff lands
+      if (this.props.mozLoop.rooms && this.props.mozLoop.rooms.addCallback) {
+        this.props.mozLoop.rooms.addCallback(
+          this.state.localRoomId,
+          "RoomCreationError", this.onCreationError);
+      }
+    },
+
+    /**
+     * Attached to the "RoomCreationError" with mozLoop.rooms.addCallback,
+     * which is fired mozLoop.rooms.createRoom from the panel encounters an
+     * error while attempting to create the room for this view.
+     *
+     * @param {Error} err - JS Error object with info about the problem
+     */
+    onCreationError: function(err) {
+      // XXX put up a user friendly error instead of this
+      rootObject.console.error("EmptyRoomView creation error: ", err);
+    },
+
+    /**
+     * Handles a "change" event on the localRoomStore, and updates this.state
+     * to match the store.
+     *
+     * @private
+     */
+    _onLocalRoomStoreChanged: function() {
+      this.setState(this.props.localRoomStore.getStoreState());
+    },
+
+    componentWillUnmount: function() {
+      this.stopListening(this.props.localRoomStore);
+
+      // XXXremoveMe (just the conditional itself) in patch 2 for bug 1074686,
+      // once the addCallback stuff lands
+      if (this.props.mozLoop.rooms && this.props.mozLoop.rooms.removeCallback) {
+        this.props.mozLoop.rooms.removeCallback(
+          this.state.localRoomId,
+          "RoomCreationError", this.onCreationError);
+      }
+    },
+
+    render: function() {
+      // XXX switch this to use the document title mixin once bug 1081079 lands
+      if (this.state.serverData && this.state.serverData.roomName) {
+        rootObject.document.title = this.state.serverData.roomName;
+      }
+
+      return (
+        <div className="goat"/>
+      );
+    }
+  });
+
+  return {
+    setRootObject: setRootObject,
+    EmptyRoomView: EmptyRoomView
+  };
+
+})(document.mozL10n || navigator.mozL10n);;
--- a/browser/components/loop/content/panel.html
+++ b/browser/components/loop/content/panel.html
@@ -9,17 +9,17 @@
     <link rel="stylesheet" type="text/css" href="loop/shared/css/common.css">
     <link rel="stylesheet" type="text/css" href="loop/shared/css/panel.css">
     <link rel="stylesheet" type="text/css" href="loop/shared/css/contacts.css">
   </head>
   <body class="panel">
 
     <div id="main"></div>
 
-    <script type="text/javascript" src="loop/shared/libs/react-0.11.1.js"></script>
+    <script type="text/javascript" src="loop/shared/libs/react-0.11.2.js"></script>
     <script type="text/javascript" src="loop/libs/l10n.js"></script>
     <script type="text/javascript" src="loop/shared/libs/jquery-2.1.0.js"></script>
     <script type="text/javascript" src="loop/shared/libs/lodash-2.4.1.js"></script>
     <script type="text/javascript" src="loop/shared/libs/backbone-1.1.2.js"></script>
 
     <script type="text/javascript" src="loop/shared/js/utils.js"></script>
     <script type="text/javascript" src="loop/shared/js/models.js"></script>
     <script type="text/javascript" src="loop/shared/js/mixins.js"></script>
--- a/browser/components/loop/content/shared/css/conversation.css
+++ b/browser/components/loop/content/shared/css/conversation.css
@@ -89,22 +89,24 @@
   vertical-align: top;
   width: .8rem;
   height: .8rem;
   background-repeat: no-repeat;
   cursor: pointer;
 }
 
 .fx-embedded-btn-icon-video,
-.fx-embedded-btn-video-small {
+.fx-embedded-btn-video-small,
+.fx-embedded-tiny-video-icon {
   background-image: url("../img/video-inverse-14x14.png");
 }
 
 .fx-embedded-btn-icon-audio,
-.fx-embedded-btn-audio-small {
+.fx-embedded-btn-audio-small,
+.fx-embedded-tiny-audio-icon {
   background-image: url("../img/audio-inverse-14x14.png");
 }
 
 .fx-embedded-btn-audio-small,
 .fx-embedded-btn-video-small {
   width: 26px;
   height: 26px;
   border-left: 1px solid rgba(255,255,255,.4);
@@ -479,16 +481,84 @@
   background-size: contain;
   background-position: center;
 }
 
 .fx-embedded .media.nested {
   min-height: 200px;
 }
 
+.fx-embedded-call-identifier {
+  display: inline;
+  width: 100%;
+  padding: 1.2em;
+}
+
+.fx-embedded-call-identifier-item {
+  height: 50px;
+}
+
+.fx-embedded-call-identifier-avatar {
+  max-width: 50px;
+  min-width: 50px;
+  background: #ccc;
+  border-radius: 50%;
+  background-image: url("../img/audio-call-avatar.svg");
+  background-repeat: no-repeat;
+  background-color: #4ba6e7;
+  background-size: contain;
+  overflow: hidden;
+  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.3);
+  float: left;
+  -moz-margin-end: 1em;
+}
+
+.fx-embedded-call-identifier-text {
+  font-weight: bold;
+}
+
+.fx-embedded-call-identifier-info {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  -moz-margin-start: 1em;
+}
+
+.fx-embedded-conversation-timestamp {
+  font-size: .6rem;
+  line-height: 17px;
+  display: inline-block;
+  vertical-align: top;
+}
+
+.fx-embedded-call-detail {
+  padding-top: 1.2em;
+}
+
+.fx-embedded-tiny-video-icon {
+  margin: 0 0.8em;
+}
+
+.fx-embedded-tiny-audio-icon,
+.fx-embedded-tiny-video-icon {
+  width: 18px;
+  height: 18px;
+  background-size: 12px 12px;
+  background-color: #4ba6e7;
+  display: inline-block;
+  background-repeat: no-repeat;
+  background-position: center;
+  border-radius: 50%;
+}
+
+  .fx-embedded-tiny-video-icon.muted {
+    background-color: rgba(0,0,0,.2)
+  }
+
 @media screen and (min-width:640px) {
 
   /* Force full height on all parents up to the video elements
    * this way we can ensure the aspect ratio and use height 100%
    * on the video element
    * */
   html, body, #main,
   .video-layout-wrapper,
--- a/browser/components/loop/content/shared/css/panel.css
+++ b/browser/components/loop/content/shared/css/panel.css
@@ -54,25 +54,28 @@ body {
   background-size: 16px 16px;
   background-position: center;
 }
 
 .tab-view > li:last-child {
   border-right-style: none;
 }
 
-.tab-view > li[data-tab-name="call"] {
+.tab-view > li[data-tab-name="call"],
+.tab-view > li[data-tab-name="rooms"] {
   background-image: url("../img/icons-16x16.svg#precall");
 }
 
-.tab-view > li[data-tab-name="call"]:hover {
+.tab-view > li[data-tab-name="call"]:hover,
+.tab-view > li[data-tab-name="rooms"]:hover {
   background-image: url("../img/icons-16x16.svg#precall-hover");
 }
 
-.tab-view > li[data-tab-name="call"].selected {
+.tab-view > li[data-tab-name="call"].selected,
+.tab-view > li[data-tab-name="rooms"].selected {
   background-image: url("../img/icons-16x16.svg#precall-active");
 }
 
 .tab-view > li[data-tab-name="contacts"] {
   background-image: url("../img/icons-16x16.svg#contacts");
 }
 
 .tab-view > li[data-tab-name="contacts"]:hover {
--- a/browser/components/loop/content/shared/js/actions.js
+++ b/browser/components/loop/content/shared/js/actions.js
@@ -120,11 +120,21 @@ loop.shared.actions = (function() {
       enabled: Boolean
     }),
 
     /**
      * Retrieves room list.
      * XXX: should move to some roomActions module - refs bug 1079284
      */
     GetAllRooms: Action.define("getAllRooms", {
-    })
+    }),
+
+    /**
+     * Primes localRoomStore with roomLocalId, which triggers the EmptyRoomView
+     * to do any necessary setup.
+     *
+     * XXX should move to localRoomActions module
+     */
+    SetupEmptyRoom: Action.define("setupEmptyRoom", {
+      localRoomId: String
+    }),
   };
 })();
new file mode 100644
--- /dev/null
+++ b/browser/components/loop/content/shared/js/localRoomStore.js
@@ -0,0 +1,113 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* global loop:true */
+
+var loop = loop || {};
+loop.store = loop.store || {};
+loop.store.LocalRoomStore = (function() {
+  "use strict";
+
+  var sharedActions = loop.shared.actions;
+
+  /**
+   * Store for things that are local to this instance (in this profile, on
+   * this machine) of this roomRoom store, in addition to a mirror of some
+   * remote-state.
+   *
+   * @extends {Backbone.Events}
+   *
+   * @param {Object}          options - Options object
+   * @param {loop.Dispatcher} options.dispatch - The dispatcher for dispatching
+   *                            actions and registering to consume them.
+   * @param {MozLoop}         options.mozLoop - MozLoop API provider object
+   */
+  function LocalRoomStore(options) {
+    options = options || {};
+
+    if (!options.dispatcher) {
+      throw new Error("Missing option dispatcher");
+    }
+    this.dispatcher = options.dispatcher;
+
+    if (!options.mozLoop) {
+      throw new Error("Missing option mozLoop");
+    }
+    this.mozLoop = options.mozLoop;
+
+    this.dispatcher.register(this, ["setupEmptyRoom"]);
+  }
+
+  LocalRoomStore.prototype = _.extend({
+
+    /**
+     * Stored data reflecting the local state of a given room, used to drive
+     * the room's views.
+     *
+     * @property {Object} serverData - local cache of the data returned by
+     *                                 MozLoop.getRoomData for this room.
+     * @see https://wiki.mozilla.org/Loop/Architecture/Rooms#GET_.2Frooms.2F.7Btoken.7D
+     *
+     * @property {Error=} error - if the room is an error state, this will be
+     *                            set to an Error object reflecting the problem;
+     *                            otherwise it will be unset.
+     *
+     * @property {String} localRoomId - profile-local identifier used with
+     *                                  the MozLoop API.
+     */
+    _storeState: {
+    },
+
+    getStoreState: function() {
+      return this._storeState;
+    },
+
+    setStoreState: function(state) {
+      this._storeState = state;
+      this.trigger("change");
+    },
+
+    /**
+     * Proxy to mozLoop.rooms.getRoomData for setupEmptyRoom action.
+     *
+     * XXXremoveMe Can probably be removed when bug 1074664 lands.
+     *
+     * @param {sharedActions.setupEmptyRoom} actionData
+     * @param {Function} cb Callback(error, roomData)
+     */
+    _fetchRoomData: function(actionData, cb) {
+      if (this.mozLoop.rooms && this.mozLoop.rooms.getRoomData) {
+        this.mozLoop.rooms.getRoomData(actionData.localRoomId, cb);
+      } else {
+        cb(null, {roomName: "Donkeys"});
+      }
+    },
+
+    /**
+     * Execute setupEmptyRoom event action from the dispatcher.  This primes
+     * the store with the localRoomId, and calls MozLoop.getRoomData on that
+     * ID.  This will return either a reflection of state on the server, or,
+     * if the createRoom call hasn't yet returned, it will have at least the
+     * roomName as specified to the createRoom method.
+     *
+     * When the room name gets set, that will trigger the view to display
+     * that name.
+     *
+     * @param {sharedActions.setupEmptyRoom} actionData
+     */
+    setupEmptyRoom: function(actionData) {
+      this._fetchRoomData(actionData, function(error, roomData) {
+        this.setStoreState({
+          error: error,
+          localRoomId: actionData.localRoomId,
+          serverData: roomData
+        });
+      }.bind(this));
+    }
+
+  }, Backbone.Events);
+
+  return LocalRoomStore;
+
+})();
--- a/browser/components/loop/content/shared/js/models.js
+++ b/browser/components/loop/content/shared/js/models.js
@@ -27,16 +27,17 @@ loop.shared.models = (function(l10n) {
       websocketToken: undefined,   // The token to use for websocket auth, this is
                                    // stored as a hex string which is what the server
                                    // requires.
       callType:     undefined,     // The type of incoming call selected by
                                    // other peer ("audio" or "audio-video")
       selectedCallType: "audio-video", // The selected type for the call that was
                                        // initiated ("audio" or "audio-video")
       callToken:    undefined,     // Incoming call token.
+      callUrl:      undefined,     // Incoming call url
                                    // Used for blocking a call url
       subscribedStream: false,     // Used to indicate that a stream has been
                                    // subscribed to
       publishedStream: false       // Used to indicate that a stream has been
                                    // published
     },
 
     /**
@@ -137,25 +138,28 @@ loop.shared.models = (function(l10n) {
     /**
      * Sets session information about the incoming call.
      *
      * @param {Object} sessionData Conversation session information.
      */
     setIncomingSessionData: function(sessionData) {
       // Explicit property assignment to prevent later "surprises"
       this.set({
-        sessionId:      sessionData.sessionId,
-        sessionToken:   sessionData.sessionToken,
-        sessionType:    sessionData.sessionType,
-        apiKey:         sessionData.apiKey,
-        callId:         sessionData.callId,
-        progressURL:    sessionData.progressURL,
-        websocketToken: sessionData.websocketToken.toString(16),
-        callType:       sessionData.callType || "audio-video",
-        callToken:      sessionData.callToken
+        sessionId:       sessionData.sessionId,
+        sessionToken:    sessionData.sessionToken,
+        sessionType:     sessionData.sessionType,
+        apiKey:          sessionData.apiKey,
+        callId:          sessionData.callId,
+        callerId:        sessionData.callerId,
+        urlCreationDate: sessionData.urlCreationDate,
+        progressURL:     sessionData.progressURL,
+        websocketToken:  sessionData.websocketToken.toString(16),
+        callType:        sessionData.callType || "audio-video",
+        callToken:       sessionData.callToken,
+        callUrl:         sessionData.callUrl
       });
     },
 
     /**
      * Starts a SDK session and subscribe to call events.
      */
     startSession: function() {
       if (!this.isSessionReady()) {
@@ -194,16 +198,33 @@ loop.shared.models = (function(l10n) {
       }
       if (callType === "outgoing") {
         return this.get("selectedCallType") === "audio-video";
       }
       return undefined;
     },
 
     /**
+     * Used to remove the scheme from a url.
+     */
+    _removeScheme: function(url) {
+      if (!url) {
+        return "";
+      }
+      return url.replace(/^https?:\/\//, "");
+    },
+
+    /**
+     * Returns a conversation identifier for the incoming call view
+     */
+    getCallIdentifier: function() {
+      return this.get("callerId") || this._removeScheme(this.get("callUrl"));
+    },
+
+    /**
      * Publishes a local stream.
      *
      * @param {Publisher} publisher The publisher object to publish
      *                              to the session.
      */
     publish: function(publisher) {
       this.session.publish(publisher);
       this.set("publishedStream", true);
--- a/browser/components/loop/content/shared/js/utils.js
+++ b/browser/components/loop/content/shared/js/utils.js
@@ -13,16 +13,28 @@ loop.shared.utils = (function() {
    * Call types used for determining if a call is audio/video or audio-only.
    */
   var CALL_TYPES = {
     AUDIO_VIDEO: "audio-video",
     AUDIO_ONLY: "audio"
   };
 
   /**
+   * Format a given date into an l10n-friendly string.
+   *
+   * @param {Integer} The timestamp in seconds to format.
+   * @return {String} The formatted string.
+   */
+  function formatDate(timestamp) {
+    var date = (new Date(timestamp * 1000));
+    var options = {year: "numeric", month: "long", day: "numeric"};
+    return date.toLocaleDateString(navigator.language, options);
+  }
+
+  /**
    * Used for adding different styles to the panel
    * @returns {String} Corresponds to the client platform
    * */
   function getTargetPlatform() {
     var platform="unknown_platform";
 
     if (navigator.platform.indexOf("Win") !== -1) {
       platform = "windows";
@@ -82,12 +94,13 @@ loop.shared.utils = (function() {
     locationHash: function() {
       return window.location.hash;
     }
   };
 
   return {
     CALL_TYPES: CALL_TYPES,
     Helper: Helper,
+    formatDate: formatDate,
     getTargetPlatform: getTargetPlatform,
     getBoolPreference: getBoolPreference
   };
 })();
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -146,19 +146,21 @@ loop.shared.views = (function(_, OT, l10
 
     // height set to 100%" to fix video layout on Google Chrome
     // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1020445
     publisherConfig: {
       insertMode: "append",
       width: "100%",
       height: "100%",
       style: {
+        audioLevelDisplayMode: "off",
         bugDisplayMode: "off",
         buttonDisplayMode: "off",
-        nameDisplayMode: "off"
+        nameDisplayMode: "off",
+        videoDisabledDisplayMode: "off"
       }
     },
 
     getDefaultProps: function() {
       return {
         initiate: true,
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true}
--- a/browser/components/loop/content/shared/js/views.jsx
+++ b/browser/components/loop/content/shared/js/views.jsx
@@ -146,19 +146,21 @@ loop.shared.views = (function(_, OT, l10
 
     // height set to 100%" to fix video layout on Google Chrome
     // @see https://bugzilla.mozilla.org/show_bug.cgi?id=1020445
     publisherConfig: {
       insertMode: "append",
       width: "100%",
       height: "100%",
       style: {
+        audioLevelDisplayMode: "off",
         bugDisplayMode: "off",
         buttonDisplayMode: "off",
-        nameDisplayMode: "off"
+        nameDisplayMode: "off",
+        videoDisabledDisplayMode: "off"
       }
     },
 
     getDefaultProps: function() {
       return {
         initiate: true,
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true}
rename from browser/components/loop/content/shared/libs/react-0.11.1-prod.js
rename to browser/components/loop/content/shared/libs/react-0.11.2-prod.js
--- a/browser/components/loop/content/shared/libs/react-0.11.1-prod.js
+++ b/browser/components/loop/content/shared/libs/react-0.11.2-prod.js
@@ -1,22 +1,22 @@
 /**
- * React (with addons) v0.11.1
+ * React (with addons) v0.11.2
  *
  * Copyright 2013-2014 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.React=e()}}(function(){return function e(t,n,r){function o(a,s){if(!n[a]){if(!t[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);throw new Error("Cannot find module '"+a+"'")}var c=n[a]={exports:{}};t[a][0].call(c.exports,function(e){var n=t[a][1][e];return o(n?n:e)},c,c.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(e,t){"use strict";var n=e("./focusNode"),r={componentDidMount:function(){this.props.autoFocus&&n(this.getDOMNode())}};t.exports=r},{"./focusNode":117}],2:[function(e,t){"use strict";function n(){var e=window.opera;return"object"==typeof e&&"function"==typeof e.version&&parseInt(e.version(),10)<=12}function r(e){return(e.ctrlKey||e.altKey||e.metaKey)&&!(e.ctrlKey&&e.altKey)}var o=e("./EventConstants"),i=e("./EventPropagators"),a=e("./ExecutionEnvironment"),s=e("./SyntheticInputEvent"),u=e("./keyOf"),c=a.canUseDOM&&"TextEvent"in window&&!("documentMode"in document||n()),l=32,p=String.fromCharCode(l),d=o.topLevelTypes,f={beforeInput:{phasedRegistrationNames:{bubbled:u({onBeforeInput:null}),captured:u({onBeforeInputCapture:null})},dependencies:[d.topCompositionEnd,d.topKeyPress,d.topTextInput,d.topPaste]}},h=null,v={eventTypes:f,extractEvents:function(e,t,n,o){var a;if(c)switch(e){case d.topKeyPress:var u=o.which;if(u!==l)return;a=String.fromCharCode(u);break;case d.topTextInput:if(a=o.data,a===p)return;break;default:return}else{switch(e){case d.topPaste:h=null;break;case d.topKeyPress:o.which&&!r(o)&&(h=String.fromCharCode(o.which));break;case d.topCompositionEnd:h=o.data}if(null===h)return;a=h}if(a){var v=s.getPooled(f.beforeInput,n,o);return v.data=a,h=null,i.accumulateTwoPhaseDispatches(v),v}}};t.exports=v},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./SyntheticInputEvent":95,"./keyOf":138}],3:[function(e,t){var n=e("./invariant"),r={addClass:function(e,t){return n(!/\s/.test(t)),t&&(e.classList?e.classList.add(t):r.hasClass(e,t)||(e.className=e.className+" "+t)),e},removeClass:function(e,t){return n(!/\s/.test(t)),t&&(e.classList?e.classList.remove(t):r.hasClass(e,t)&&(e.className=e.className.replace(new RegExp("(^|\\s)"+t+"(?:\\s|$)","g"),"$1").replace(/\s+/g," ").replace(/^\s*|\s*$/g,""))),e},conditionClass:function(e,t,n){return(n?r.addClass:r.removeClass)(e,t)},hasClass:function(e,t){return n(!/\s/.test(t)),e.classList?!!t&&e.classList.contains(t):(" "+e.className+" ").indexOf(" "+t+" ")>-1}};t.exports=r},{"./invariant":131}],4:[function(e,t){"use strict";function n(e,t){return e+t.charAt(0).toUpperCase()+t.substring(1)}var r={columnCount:!0,fillOpacity:!0,flex:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},o=["Webkit","ms","Moz","O"];Object.keys(r).forEach(function(e){o.forEach(function(t){r[n(t,e)]=r[e]})});var i={background:{backgroundImage:!0,backgroundPosition:!0,backgroundRepeat:!0,backgroundColor:!0},border:{borderWidth:!0,borderStyle:!0,borderColor:!0},borderBottom:{borderBottomWidth:!0,borderBottomStyle:!0,borderBottomColor:!0},borderLeft:{borderLeftWidth:!0,borderLeftStyle:!0,borderLeftColor:!0},borderRight:{borderRightWidth:!0,borderRightStyle:!0,borderRightColor:!0},borderTop:{borderTopWidth:!0,borderTopStyle:!0,borderTopColor:!0},font:{fontStyle:!0,fontVariant:!0,fontWeight:!0,fontSize:!0,lineHeight:!0,fontFamily:!0}},a={isUnitlessNumber:r,shorthandPropertyExpansions:i};t.exports=a},{}],5:[function(e,t){"use strict";var n=e("./CSSProperty"),r=e("./dangerousStyleValue"),o=e("./hyphenateStyleName"),i=e("./memoizeStringOnly"),a=i(function(e){return o(e)}),s={createMarkupForStyles:function(e){var t="";for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];null!=o&&(t+=a(n)+":",t+=r(n,o)+";")}return t||null},setValueForStyles:function(e,t){var o=e.style;for(var i in t)if(t.hasOwnProperty(i)){var a=r(i,t[i]);if(a)o[i]=a;else{var s=n.shorthandPropertyExpansions[i];if(s)for(var u in s)o[u]="";else o[i]=""}}}};t.exports=s},{"./CSSProperty":4,"./dangerousStyleValue":112,"./hyphenateStyleName":129,"./memoizeStringOnly":140}],6:[function(e,t){"use strict";function n(){this._callbacks=null,this._contexts=null}var r=e("./PooledClass"),o=e("./invariant"),i=e("./mixInto");i(n,{enqueue:function(e,t){this._callbacks=this._callbacks||[],this._contexts=this._contexts||[],this._callbacks.push(e),this._contexts.push(t)},notifyAll:function(){var e=this._callbacks,t=this._contexts;if(e){o(e.length===t.length),this._callbacks=null,this._contexts=null;for(var n=0,r=e.length;r>n;n++)e[n].call(t[n]);e.length=0,t.length=0}},reset:function(){this._callbacks=null,this._contexts=null},destructor:function(){this.reset()}}),r.addPoolingTo(n),t.exports=n},{"./PooledClass":28,"./invariant":131,"./mixInto":144}],7:[function(e,t){"use strict";function n(e){return"SELECT"===e.nodeName||"INPUT"===e.nodeName&&"file"===e.type}function r(e){var t=M.getPooled(P.change,S,e);C.accumulateTwoPhaseDispatches(t),R.batchedUpdates(o,t)}function o(e){y.enqueueEvents(e),y.processEventQueue()}function i(e,t){T=e,S=t,T.attachEvent("onchange",r)}function a(){T&&(T.detachEvent("onchange",r),T=null,S=null)}function s(e,t,n){return e===O.topChange?n:void 0}function u(e,t,n){e===O.topFocus?(a(),i(t,n)):e===O.topBlur&&a()}function c(e,t){T=e,S=t,w=e.value,_=Object.getOwnPropertyDescriptor(e.constructor.prototype,"value"),Object.defineProperty(T,"value",k),T.attachEvent("onpropertychange",p)}function l(){T&&(delete T.value,T.detachEvent("onpropertychange",p),T=null,S=null,w=null,_=null)}function p(e){if("value"===e.propertyName){var t=e.srcElement.value;t!==w&&(w=t,r(e))}}function d(e,t,n){return e===O.topInput?n:void 0}function f(e,t,n){e===O.topFocus?(l(),c(t,n)):e===O.topBlur&&l()}function h(e){return e!==O.topSelectionChange&&e!==O.topKeyUp&&e!==O.topKeyDown||!T||T.value===w?void 0:(w=T.value,S)}function v(e){return"INPUT"===e.nodeName&&("checkbox"===e.type||"radio"===e.type)}function m(e,t,n){return e===O.topClick?n:void 0}var g=e("./EventConstants"),y=e("./EventPluginHub"),C=e("./EventPropagators"),E=e("./ExecutionEnvironment"),R=e("./ReactUpdates"),M=e("./SyntheticEvent"),D=e("./isEventSupported"),x=e("./isTextInputElement"),b=e("./keyOf"),O=g.topLevelTypes,P={change:{phasedRegistrationNames:{bubbled:b({onChange:null}),captured:b({onChangeCapture:null})},dependencies:[O.topBlur,O.topChange,O.topClick,O.topFocus,O.topInput,O.topKeyDown,O.topKeyUp,O.topSelectionChange]}},T=null,S=null,w=null,_=null,I=!1;E.canUseDOM&&(I=D("change")&&(!("documentMode"in document)||document.documentMode>8));var N=!1;E.canUseDOM&&(N=D("input")&&(!("documentMode"in document)||document.documentMode>9));var k={get:function(){return _.get.call(this)},set:function(e){w=""+e,_.set.call(this,e)}},A={eventTypes:P,extractEvents:function(e,t,r,o){var i,a;if(n(t)?I?i=s:a=u:x(t)?N?i=d:(i=h,a=f):v(t)&&(i=m),i){var c=i(e,t,r);if(c){var l=M.getPooled(P.change,c,o);return C.accumulateTwoPhaseDispatches(l),l}}a&&a(e,t,r)}};t.exports=A},{"./EventConstants":16,"./EventPluginHub":18,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactUpdates":84,"./SyntheticEvent":93,"./isEventSupported":132,"./isTextInputElement":134,"./keyOf":138}],8:[function(e,t){"use strict";var n=0,r={createReactRootIndex:function(){return n++}};t.exports=r},{}],9:[function(e,t){"use strict";function n(e){switch(e){case g.topCompositionStart:return C.compositionStart;case g.topCompositionEnd:return C.compositionEnd;case g.topCompositionUpdate:return C.compositionUpdate}}function r(e,t){return e===g.topKeyDown&&t.keyCode===h}function o(e,t){switch(e){case g.topKeyUp:return-1!==f.indexOf(t.keyCode);case g.topKeyDown:return t.keyCode!==h;case g.topKeyPress:case g.topMouseDown:case g.topBlur:return!0;default:return!1}}function i(e){this.root=e,this.startSelection=c.getSelection(e),this.startValue=this.getText()}var a=e("./EventConstants"),s=e("./EventPropagators"),u=e("./ExecutionEnvironment"),c=e("./ReactInputSelection"),l=e("./SyntheticCompositionEvent"),p=e("./getTextContentAccessor"),d=e("./keyOf"),f=[9,13,27,32],h=229,v=u.canUseDOM&&"CompositionEvent"in window,m=!v||"documentMode"in document&&document.documentMode>8&&document.documentMode<=11,g=a.topLevelTypes,y=null,C={compositionEnd:{phasedRegistrationNames:{bubbled:d({onCompositionEnd:null}),captured:d({onCompositionEndCapture:null})},dependencies:[g.topBlur,g.topCompositionEnd,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:d({onCompositionStart:null}),captured:d({onCompositionStartCapture:null})},dependencies:[g.topBlur,g.topCompositionStart,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:d({onCompositionUpdate:null}),captured:d({onCompositionUpdateCapture:null})},dependencies:[g.topBlur,g.topCompositionUpdate,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]}};i.prototype.getText=function(){return this.root.value||this.root[p()]},i.prototype.getData=function(){var e=this.getText(),t=this.startSelection.start,n=this.startValue.length-this.startSelection.end;return e.substr(t,e.length-n-t)};var E={eventTypes:C,extractEvents:function(e,t,a,u){var c,p;if(v?c=n(e):y?o(e,u)&&(c=C.compositionEnd):r(e,u)&&(c=C.compositionStart),m&&(y||c!==C.compositionStart?c===C.compositionEnd&&y&&(p=y.getData(),y=null):y=new i(t)),c){var d=l.getPooled(c,a,u);return p&&(d.data=p),s.accumulateTwoPhaseDispatches(d),d}}};t.exports=E},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactInputSelection":61,"./SyntheticCompositionEvent":91,"./getTextContentAccessor":126,"./keyOf":138}],10:[function(e,t){"use strict";function n(e,t,n){e.insertBefore(t,e.childNodes[n]||null)}var r,o=e("./Danger"),i=e("./ReactMultiChildUpdateTypes"),a=e("./getTextContentAccessor"),s=e("./invariant"),u=a();r="textContent"===u?function(e,t){e.textContent=t}:function(e,t){for(;e.firstChild;)e.removeChild(e.firstChild);if(t){var n=e.ownerDocument||document;e.appendChild(n.createTextNode(t))}};var c={dangerouslyReplaceNodeWithMarkup:o.dangerouslyReplaceNodeWithMarkup,updateTextContent:r,processUpdates:function(e,t){for(var a,u=null,c=null,l=0;a=e[l];l++)if(a.type===i.MOVE_EXISTING||a.type===i.REMOVE_NODE){var p=a.fromIndex,d=a.parentNode.childNodes[p],f=a.parentID;s(d),u=u||{},u[f]=u[f]||[],u[f][p]=d,c=c||[],c.push(d)}var h=o.dangerouslyRenderMarkup(t);if(c)for(var v=0;v<c.length;v++)c[v].parentNode.removeChild(c[v]);for(var m=0;a=e[m];m++)switch(a.type){case i.INSERT_MARKUP:n(a.parentNode,h[a.markupIndex],a.toIndex);break;case i.MOVE_EXISTING:n(a.parentNode,u[a.parentID][a.fromIndex],a.toIndex);break;case i.TEXT_CONTENT:r(a.parentNode,a.textContent);break;case i.REMOVE_NODE:}}};t.exports=c},{"./Danger":13,"./ReactMultiChildUpdateTypes":67,"./getTextContentAccessor":126,"./invariant":131}],11:[function(e,t){"use strict";var n=e("./invariant"),r={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(e){var t=e.Properties||{},o=e.DOMAttributeNames||{},a=e.DOMPropertyNames||{},s=e.DOMMutationMethods||{};e.isCustomAttribute&&i._isCustomAttributeFunctions.push(e.isCustomAttribute);for(var u in t){n(!i.isStandardName.hasOwnProperty(u)),i.isStandardName[u]=!0;var c=u.toLowerCase();if(i.getPossibleStandardName[c]=u,o.hasOwnProperty(u)){var l=o[u];i.getPossibleStandardName[l]=u,i.getAttributeName[u]=l}else i.getAttributeName[u]=c;i.getPropertyName[u]=a.hasOwnProperty(u)?a[u]:u,i.getMutationMethod[u]=s.hasOwnProperty(u)?s[u]:null;var p=t[u];i.mustUseAttribute[u]=p&r.MUST_USE_ATTRIBUTE,i.mustUseProperty[u]=p&r.MUST_USE_PROPERTY,i.hasSideEffects[u]=p&r.HAS_SIDE_EFFECTS,i.hasBooleanValue[u]=p&r.HAS_BOOLEAN_VALUE,i.hasNumericValue[u]=p&r.HAS_NUMERIC_VALUE,i.hasPositiveNumericValue[u]=p&r.HAS_POSITIVE_NUMERIC_VALUE,i.hasOverloadedBooleanValue[u]=p&r.HAS_OVERLOADED_BOOLEAN_VALUE,n(!i.mustUseAttribute[u]||!i.mustUseProperty[u]),n(i.mustUseProperty[u]||!i.hasSideEffects[u]),n(!!i.hasBooleanValue[u]+!!i.hasNumericValue[u]+!!i.hasOverloadedBooleanValue[u]<=1)}}},o={},i={ID_ATTRIBUTE_NAME:"data-reactid",isStandardName:{},getPossibleStandardName:{},getAttributeName:{},getPropertyName:{},getMutationMethod:{},mustUseAttribute:{},mustUseProperty:{},hasSideEffects:{},hasBooleanValue:{},hasNumericValue:{},hasPositiveNumericValue:{},hasOverloadedBooleanValue:{},_isCustomAttributeFunctions:[],isCustomAttribute:function(e){for(var t=0;t<i._isCustomAttributeFunctions.length;t++){var n=i._isCustomAttributeFunctions[t];if(n(e))return!0}return!1},getDefaultValueForProperty:function(e,t){var n,r=o[e];return r||(o[e]=r={}),t in r||(n=document.createElement(e),r[t]=n[t]),r[t]},injection:r};t.exports=i},{"./invariant":131}],12:[function(e,t){"use strict";function n(e,t){return null==t||r.hasBooleanValue[e]&&!t||r.hasNumericValue[e]&&isNaN(t)||r.hasPositiveNumericValue[e]&&1>t||r.hasOverloadedBooleanValue[e]&&t===!1}var r=e("./DOMProperty"),o=e("./escapeTextForBrowser"),i=e("./memoizeStringOnly"),a=(e("./warning"),i(function(e){return o(e)+'="'})),s={createMarkupForID:function(e){return a(r.ID_ATTRIBUTE_NAME)+o(e)+'"'},createMarkupForProperty:function(e,t){if(r.isStandardName.hasOwnProperty(e)&&r.isStandardName[e]){if(n(e,t))return"";var i=r.getAttributeName[e];return r.hasBooleanValue[e]||r.hasOverloadedBooleanValue[e]&&t===!0?o(i):a(i)+o(t)+'"'}return r.isCustomAttribute(e)?null==t?"":a(e)+o(t)+'"':null},setValueForProperty:function(e,t,o){if(r.isStandardName.hasOwnProperty(t)&&r.isStandardName[t]){var i=r.getMutationMethod[t];if(i)i(e,o);else if(n(t,o))this.deleteValueForProperty(e,t);else if(r.mustUseAttribute[t])e.setAttribute(r.getAttributeName[t],""+o);else{var a=r.getPropertyName[t];r.hasSideEffects[t]&&e[a]===o||(e[a]=o)}}else r.isCustomAttribute(t)&&(null==o?e.removeAttribute(t):e.setAttribute(t,""+o))},deleteValueForProperty:function(e,t){if(r.isStandardName.hasOwnProperty(t)&&r.isStandardName[t]){var n=r.getMutationMethod[t];if(n)n(e,void 0);else if(r.mustUseAttribute[t])e.removeAttribute(r.getAttributeName[t]);else{var o=r.getPropertyName[t],i=r.getDefaultValueForProperty(e.nodeName,o);r.hasSideEffects[t]&&e[o]===i||(e[o]=i)}}else r.isCustomAttribute(t)&&e.removeAttribute(t)}};t.exports=s},{"./DOMProperty":11,"./escapeTextForBrowser":115,"./memoizeStringOnly":140,"./warning":153}],13:[function(e,t){"use strict";function n(e){return e.substring(1,e.indexOf(" "))}var r=e("./ExecutionEnvironment"),o=e("./createNodesFromMarkup"),i=e("./emptyFunction"),a=e("./getMarkupWrap"),s=e("./invariant"),u=/^(<[^ \/>]+)/,c="data-danger-index",l={dangerouslyRenderMarkup:function(e){s(r.canUseDOM);for(var t,l={},p=0;p<e.length;p++)s(e[p]),t=n(e[p]),t=a(t)?t:"*",l[t]=l[t]||[],l[t][p]=e[p];var d=[],f=0;for(t in l)if(l.hasOwnProperty(t)){var h=l[t];for(var v in h)if(h.hasOwnProperty(v)){var m=h[v];h[v]=m.replace(u,"$1 "+c+'="'+v+'" ')}var g=o(h.join(""),i);for(p=0;p<g.length;++p){var y=g[p];y.hasAttribute&&y.hasAttribute(c)&&(v=+y.getAttribute(c),y.removeAttribute(c),s(!d.hasOwnProperty(v)),d[v]=y,f+=1)}}return s(f===d.length),s(d.length===e.length),d},dangerouslyReplaceNodeWithMarkup:function(e,t){s(r.canUseDOM),s(t),s("html"!==e.tagName.toLowerCase());var n=o(t,i)[0];e.parentNode.replaceChild(n,e)}};t.exports=l},{"./ExecutionEnvironment":22,"./createNodesFromMarkup":110,"./emptyFunction":113,"./getMarkupWrap":123,"./invariant":131}],14:[function(e,t){"use strict";var n=e("./keyOf"),r=[n({ResponderEventPlugin:null}),n({SimpleEventPlugin:null}),n({TapEventPlugin:null}),n({EnterLeaveEventPlugin:null}),n({ChangeEventPlugin:null}),n({SelectEventPlugin:null}),n({CompositionEventPlugin:null}),n({BeforeInputEventPlugin:null}),n({AnalyticsEventPlugin:null}),n({MobileSafariClickEventPlugin:null})];t.exports=r},{"./keyOf":138}],15:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./EventPropagators"),o=e("./SyntheticMouseEvent"),i=e("./ReactMount"),a=e("./keyOf"),s=n.topLevelTypes,u=i.getFirstReactDOM,c={mouseEnter:{registrationName:a({onMouseEnter:null}),dependencies:[s.topMouseOut,s.topMouseOver]},mouseLeave:{registrationName:a({onMouseLeave:null}),dependencies:[s.topMouseOut,s.topMouseOver]}},l=[null,null],p={eventTypes:c,extractEvents:function(e,t,n,a){if(e===s.topMouseOver&&(a.relatedTarget||a.fromElement))return null;if(e!==s.topMouseOut&&e!==s.topMouseOver)return null;var p;if(t.window===t)p=t;else{var d=t.ownerDocument;p=d?d.defaultView||d.parentWindow:window}var f,h;if(e===s.topMouseOut?(f=t,h=u(a.relatedTarget||a.toElement)||p):(f=p,h=t),f===h)return null;var v=f?i.getID(f):"",m=h?i.getID(h):"",g=o.getPooled(c.mouseLeave,v,a);g.type="mouseleave",g.target=f,g.relatedTarget=h;var y=o.getPooled(c.mouseEnter,m,a);return y.type="mouseenter",y.target=h,y.relatedTarget=f,r.accumulateEnterLeaveDispatches(g,y,v,m),l[0]=g,l[1]=y,l}};t.exports=p},{"./EventConstants":16,"./EventPropagators":21,"./ReactMount":65,"./SyntheticMouseEvent":97,"./keyOf":138}],16:[function(e,t){"use strict";var n=e("./keyMirror"),r=n({bubbled:null,captured:null}),o=n({topBlur:null,topChange:null,topClick:null,topCompositionEnd:null,topCompositionStart:null,topCompositionUpdate:null,topContextMenu:null,topCopy:null,topCut:null,topDoubleClick:null,topDrag:null,topDragEnd:null,topDragEnter:null,topDragExit:null,topDragLeave:null,topDragOver:null,topDragStart:null,topDrop:null,topError:null,topFocus:null,topInput:null,topKeyDown:null,topKeyPress:null,topKeyUp:null,topLoad:null,topMouseDown:null,topMouseMove:null,topMouseOut:null,topMouseOver:null,topMouseUp:null,topPaste:null,topReset:null,topScroll:null,topSelectionChange:null,topSubmit:null,topTextInput:null,topTouchCancel:null,topTouchEnd:null,topTouchMove:null,topTouchStart:null,topWheel:null}),i={topLevelTypes:o,PropagationPhases:r};t.exports=i},{"./keyMirror":137}],17:[function(e,t){var n=e("./emptyFunction"),r={listen:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!1),{remove:function(){e.removeEventListener(t,n,!1)}}):e.attachEvent?(e.attachEvent("on"+t,n),{remove:function(){e.detachEvent("on"+t,n)}}):void 0},capture:function(e,t,r){return e.addEventListener?(e.addEventListener(t,r,!0),{remove:function(){e.removeEventListener(t,r,!0)}}):{remove:n}},registerDefault:function(){}};t.exports=r},{"./emptyFunction":113}],18:[function(e,t){"use strict";var n=e("./EventPluginRegistry"),r=e("./EventPluginUtils"),o=e("./accumulate"),i=e("./forEachAccumulated"),a=e("./invariant"),s=(e("./isEventSupported"),e("./monitorCodeUse"),{}),u=null,c=function(e){if(e){var t=r.executeDispatch,o=n.getPluginModuleForEvent(e);o&&o.executeDispatch&&(t=o.executeDispatch),r.executeDispatchesInOrder(e,t),e.isPersistent()||e.constructor.release(e)}},l=null,p={injection:{injectMount:r.injection.injectMount,injectInstanceHandle:function(e){l=e},getInstanceHandle:function(){return l},injectEventPluginOrder:n.injectEventPluginOrder,injectEventPluginsByName:n.injectEventPluginsByName},eventNameDispatchConfigs:n.eventNameDispatchConfigs,registrationNameModules:n.registrationNameModules,putListener:function(e,t,n){a(!n||"function"==typeof n);var r=s[t]||(s[t]={});r[e]=n},getListener:function(e,t){var n=s[t];return n&&n[e]},deleteListener:function(e,t){var n=s[t];n&&delete n[e]},deleteAllListeners:function(e){for(var t in s)delete s[t][e]},extractEvents:function(e,t,r,i){for(var a,s=n.plugins,u=0,c=s.length;c>u;u++){var l=s[u];if(l){var p=l.extractEvents(e,t,r,i);p&&(a=o(a,p))}}return a},enqueueEvents:function(e){e&&(u=o(u,e))},processEventQueue:function(){var e=u;u=null,i(e,c),a(!u)},__purge:function(){s={}},__getListenerBank:function(){return s}};t.exports=p},{"./EventPluginRegistry":19,"./EventPluginUtils":20,"./accumulate":103,"./forEachAccumulated":118,"./invariant":131,"./isEventSupported":132,"./monitorCodeUse":145}],19:[function(e,t){"use strict";function n(){if(a)for(var e in s){var t=s[e],n=a.indexOf(e);if(i(n>-1),!u.plugins[n]){i(t.extractEvents),u.plugins[n]=t;var o=t.eventTypes;for(var c in o)i(r(o[c],t,c))}}}function r(e,t,n){i(!u.eventNameDispatchConfigs.hasOwnProperty(n)),u.eventNameDispatchConfigs[n]=e;var r=e.phasedRegistrationNames;if(r){for(var a in r)if(r.hasOwnProperty(a)){var s=r[a];o(s,t,n)}return!0}return e.registrationName?(o(e.registrationName,t,n),!0):!1}function o(e,t,n){i(!u.registrationNameModules[e]),u.registrationNameModules[e]=t,u.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var i=e("./invariant"),a=null,s={},u={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(e){i(!a),a=Array.prototype.slice.call(e),n()},injectEventPluginsByName:function(e){var t=!1;for(var r in e)if(e.hasOwnProperty(r)){var o=e[r];s.hasOwnProperty(r)&&s[r]===o||(i(!s[r]),s[r]=o,t=!0)}t&&n()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return u.registrationNameModules[t.registrationName]||null;for(var n in t.phasedRegistrationNames)if(t.phasedRegistrationNames.hasOwnProperty(n)){var r=u.registrationNameModules[t.phasedRegistrationNames[n]];if(r)return r}return null},_resetEventPlugins:function(){a=null;for(var e in s)s.hasOwnProperty(e)&&delete s[e];u.plugins.length=0;var t=u.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=u.registrationNameModules;for(var o in r)r.hasOwnProperty(o)&&delete r[o]}};t.exports=u},{"./invariant":131}],20:[function(e,t){"use strict";function n(e){return e===v.topMouseUp||e===v.topTouchEnd||e===v.topTouchCancel}function r(e){return e===v.topMouseMove||e===v.topTouchMove}function o(e){return e===v.topMouseDown||e===v.topTouchStart}function i(e,t){var n=e._dispatchListeners,r=e._dispatchIDs;if(Array.isArray(n))for(var o=0;o<n.length&&!e.isPropagationStopped();o++)t(e,n[o],r[o]);else n&&t(e,n,r)}function a(e,t,n){e.currentTarget=h.Mount.getNode(n);var r=t(e,n);return e.currentTarget=null,r}function s(e,t){i(e,t),e._dispatchListeners=null,e._dispatchIDs=null}function u(e){var t=e._dispatchListeners,n=e._dispatchIDs;if(Array.isArray(t)){for(var r=0;r<t.length&&!e.isPropagationStopped();r++)if(t[r](e,n[r]))return n[r]}else if(t&&t(e,n))return n;return null}function c(e){var t=u(e);return e._dispatchIDs=null,e._dispatchListeners=null,t}function l(e){var t=e._dispatchListeners,n=e._dispatchIDs;f(!Array.isArray(t));var r=t?t(e,n):null;return e._dispatchListeners=null,e._dispatchIDs=null,r}function p(e){return!!e._dispatchListeners}var d=e("./EventConstants"),f=e("./invariant"),h={Mount:null,injectMount:function(e){h.Mount=e}},v=d.topLevelTypes,m={isEndish:n,isMoveish:r,isStartish:o,executeDirectDispatch:l,executeDispatch:a,executeDispatchesInOrder:s,executeDispatchesInOrderStopAtTrue:c,hasDispatches:p,injection:h,useTouchEvents:!1};t.exports=m},{"./EventConstants":16,"./invariant":131}],21:[function(e,t){"use strict";function n(e,t,n){var r=t.dispatchConfig.phasedRegistrationNames[n];return v(e,r)}function r(e,t,r){var o=t?h.bubbled:h.captured,i=n(e,r,o);i&&(r._dispatchListeners=d(r._dispatchListeners,i),r._dispatchIDs=d(r._dispatchIDs,e))}function o(e){e&&e.dispatchConfig.phasedRegistrationNames&&p.injection.getInstanceHandle().traverseTwoPhase(e.dispatchMarker,r,e)}function i(e,t,n){if(n&&n.dispatchConfig.registrationName){var r=n.dispatchConfig.registrationName,o=v(e,r);o&&(n._dispatchListeners=d(n._dispatchListeners,o),n._dispatchIDs=d(n._dispatchIDs,e))}}function a(e){e&&e.dispatchConfig.registrationName&&i(e.dispatchMarker,null,e)}function s(e){f(e,o)}function u(e,t,n,r){p.injection.getInstanceHandle().traverseEnterLeave(n,r,i,e,t)}function c(e){f(e,a)}var l=e("./EventConstants"),p=e("./EventPluginHub"),d=e("./accumulate"),f=e("./forEachAccumulated"),h=l.PropagationPhases,v=p.getListener,m={accumulateTwoPhaseDispatches:s,accumulateDirectDispatches:c,accumulateEnterLeaveDispatches:u};t.exports=m},{"./EventConstants":16,"./EventPluginHub":18,"./accumulate":103,"./forEachAccumulated":118}],22:[function(e,t){"use strict";var n=!("undefined"==typeof window||!window.document||!window.document.createElement),r={canUseDOM:n,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:n&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:n&&!!window.screen,isInWorker:!n};t.exports=r},{}],23:[function(e,t){"use strict";var n,r=e("./DOMProperty"),o=e("./ExecutionEnvironment"),i=r.injection.MUST_USE_ATTRIBUTE,a=r.injection.MUST_USE_PROPERTY,s=r.injection.HAS_BOOLEAN_VALUE,u=r.injection.HAS_SIDE_EFFECTS,c=r.injection.HAS_NUMERIC_VALUE,l=r.injection.HAS_POSITIVE_NUMERIC_VALUE,p=r.injection.HAS_OVERLOADED_BOOLEAN_VALUE;if(o.canUseDOM){var d=document.implementation;n=d&&d.hasFeature&&d.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}var f={isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),Properties:{accept:null,accessKey:null,action:null,allowFullScreen:i|s,allowTransparency:i,alt:null,async:s,autoComplete:null,autoPlay:s,cellPadding:null,cellSpacing:null,charSet:i,checked:a|s,className:n?i:a,cols:i|l,colSpan:null,content:null,contentEditable:null,contextMenu:i,controls:a|s,coords:null,crossOrigin:null,data:null,dateTime:i,defer:s,dir:null,disabled:i|s,download:p,draggable:null,encType:null,form:i,formNoValidate:s,frameBorder:i,height:i,hidden:i|s,href:null,hrefLang:null,htmlFor:null,httpEquiv:null,icon:null,id:a,label:null,lang:null,list:null,loop:a|s,max:null,maxLength:i,mediaGroup:null,method:null,min:null,multiple:a|s,muted:a|s,name:null,noValidate:s,pattern:null,placeholder:null,poster:null,preload:null,radioGroup:null,readOnly:a|s,rel:null,required:s,role:i,rows:i|l,rowSpan:null,sandbox:null,scope:null,scrollLeft:a,scrolling:null,scrollTop:a,seamless:i|s,selected:a|s,shape:null,size:i|l,span:l,spellCheck:null,src:null,srcDoc:a,srcSet:null,start:c,step:null,style:null,tabIndex:null,target:null,title:null,type:null,useMap:null,value:a|u,width:i,wmode:i,autoCapitalize:null,autoCorrect:null,itemProp:i,itemScope:i|s,itemType:i,property:null},DOMAttributeNames:{className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{autoCapitalize:"autocapitalize",autoComplete:"autocomplete",autoCorrect:"autocorrect",autoFocus:"autofocus",autoPlay:"autoplay",encType:"enctype",hrefLang:"hreflang",radioGroup:"radiogroup",spellCheck:"spellcheck",srcDoc:"srcdoc",srcSet:"srcset"}};t.exports=f},{"./DOMProperty":11,"./ExecutionEnvironment":22}],24:[function(e,t){"use strict";var n=e("./ReactLink"),r=e("./ReactStateSetters"),o={linkState:function(e){return new n(this.state[e],r.createStateKeySetter(this,e))}};t.exports=o},{"./ReactLink":63,"./ReactStateSetters":79}],25:[function(e,t){"use strict";function n(e){u(null==e.props.checkedLink||null==e.props.valueLink)}function r(e){n(e),u(null==e.props.value&&null==e.props.onChange)}function o(e){n(e),u(null==e.props.checked&&null==e.props.onChange)}function i(e){this.props.valueLink.requestChange(e.target.value)}function a(e){this.props.checkedLink.requestChange(e.target.checked)}var s=e("./ReactPropTypes"),u=e("./invariant"),c={button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0},l={Mixin:{propTypes:{value:function(e,t){return!e[t]||c[e.type]||e.onChange||e.readOnly||e.disabled?void 0:new Error("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.")},checked:function(e,t){return!e[t]||e.onChange||e.readOnly||e.disabled?void 0:new Error("You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")},onChange:s.func}},getValue:function(e){return e.props.valueLink?(r(e),e.props.valueLink.value):e.props.value},getChecked:function(e){return e.props.checkedLink?(o(e),e.props.checkedLink.value):e.props.checked},getOnChange:function(e){return e.props.valueLink?(r(e),i):e.props.checkedLink?(o(e),a):e.props.onChange}};t.exports=l},{"./ReactPropTypes":73,"./invariant":131}],26:[function(e,t){"use strict";function n(e){e.remove()}var r=e("./ReactBrowserEventEmitter"),o=e("./accumulate"),i=e("./forEachAccumulated"),a=e("./invariant"),s={trapBubbledEvent:function(e,t){a(this.isMounted());var n=r.trapBubbledEvent(e,t,this.getDOMNode());this._localEventListeners=o(this._localEventListeners,n)},componentWillUnmount:function(){this._localEventListeners&&i(this._localEventListeners,n)}};t.exports=s},{"./ReactBrowserEventEmitter":31,"./accumulate":103,"./forEachAccumulated":118,"./invariant":131}],27:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./emptyFunction"),o=n.topLevelTypes,i={eventTypes:null,extractEvents:function(e,t,n,i){if(e===o.topTouchStart){var a=i.target;a&&!a.onclick&&(a.onclick=r)}}};t.exports=i},{"./EventConstants":16,"./emptyFunction":113}],28:[function(e,t){"use strict";var n=e("./invariant"),r=function(e){var t=this;if(t.instancePool.length){var n=t.instancePool.pop();return t.call(n,e),n}return new t(e)},o=function(e,t){var n=this;if(n.instancePool.length){var r=n.instancePool.pop();return n.call(r,e,t),r}return new n(e,t)},i=function(e,t,n){var r=this;if(r.instancePool.length){var o=r.instancePool.pop();return r.call(o,e,t,n),o}return new r(e,t,n)},a=function(e,t,n,r,o){var i=this;if(i.instancePool.length){var a=i.instancePool.pop();return i.call(a,e,t,n,r,o),a}return new i(e,t,n,r,o)},s=function(e){var t=this;n(e instanceof t),e.destructor&&e.destructor(),t.instancePool.length<t.poolSize&&t.instancePool.push(e)},u=10,c=r,l=function(e,t){var n=e;return n.instancePool=[],n.getPooled=t||c,n.poolSize||(n.poolSize=u),n.release=s,n},p={addPoolingTo:l,oneArgumentPooler:r,twoArgumentPooler:o,threeArgumentPooler:i,fiveArgumentPooler:a};t.exports=p},{"./invariant":131}],29:[function(e,t){"use strict";var n=e("./DOMPropertyOperations"),r=e("./EventPluginUtils"),o=e("./ReactChildren"),i=e("./ReactComponent"),a=e("./ReactCompositeComponent"),s=e("./ReactContext"),u=e("./ReactCurrentOwner"),c=e("./ReactDescriptor"),l=e("./ReactDOM"),p=e("./ReactDOMComponent"),d=e("./ReactDefaultInjection"),f=e("./ReactInstanceHandles"),h=e("./ReactMount"),v=e("./ReactMultiChild"),m=e("./ReactPerf"),g=e("./ReactPropTypes"),y=e("./ReactServerRendering"),C=e("./ReactTextComponent"),E=e("./onlyChild");d.inject();var R={Children:{map:o.map,forEach:o.forEach,count:o.count,only:E},DOM:l,PropTypes:g,initializeTouchEvents:function(e){r.useTouchEvents=e},createClass:a.createClass,createDescriptor:function(e){var t=Array.prototype.slice.call(arguments,1);return e.apply(null,t)},constructAndRenderComponent:h.constructAndRenderComponent,constructAndRenderComponentByID:h.constructAndRenderComponentByID,renderComponent:m.measure("React","renderComponent",h.renderComponent),renderComponentToString:y.renderComponentToString,renderComponentToStaticMarkup:y.renderComponentToStaticMarkup,unmountComponentAtNode:h.unmountComponentAtNode,isValidClass:c.isValidFactory,isValidComponent:c.isValidDescriptor,withContext:s.withContext,__internals:{Component:i,CurrentOwner:u,DOMComponent:p,DOMPropertyOperations:n,InstanceHandles:f,Mount:h,MultiChild:v,TextComponent:C}};R.version="0.11.1",t.exports=R},{"./DOMPropertyOperations":12,"./EventPluginUtils":20,"./ReactChildren":34,"./ReactComponent":35,"./ReactCompositeComponent":38,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDOM":41,"./ReactDOMComponent":43,"./ReactDefaultInjection":53,"./ReactDescriptor":54,"./ReactInstanceHandles":62,"./ReactMount":65,"./ReactMultiChild":66,"./ReactPerf":69,"./ReactPropTypes":73,"./ReactServerRendering":77,"./ReactTextComponent":80,"./onlyChild":146}],30:[function(e,t){"use strict";
-var n=e("./ReactEmptyComponent"),r=e("./ReactMount"),o=e("./invariant"),i={getDOMNode:function(){return o(this.isMounted()),n.isNullComponentID(this._rootNodeID)?null:r.getNode(this._rootNodeID)}};t.exports=i},{"./ReactEmptyComponent":56,"./ReactMount":65,"./invariant":131}],31:[function(e,t){"use strict";function n(e){return Object.prototype.hasOwnProperty.call(e,h)||(e[h]=d++,l[e[h]]={}),l[e[h]]}var r=e("./EventConstants"),o=e("./EventPluginHub"),i=e("./EventPluginRegistry"),a=e("./ReactEventEmitterMixin"),s=e("./ViewportMetrics"),u=e("./isEventSupported"),c=e("./merge"),l={},p=!1,d=0,f={topBlur:"blur",topChange:"change",topClick:"click",topCompositionEnd:"compositionend",topCompositionStart:"compositionstart",topCompositionUpdate:"compositionupdate",topContextMenu:"contextmenu",topCopy:"copy",topCut:"cut",topDoubleClick:"dblclick",topDrag:"drag",topDragEnd:"dragend",topDragEnter:"dragenter",topDragExit:"dragexit",topDragLeave:"dragleave",topDragOver:"dragover",topDragStart:"dragstart",topDrop:"drop",topFocus:"focus",topInput:"input",topKeyDown:"keydown",topKeyPress:"keypress",topKeyUp:"keyup",topMouseDown:"mousedown",topMouseMove:"mousemove",topMouseOut:"mouseout",topMouseOver:"mouseover",topMouseUp:"mouseup",topPaste:"paste",topScroll:"scroll",topSelectionChange:"selectionchange",topTextInput:"textInput",topTouchCancel:"touchcancel",topTouchEnd:"touchend",topTouchMove:"touchmove",topTouchStart:"touchstart",topWheel:"wheel"},h="_reactListenersID"+String(Math.random()).slice(2),v=c(a,{ReactEventListener:null,injection:{injectReactEventListener:function(e){e.setHandleTopLevel(v.handleTopLevel),v.ReactEventListener=e}},setEnabled:function(e){v.ReactEventListener&&v.ReactEventListener.setEnabled(e)},isEnabled:function(){return!(!v.ReactEventListener||!v.ReactEventListener.isEnabled())},listenTo:function(e,t){for(var o=t,a=n(o),s=i.registrationNameDependencies[e],c=r.topLevelTypes,l=0,p=s.length;p>l;l++){var d=s[l];a.hasOwnProperty(d)&&a[d]||(d===c.topWheel?u("wheel")?v.ReactEventListener.trapBubbledEvent(c.topWheel,"wheel",o):u("mousewheel")?v.ReactEventListener.trapBubbledEvent(c.topWheel,"mousewheel",o):v.ReactEventListener.trapBubbledEvent(c.topWheel,"DOMMouseScroll",o):d===c.topScroll?u("scroll",!0)?v.ReactEventListener.trapCapturedEvent(c.topScroll,"scroll",o):v.ReactEventListener.trapBubbledEvent(c.topScroll,"scroll",v.ReactEventListener.WINDOW_HANDLE):d===c.topFocus||d===c.topBlur?(u("focus",!0)?(v.ReactEventListener.trapCapturedEvent(c.topFocus,"focus",o),v.ReactEventListener.trapCapturedEvent(c.topBlur,"blur",o)):u("focusin")&&(v.ReactEventListener.trapBubbledEvent(c.topFocus,"focusin",o),v.ReactEventListener.trapBubbledEvent(c.topBlur,"focusout",o)),a[c.topBlur]=!0,a[c.topFocus]=!0):f.hasOwnProperty(d)&&v.ReactEventListener.trapBubbledEvent(d,f[d],o),a[d]=!0)}},trapBubbledEvent:function(e,t,n){return v.ReactEventListener.trapBubbledEvent(e,t,n)},trapCapturedEvent:function(e,t,n){return v.ReactEventListener.trapCapturedEvent(e,t,n)},ensureScrollValueMonitoring:function(){if(!p){var e=s.refreshScrollValues;v.ReactEventListener.monitorScrollValue(e),p=!0}},eventNameDispatchConfigs:o.eventNameDispatchConfigs,registrationNameModules:o.registrationNameModules,putListener:o.putListener,getListener:o.getListener,deleteListener:o.deleteListener,deleteAllListeners:o.deleteAllListeners});t.exports=v},{"./EventConstants":16,"./EventPluginHub":18,"./EventPluginRegistry":19,"./ReactEventEmitterMixin":58,"./ViewportMetrics":102,"./isEventSupported":132,"./merge":141}],32:[function(e,t){"use strict";var n=e("./React"),r=e("./ReactTransitionGroup"),o=e("./ReactCSSTransitionGroupChild"),i=n.createClass({displayName:"ReactCSSTransitionGroup",propTypes:{transitionName:n.PropTypes.string.isRequired,transitionEnter:n.PropTypes.bool,transitionLeave:n.PropTypes.bool},getDefaultProps:function(){return{transitionEnter:!0,transitionLeave:!0}},_wrapChild:function(e){return o({name:this.props.transitionName,enter:this.props.transitionEnter,leave:this.props.transitionLeave},e)},render:function(){return this.transferPropsTo(r({childFactory:this._wrapChild},this.props.children))}});t.exports=i},{"./React":29,"./ReactCSSTransitionGroupChild":33,"./ReactTransitionGroup":83}],33:[function(e,t){"use strict";var n=e("./React"),r=e("./CSSCore"),o=e("./ReactTransitionEvents"),i=e("./onlyChild"),a=17,s=n.createClass({displayName:"ReactCSSTransitionGroupChild",transition:function(e,t){var n=this.getDOMNode(),i=this.props.name+"-"+e,a=i+"-active",s=function(){r.removeClass(n,i),r.removeClass(n,a),o.removeEndEventListener(n,s),t&&t()};o.addEndEventListener(n,s),r.addClass(n,i),this.queueClass(a)},queueClass:function(e){this.classNameQueue.push(e),this.timeout||(this.timeout=setTimeout(this.flushClassNameQueue,a))},flushClassNameQueue:function(){this.isMounted()&&this.classNameQueue.forEach(r.addClass.bind(r,this.getDOMNode())),this.classNameQueue.length=0,this.timeout=null},componentWillMount:function(){this.classNameQueue=[]},componentWillUnmount:function(){this.timeout&&clearTimeout(this.timeout)},componentWillEnter:function(e){this.props.enter?this.transition("enter",e):e()},componentWillLeave:function(e){this.props.leave?this.transition("leave",e):e()},render:function(){return i(this.props.children)}});t.exports=s},{"./CSSCore":3,"./React":29,"./ReactTransitionEvents":82,"./onlyChild":146}],34:[function(e,t){"use strict";function n(e,t){this.forEachFunction=e,this.forEachContext=t}function r(e,t,n,r){var o=e;o.forEachFunction.call(o.forEachContext,t,r)}function o(e,t,o){if(null==e)return e;var i=n.getPooled(t,o);p(e,r,i),n.release(i)}function i(e,t,n){this.mapResult=e,this.mapFunction=t,this.mapContext=n}function a(e,t,n,r){var o=e,i=o.mapResult,a=!i.hasOwnProperty(n);if(a){var s=o.mapFunction.call(o.mapContext,t,r);i[n]=s}}function s(e,t,n){if(null==e)return e;var r={},o=i.getPooled(r,t,n);return p(e,a,o),i.release(o),r}function u(){return null}function c(e){return p(e,u,null)}var l=e("./PooledClass"),p=e("./traverseAllChildren"),d=(e("./warning"),l.twoArgumentPooler),f=l.threeArgumentPooler;l.addPoolingTo(n,d),l.addPoolingTo(i,f);var h={forEach:o,map:s,count:c};t.exports=h},{"./PooledClass":28,"./traverseAllChildren":151,"./warning":153}],35:[function(e,t){"use strict";var n=e("./ReactDescriptor"),r=e("./ReactOwner"),o=e("./ReactUpdates"),i=e("./invariant"),a=e("./keyMirror"),s=e("./merge"),u=a({MOUNTED:null,UNMOUNTED:null}),c=!1,l=null,p=null,d={injection:{injectEnvironment:function(e){i(!c),p=e.mountImageIntoNode,l=e.unmountIDFromEnvironment,d.BackendIDOperations=e.BackendIDOperations,c=!0}},LifeCycle:u,BackendIDOperations:null,Mixin:{isMounted:function(){return this._lifeCycleState===u.MOUNTED},setProps:function(e,t){var n=this._pendingDescriptor||this._descriptor;this.replaceProps(s(n.props,e),t)},replaceProps:function(e,t){i(this.isMounted()),i(0===this._mountDepth),this._pendingDescriptor=n.cloneAndReplaceProps(this._pendingDescriptor||this._descriptor,e),o.enqueueUpdate(this,t)},_setPropsInternal:function(e,t){var r=this._pendingDescriptor||this._descriptor;this._pendingDescriptor=n.cloneAndReplaceProps(r,s(r.props,e)),o.enqueueUpdate(this,t)},construct:function(e){this.props=e.props,this._owner=e._owner,this._lifeCycleState=u.UNMOUNTED,this._pendingCallbacks=null,this._descriptor=e,this._pendingDescriptor=null},mountComponent:function(e,t,n){i(!this.isMounted());var o=this._descriptor.props;if(null!=o.ref){var a=this._descriptor._owner;r.addComponentAsRefTo(this,o.ref,a)}this._rootNodeID=e,this._lifeCycleState=u.MOUNTED,this._mountDepth=n},unmountComponent:function(){i(this.isMounted());var e=this.props;null!=e.ref&&r.removeComponentAsRefFrom(this,e.ref,this._owner),l(this._rootNodeID),this._rootNodeID=null,this._lifeCycleState=u.UNMOUNTED},receiveComponent:function(e,t){i(this.isMounted()),this._pendingDescriptor=e,this.performUpdateIfNecessary(t)},performUpdateIfNecessary:function(e){if(null!=this._pendingDescriptor){var t=this._descriptor,n=this._pendingDescriptor;this._descriptor=n,this.props=n.props,this._owner=n._owner,this._pendingDescriptor=null,this.updateComponent(e,t)}},updateComponent:function(e,t){var n=this._descriptor;(n._owner!==t._owner||n.props.ref!==t.props.ref)&&(null!=t.props.ref&&r.removeComponentAsRefFrom(this,t.props.ref,t._owner),null!=n.props.ref&&r.addComponentAsRefTo(this,n.props.ref,n._owner))},mountComponentIntoNode:function(e,t,n){var r=o.ReactReconcileTransaction.getPooled();r.perform(this._mountComponentIntoNode,this,e,t,r,n),o.ReactReconcileTransaction.release(r)},_mountComponentIntoNode:function(e,t,n,r){var o=this.mountComponent(e,n,0);p(o,t,r)},isOwnedBy:function(e){return this._owner===e},getSiblingByRef:function(e){var t=this._owner;return t&&t.refs?t.refs[e]:null}}};t.exports=d},{"./ReactDescriptor":54,"./ReactOwner":68,"./ReactUpdates":84,"./invariant":131,"./keyMirror":137,"./merge":141}],36:[function(e,t){"use strict";var n=e("./ReactDOMIDOperations"),r=e("./ReactMarkupChecksum"),o=e("./ReactMount"),i=e("./ReactPerf"),a=e("./ReactReconcileTransaction"),s=e("./getReactRootElementInContainer"),u=e("./invariant"),c=e("./setInnerHTML"),l=1,p=9,d={ReactReconcileTransaction:a,BackendIDOperations:n,unmountIDFromEnvironment:function(e){o.purgeID(e)},mountImageIntoNode:i.measure("ReactComponentBrowserEnvironment","mountImageIntoNode",function(e,t,n){if(u(t&&(t.nodeType===l||t.nodeType===p)),n){if(r.canReuseMarkup(e,s(t)))return;u(t.nodeType!==p)}u(t.nodeType!==p),c(t,e)})};t.exports=d},{"./ReactDOMIDOperations":45,"./ReactMarkupChecksum":64,"./ReactMount":65,"./ReactPerf":69,"./ReactReconcileTransaction":75,"./getReactRootElementInContainer":125,"./invariant":131,"./setInnerHTML":147}],37:[function(e,t){"use strict";var n=e("./shallowEqual"),r={shouldComponentUpdate:function(e,t){return!n(this.props,e)||!n(this.state,t)}};t.exports=r},{"./shallowEqual":148}],38:[function(e,t){"use strict";function n(e){var t=e._owner||null;return t&&t.constructor&&t.constructor.displayName?" Check the render method of `"+t.constructor.displayName+"`.":""}function r(e,t){for(var n in t)t.hasOwnProperty(n)&&D("function"==typeof t[n])}function o(e,t){var n=_.hasOwnProperty(t)?_[t]:null;k.hasOwnProperty(t)&&D(n===S.OVERRIDE_BASE),e.hasOwnProperty(t)&&D(n===S.DEFINE_MANY||n===S.DEFINE_MANY_MERGED)}function i(e){var t=e._compositeLifeCycleState;D(e.isMounted()||t===N.MOUNTING),D(t!==N.RECEIVING_STATE),D(t!==N.UNMOUNTING)}function a(e,t){D(!h.isValidFactory(t)),D(!h.isValidDescriptor(t));var n=e.prototype;for(var r in t){var i=t[r];if(t.hasOwnProperty(r))if(o(n,r),I.hasOwnProperty(r))I[r](e,i);else{var a=_.hasOwnProperty(r),s=n.hasOwnProperty(r),u=i&&i.__reactDontBind,p="function"==typeof i,d=p&&!a&&!s&&!u;if(d)n.__reactAutoBindMap||(n.__reactAutoBindMap={}),n.__reactAutoBindMap[r]=i,n[r]=i;else if(s){var f=_[r];D(a&&(f===S.DEFINE_MANY_MERGED||f===S.DEFINE_MANY)),f===S.DEFINE_MANY_MERGED?n[r]=c(n[r],i):f===S.DEFINE_MANY&&(n[r]=l(n[r],i))}else n[r]=i}}}function s(e,t){if(t)for(var n in t){var r=t[n];if(t.hasOwnProperty(n)){var o=n in e,i=r;if(o){var a=e[n],s=typeof a,u=typeof r;D("function"===s&&"function"===u),i=l(a,r)}e[n]=i}}}function u(e,t){return D(e&&t&&"object"==typeof e&&"object"==typeof t),P(t,function(t,n){D(void 0===e[n]),e[n]=t}),e}function c(e,t){return function(){var n=e.apply(this,arguments),r=t.apply(this,arguments);return null==n?r:null==r?n:u(n,r)}}function l(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}var p=e("./ReactComponent"),d=e("./ReactContext"),f=e("./ReactCurrentOwner"),h=e("./ReactDescriptor"),v=(e("./ReactDescriptorValidator"),e("./ReactEmptyComponent")),m=e("./ReactErrorUtils"),g=e("./ReactOwner"),y=e("./ReactPerf"),C=e("./ReactPropTransferer"),E=e("./ReactPropTypeLocations"),R=(e("./ReactPropTypeLocationNames"),e("./ReactUpdates")),M=e("./instantiateReactComponent"),D=e("./invariant"),x=e("./keyMirror"),b=e("./merge"),O=e("./mixInto"),P=(e("./monitorCodeUse"),e("./mapObject")),T=e("./shouldUpdateReactComponent"),S=(e("./warning"),x({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null})),w=[],_={mixins:S.DEFINE_MANY,statics:S.DEFINE_MANY,propTypes:S.DEFINE_MANY,contextTypes:S.DEFINE_MANY,childContextTypes:S.DEFINE_MANY,getDefaultProps:S.DEFINE_MANY_MERGED,getInitialState:S.DEFINE_MANY_MERGED,getChildContext:S.DEFINE_MANY_MERGED,render:S.DEFINE_ONCE,componentWillMount:S.DEFINE_MANY,componentDidMount:S.DEFINE_MANY,componentWillReceiveProps:S.DEFINE_MANY,shouldComponentUpdate:S.DEFINE_ONCE,componentWillUpdate:S.DEFINE_MANY,componentDidUpdate:S.DEFINE_MANY,componentWillUnmount:S.DEFINE_MANY,updateComponent:S.OVERRIDE_BASE},I={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n<t.length;n++)a(e,t[n])},childContextTypes:function(e,t){r(e,t,E.childContext),e.childContextTypes=b(e.childContextTypes,t)},contextTypes:function(e,t){r(e,t,E.context),e.contextTypes=b(e.contextTypes,t)},getDefaultProps:function(e,t){e.getDefaultProps=e.getDefaultProps?c(e.getDefaultProps,t):t},propTypes:function(e,t){r(e,t,E.prop),e.propTypes=b(e.propTypes,t)},statics:function(e,t){s(e,t)}},N=x({MOUNTING:null,UNMOUNTING:null,RECEIVING_PROPS:null,RECEIVING_STATE:null}),k={construct:function(){p.Mixin.construct.apply(this,arguments),g.Mixin.construct.apply(this,arguments),this.state=null,this._pendingState=null,this.context=null,this._compositeLifeCycleState=null},isMounted:function(){return p.Mixin.isMounted.call(this)&&this._compositeLifeCycleState!==N.MOUNTING},mountComponent:y.measure("ReactCompositeComponent","mountComponent",function(e,t,n){p.Mixin.mountComponent.call(this,e,t,n),this._compositeLifeCycleState=N.MOUNTING,this.__reactAutoBindMap&&this._bindAutoBindMethods(),this.context=this._processContext(this._descriptor._context),this.props=this._processProps(this.props),this.state=this.getInitialState?this.getInitialState():null,D("object"==typeof this.state&&!Array.isArray(this.state)),this._pendingState=null,this._pendingForceUpdate=!1,this.componentWillMount&&(this.componentWillMount(),this._pendingState&&(this.state=this._pendingState,this._pendingState=null)),this._renderedComponent=M(this._renderValidatedComponent()),this._compositeLifeCycleState=null;var r=this._renderedComponent.mountComponent(e,t,n+1);return this.componentDidMount&&t.getReactMountReady().enqueue(this.componentDidMount,this),r}),unmountComponent:function(){this._compositeLifeCycleState=N.UNMOUNTING,this.componentWillUnmount&&this.componentWillUnmount(),this._compositeLifeCycleState=null,this._renderedComponent.unmountComponent(),this._renderedComponent=null,p.Mixin.unmountComponent.call(this)},setState:function(e,t){D("object"==typeof e||null==e),this.replaceState(b(this._pendingState||this.state,e),t)},replaceState:function(e,t){i(this),this._pendingState=e,this._compositeLifeCycleState!==N.MOUNTING&&R.enqueueUpdate(this,t)},_processContext:function(e){var t=null,n=this.constructor.contextTypes;if(n){t={};for(var r in n)t[r]=e[r]}return t},_processChildContext:function(e){var t=this.getChildContext&&this.getChildContext();if(this.constructor.displayName||"ReactCompositeComponent",t){D("object"==typeof this.constructor.childContextTypes);for(var n in t)D(n in this.constructor.childContextTypes);return b(e,t)}return e},_processProps:function(e){var t,n=this.constructor.defaultProps;if(n){t=b(e);for(var r in n)"undefined"==typeof t[r]&&(t[r]=n[r])}else t=e;return t},_checkPropTypes:function(e,t,r){var o=this.constructor.displayName;for(var i in e)if(e.hasOwnProperty(i)){var a=e[i](t,i,o,r);a instanceof Error&&n(this)}},performUpdateIfNecessary:function(e){var t=this._compositeLifeCycleState;if(t!==N.MOUNTING&&t!==N.RECEIVING_PROPS&&(null!=this._pendingDescriptor||null!=this._pendingState||this._pendingForceUpdate)){var n=this.context,r=this.props,o=this._descriptor;null!=this._pendingDescriptor&&(o=this._pendingDescriptor,n=this._processContext(o._context),r=this._processProps(o.props),this._pendingDescriptor=null,this._compositeLifeCycleState=N.RECEIVING_PROPS,this.componentWillReceiveProps&&this.componentWillReceiveProps(r,n)),this._compositeLifeCycleState=N.RECEIVING_STATE;var i=this._pendingState||this.state;this._pendingState=null;try{var a=this._pendingForceUpdate||!this.shouldComponentUpdate||this.shouldComponentUpdate(r,i,n);a?(this._pendingForceUpdate=!1,this._performComponentUpdate(o,r,i,n,e)):(this._descriptor=o,this.props=r,this.state=i,this.context=n,this._owner=o._owner)}finally{this._compositeLifeCycleState=null}}},_performComponentUpdate:function(e,t,n,r,o){var i=this._descriptor,a=this.props,s=this.state,u=this.context;this.componentWillUpdate&&this.componentWillUpdate(t,n,r),this._descriptor=e,this.props=t,this.state=n,this.context=r,this._owner=e._owner,this.updateComponent(o,i),this.componentDidUpdate&&o.getReactMountReady().enqueue(this.componentDidUpdate.bind(this,a,s,u),this)},receiveComponent:function(e,t){(e!==this._descriptor||null==e._owner)&&p.Mixin.receiveComponent.call(this,e,t)},updateComponent:y.measure("ReactCompositeComponent","updateComponent",function(e,t){p.Mixin.updateComponent.call(this,e,t);var n=this._renderedComponent,r=n._descriptor,o=this._renderValidatedComponent();if(T(r,o))n.receiveComponent(o,e);else{var i=this._rootNodeID,a=n._rootNodeID;n.unmountComponent(),this._renderedComponent=M(o);var s=this._renderedComponent.mountComponent(i,e,this._mountDepth+1);p.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(a,s)}}),forceUpdate:function(e){var t=this._compositeLifeCycleState;D(this.isMounted()||t===N.MOUNTING),D(t!==N.RECEIVING_STATE&&t!==N.UNMOUNTING),this._pendingForceUpdate=!0,R.enqueueUpdate(this,e)},_renderValidatedComponent:y.measure("ReactCompositeComponent","_renderValidatedComponent",function(){var e,t=d.current;d.current=this._processChildContext(this._descriptor._context),f.current=this;try{e=this.render(),null===e||e===!1?(e=v.getEmptyComponent(),v.registerNullComponentID(this._rootNodeID)):v.deregisterNullComponentID(this._rootNodeID)}finally{d.current=t,f.current=null}return D(h.isValidDescriptor(e)),e}),_bindAutoBindMethods:function(){for(var e in this.__reactAutoBindMap)if(this.__reactAutoBindMap.hasOwnProperty(e)){var t=this.__reactAutoBindMap[e];this[e]=this._bindAutoBindMethod(m.guard(t,this.constructor.displayName+"."+e))}},_bindAutoBindMethod:function(e){var t=this,n=function(){return e.apply(t,arguments)};return n}},A=function(){};O(A,p.Mixin),O(A,g.Mixin),O(A,C.Mixin),O(A,k);var L={LifeCycle:N,Base:A,createClass:function(e){var t=function(e,t){this.construct(e,t)};t.prototype=new A,t.prototype.constructor=t,w.forEach(a.bind(null,t)),a(t,e),t.getDefaultProps&&(t.defaultProps=t.getDefaultProps()),D(t.prototype.render);for(var n in _)t.prototype[n]||(t.prototype[n]=null);var r=h.createFactory(t);return r},injection:{injectMixin:function(e){w.push(e)}}};t.exports=L},{"./ReactComponent":35,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDescriptor":54,"./ReactDescriptorValidator":55,"./ReactEmptyComponent":56,"./ReactErrorUtils":57,"./ReactOwner":68,"./ReactPerf":69,"./ReactPropTransferer":70,"./ReactPropTypeLocationNames":71,"./ReactPropTypeLocations":72,"./ReactUpdates":84,"./instantiateReactComponent":130,"./invariant":131,"./keyMirror":137,"./mapObject":139,"./merge":141,"./mixInto":144,"./monitorCodeUse":145,"./shouldUpdateReactComponent":149,"./warning":153}],39:[function(e,t){"use strict";var n=e("./merge"),r={current:{},withContext:function(e,t){var o,i=r.current;r.current=n(i,e);try{o=t()}finally{r.current=i}return o}};t.exports=r},{"./merge":141}],40:[function(e,t){"use strict";var n={current:null};t.exports=n},{}],41:[function(e,t){"use strict";function n(e,t){var n=function(e){this.construct(e)};n.prototype=new o(t,e),n.prototype.constructor=n,n.displayName=t;var i=r.createFactory(n);return i}var r=e("./ReactDescriptor"),o=(e("./ReactDescriptorValidator"),e("./ReactDOMComponent")),i=e("./mergeInto"),a=e("./mapObject"),s=a({a:!1,abbr:!1,address:!1,area:!0,article:!1,aside:!1,audio:!1,b:!1,base:!0,bdi:!1,bdo:!1,big:!1,blockquote:!1,body:!1,br:!0,button:!1,canvas:!1,caption:!1,cite:!1,code:!1,col:!0,colgroup:!1,data:!1,datalist:!1,dd:!1,del:!1,details:!1,dfn:!1,div:!1,dl:!1,dt:!1,em:!1,embed:!0,fieldset:!1,figcaption:!1,figure:!1,footer:!1,form:!1,h1:!1,h2:!1,h3:!1,h4:!1,h5:!1,h6:!1,head:!1,header:!1,hr:!0,html:!1,i:!1,iframe:!1,img:!0,input:!0,ins:!1,kbd:!1,keygen:!0,label:!1,legend:!1,li:!1,link:!0,main:!1,map:!1,mark:!1,menu:!1,menuitem:!1,meta:!0,meter:!1,nav:!1,noscript:!1,object:!1,ol:!1,optgroup:!1,option:!1,output:!1,p:!1,param:!0,pre:!1,progress:!1,q:!1,rp:!1,rt:!1,ruby:!1,s:!1,samp:!1,script:!1,section:!1,select:!1,small:!1,source:!0,span:!1,strong:!1,style:!1,sub:!1,summary:!1,sup:!1,table:!1,tbody:!1,td:!1,textarea:!1,tfoot:!1,th:!1,thead:!1,time:!1,title:!1,tr:!1,track:!0,u:!1,ul:!1,"var":!1,video:!1,wbr:!0,circle:!1,defs:!1,ellipse:!1,g:!1,line:!1,linearGradient:!1,mask:!1,path:!1,pattern:!1,polygon:!1,polyline:!1,radialGradient:!1,rect:!1,stop:!1,svg:!1,text:!1,tspan:!1},n),u={injectComponentClasses:function(e){i(s,e)}};s.injection=u,t.exports=s},{"./ReactDOMComponent":43,"./ReactDescriptor":54,"./ReactDescriptorValidator":55,"./mapObject":139,"./mergeInto":143}],42:[function(e,t){"use strict";var n=e("./AutoFocusMixin"),r=e("./ReactBrowserComponentMixin"),o=e("./ReactCompositeComponent"),i=e("./ReactDOM"),a=e("./keyMirror"),s=i.button,u=a({onClick:!0,onDoubleClick:!0,onMouseDown:!0,onMouseMove:!0,onMouseUp:!0,onClickCapture:!0,onDoubleClickCapture:!0,onMouseDownCapture:!0,onMouseMoveCapture:!0,onMouseUpCapture:!0}),c=o.createClass({displayName:"ReactDOMButton",mixins:[n,r],render:function(){var e={};for(var t in this.props)!this.props.hasOwnProperty(t)||this.props.disabled&&u[t]||(e[t]=this.props[t]);return s(e,this.props.children)}});t.exports=c},{"./AutoFocusMixin":1,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./keyMirror":137}],43:[function(e,t){"use strict";function n(e){e&&(v(null==e.children||null==e.dangerouslySetInnerHTML),v(null==e.style||"object"==typeof e.style))}function r(e,t,n,r){var o=p.findReactContainerForID(e);if(o){var i=o.nodeType===x?o.ownerDocument:o;E(t,i)}r.getPutListenerQueue().enqueuePutListener(e,t,n)}function o(e,t){this._tagOpen="<"+e,this._tagClose=t?"":"</"+e+">",this.tagName=e.toUpperCase()}var i=e("./CSSPropertyOperations"),a=e("./DOMProperty"),s=e("./DOMPropertyOperations"),u=e("./ReactBrowserComponentMixin"),c=e("./ReactComponent"),l=e("./ReactBrowserEventEmitter"),p=e("./ReactMount"),d=e("./ReactMultiChild"),f=e("./ReactPerf"),h=e("./escapeTextForBrowser"),v=e("./invariant"),m=e("./keyOf"),g=e("./merge"),y=e("./mixInto"),C=l.deleteListener,E=l.listenTo,R=l.registrationNameModules,M={string:!0,number:!0},D=m({style:null}),x=1;o.Mixin={mountComponent:f.measure("ReactDOMComponent","mountComponent",function(e,t,r){return c.Mixin.mountComponent.call(this,e,t,r),n(this.props),this._createOpenTagMarkupAndPutListeners(t)+this._createContentMarkup(t)+this._tagClose}),_createOpenTagMarkupAndPutListeners:function(e){var t=this.props,n=this._tagOpen;for(var o in t)if(t.hasOwnProperty(o)){var a=t[o];if(null!=a)if(R.hasOwnProperty(o))r(this._rootNodeID,o,a,e);else{o===D&&(a&&(a=t.style=g(t.style)),a=i.createMarkupForStyles(a));var u=s.createMarkupForProperty(o,a);u&&(n+=" "+u)}}if(e.renderToStaticMarkup)return n+">";var c=s.createMarkupForID(this._rootNodeID);return n+" "+c+">"},_createContentMarkup:function(e){var t=this.props.dangerouslySetInnerHTML;if(null!=t){if(null!=t.__html)return t.__html}else{var n=M[typeof this.props.children]?this.props.children:null,r=null!=n?null:this.props.children;if(null!=n)return h(n);if(null!=r){var o=this.mountChildren(r,e);return o.join("")}}return""},receiveComponent:function(e,t){(e!==this._descriptor||null==e._owner)&&c.Mixin.receiveComponent.call(this,e,t)},updateComponent:f.measure("ReactDOMComponent","updateComponent",function(e,t){n(this._descriptor.props),c.Mixin.updateComponent.call(this,e,t),this._updateDOMProperties(t.props,e),this._updateDOMChildren(t.props,e)}),_updateDOMProperties:function(e,t){var n,o,i,s=this.props;for(n in e)if(!s.hasOwnProperty(n)&&e.hasOwnProperty(n))if(n===D){var u=e[n];for(o in u)u.hasOwnProperty(o)&&(i=i||{},i[o]="")}else R.hasOwnProperty(n)?C(this._rootNodeID,n):(a.isStandardName[n]||a.isCustomAttribute(n))&&c.BackendIDOperations.deletePropertyByID(this._rootNodeID,n);for(n in s){var l=s[n],p=e[n];if(s.hasOwnProperty(n)&&l!==p)if(n===D)if(l&&(l=s.style=g(l)),p){for(o in p)!p.hasOwnProperty(o)||l&&l.hasOwnProperty(o)||(i=i||{},i[o]="");for(o in l)l.hasOwnProperty(o)&&p[o]!==l[o]&&(i=i||{},i[o]=l[o])}else i=l;else R.hasOwnProperty(n)?r(this._rootNodeID,n,l,t):(a.isStandardName[n]||a.isCustomAttribute(n))&&c.BackendIDOperations.updatePropertyByID(this._rootNodeID,n,l)}i&&c.BackendIDOperations.updateStylesByID(this._rootNodeID,i)},_updateDOMChildren:function(e,t){var n=this.props,r=M[typeof e.children]?e.children:null,o=M[typeof n.children]?n.children:null,i=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,a=n.dangerouslySetInnerHTML&&n.dangerouslySetInnerHTML.__html,s=null!=r?null:e.children,u=null!=o?null:n.children,l=null!=r||null!=i,p=null!=o||null!=a;null!=s&&null==u?this.updateChildren(null,t):l&&!p&&this.updateTextContent(""),null!=o?r!==o&&this.updateTextContent(""+o):null!=a?i!==a&&c.BackendIDOperations.updateInnerHTMLByID(this._rootNodeID,a):null!=u&&this.updateChildren(u,t)},unmountComponent:function(){this.unmountChildren(),l.deleteAllListeners(this._rootNodeID),c.Mixin.unmountComponent.call(this)}},y(o,c.Mixin),y(o,o.Mixin),y(o,d.Mixin),y(o,u),t.exports=o},{"./CSSPropertyOperations":5,"./DOMProperty":11,"./DOMPropertyOperations":12,"./ReactBrowserComponentMixin":30,"./ReactBrowserEventEmitter":31,"./ReactComponent":35,"./ReactMount":65,"./ReactMultiChild":66,"./ReactPerf":69,"./escapeTextForBrowser":115,"./invariant":131,"./keyOf":138,"./merge":141,"./mixInto":144}],44:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./LocalEventTrapMixin"),o=e("./ReactBrowserComponentMixin"),i=e("./ReactCompositeComponent"),a=e("./ReactDOM"),s=a.form,u=i.createClass({displayName:"ReactDOMForm",mixins:[o,r],render:function(){return this.transferPropsTo(s(null,this.props.children))},componentDidMount:function(){this.trapBubbledEvent(n.topLevelTypes.topReset,"reset"),this.trapBubbledEvent(n.topLevelTypes.topSubmit,"submit")}});t.exports=u},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],45:[function(e,t){"use strict";var n=e("./CSSPropertyOperations"),r=e("./DOMChildrenOperations"),o=e("./DOMPropertyOperations"),i=e("./ReactMount"),a=e("./ReactPerf"),s=e("./invariant"),u=e("./setInnerHTML"),c={dangerouslySetInnerHTML:"`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.",style:"`style` must be set using `updateStylesByID()`."},l={updatePropertyByID:a.measure("ReactDOMIDOperations","updatePropertyByID",function(e,t,n){var r=i.getNode(e);s(!c.hasOwnProperty(t)),null!=n?o.setValueForProperty(r,t,n):o.deleteValueForProperty(r,t)}),deletePropertyByID:a.measure("ReactDOMIDOperations","deletePropertyByID",function(e,t,n){var r=i.getNode(e);s(!c.hasOwnProperty(t)),o.deleteValueForProperty(r,t,n)}),updateStylesByID:a.measure("ReactDOMIDOperations","updateStylesByID",function(e,t){var r=i.getNode(e);n.setValueForStyles(r,t)}),updateInnerHTMLByID:a.measure("ReactDOMIDOperations","updateInnerHTMLByID",function(e,t){var n=i.getNode(e);u(n,t)}),updateTextContentByID:a.measure("ReactDOMIDOperations","updateTextContentByID",function(e,t){var n=i.getNode(e);r.updateTextContent(n,t)}),dangerouslyReplaceNodeWithMarkupByID:a.measure("ReactDOMIDOperations","dangerouslyReplaceNodeWithMarkupByID",function(e,t){var n=i.getNode(e);r.dangerouslyReplaceNodeWithMarkup(n,t)}),dangerouslyProcessChildrenUpdates:a.measure("ReactDOMIDOperations","dangerouslyProcessChildrenUpdates",function(e,t){for(var n=0;n<e.length;n++)e[n].parentNode=i.getNode(e[n].parentID);r.processUpdates(e,t)})};t.exports=l},{"./CSSPropertyOperations":5,"./DOMChildrenOperations":10,"./DOMPropertyOperations":12,"./ReactMount":65,"./ReactPerf":69,"./invariant":131,"./setInnerHTML":147}],46:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./LocalEventTrapMixin"),o=e("./ReactBrowserComponentMixin"),i=e("./ReactCompositeComponent"),a=e("./ReactDOM"),s=a.img,u=i.createClass({displayName:"ReactDOMImg",tagName:"IMG",mixins:[o,r],render:function(){return s(this.props)},componentDidMount:function(){this.trapBubbledEvent(n.topLevelTypes.topLoad,"load"),this.trapBubbledEvent(n.topLevelTypes.topError,"error")}});t.exports=u},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],47:[function(e,t){"use strict";var n=e("./AutoFocusMixin"),r=e("./DOMPropertyOperations"),o=e("./LinkedValueUtils"),i=e("./ReactBrowserComponentMixin"),a=e("./ReactCompositeComponent"),s=e("./ReactDOM"),u=e("./ReactMount"),c=e("./invariant"),l=e("./merge"),p=s.input,d={},f=a.createClass({displayName:"ReactDOMInput",mixins:[n,o.Mixin,i],getInitialState:function(){var e=this.props.defaultValue;return{checked:this.props.defaultChecked||!1,value:null!=e?e:null}},shouldComponentUpdate:function(){return!this._isChanging},render:function(){var e=l(this.props);e.defaultChecked=null,e.defaultValue=null;var t=o.getValue(this);e.value=null!=t?t:this.state.value;var n=o.getChecked(this);return e.checked=null!=n?n:this.state.checked,e.onChange=this._handleChange,p(e,this.props.children)},componentDidMount:function(){var e=u.getID(this.getDOMNode());d[e]=this},componentWillUnmount:function(){var e=this.getDOMNode(),t=u.getID(e);delete d[t]},componentDidUpdate:function(){var e=this.getDOMNode();null!=this.props.checked&&r.setValueForProperty(e,"checked",this.props.checked||!1);var t=o.getValue(this);null!=t&&r.setValueForProperty(e,"value",""+t)},_handleChange:function(e){var t,n=o.getOnChange(this);n&&(this._isChanging=!0,t=n.call(this,e),this._isChanging=!1),this.setState({checked:e.target.checked,value:e.target.value});var r=this.props.name;if("radio"===this.props.type&&null!=r){for(var i=this.getDOMNode(),a=i;a.parentNode;)a=a.parentNode;for(var s=a.querySelectorAll("input[name="+JSON.stringify(""+r)+'][type="radio"]'),l=0,p=s.length;p>l;l++){var f=s[l];if(f!==i&&f.form===i.form){var h=u.getID(f);c(h);var v=d[h];c(v),v.setState({checked:!1})}}}return t}});t.exports=f},{"./AutoFocusMixin":1,"./DOMPropertyOperations":12,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./ReactMount":65,"./invariant":131,"./merge":141}],48:[function(e,t){"use strict";var n=e("./ReactBrowserComponentMixin"),r=e("./ReactCompositeComponent"),o=e("./ReactDOM"),i=(e("./warning"),o.option),a=r.createClass({displayName:"ReactDOMOption",mixins:[n],componentWillMount:function(){},render:function(){return i(this.props,this.props.children)}});t.exports=a},{"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./warning":153}],49:[function(e,t){"use strict";function n(e,t){if(null!=e[t])if(e.multiple){if(!Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be an array if `multiple` is true.")}else if(Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be a scalar value if `multiple` is false.")}function r(e,t){var n,r,o,i=e.props.multiple,a=null!=t?t:e.state.value,s=e.getDOMNode().options;if(i)for(n={},r=0,o=a.length;o>r;++r)n[""+a[r]]=!0;else n=""+a;for(r=0,o=s.length;o>r;r++){var u=i?n.hasOwnProperty(s[r].value):s[r].value===n;u!==s[r].selected&&(s[r].selected=u)}}var o=e("./AutoFocusMixin"),i=e("./LinkedValueUtils"),a=e("./ReactBrowserComponentMixin"),s=e("./ReactCompositeComponent"),u=e("./ReactDOM"),c=e("./merge"),l=u.select,p=s.createClass({displayName:"ReactDOMSelect",mixins:[o,i.Mixin,a],propTypes:{defaultValue:n,value:n},getInitialState:function(){return{value:this.props.defaultValue||(this.props.multiple?[]:"")}
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.React=e()}}(function(){return function e(t,n,r){function o(a,s){if(!n[a]){if(!t[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);throw new Error("Cannot find module '"+a+"'")}var c=n[a]={exports:{}};t[a][0].call(c.exports,function(e){var n=t[a][1][e];return o(n?n:e)},c,c.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(e,t){"use strict";var n=e("./focusNode"),r={componentDidMount:function(){this.props.autoFocus&&n(this.getDOMNode())}};t.exports=r},{"./focusNode":117}],2:[function(e,t){"use strict";function n(){var e=window.opera;return"object"==typeof e&&"function"==typeof e.version&&parseInt(e.version(),10)<=12}function r(e){return(e.ctrlKey||e.altKey||e.metaKey)&&!(e.ctrlKey&&e.altKey)}var o=e("./EventConstants"),i=e("./EventPropagators"),a=e("./ExecutionEnvironment"),s=e("./SyntheticInputEvent"),u=e("./keyOf"),c=a.canUseDOM&&"TextEvent"in window&&!("documentMode"in document||n()),l=32,p=String.fromCharCode(l),d=o.topLevelTypes,f={beforeInput:{phasedRegistrationNames:{bubbled:u({onBeforeInput:null}),captured:u({onBeforeInputCapture:null})},dependencies:[d.topCompositionEnd,d.topKeyPress,d.topTextInput,d.topPaste]}},h=null,v={eventTypes:f,extractEvents:function(e,t,n,o){var a;if(c)switch(e){case d.topKeyPress:var u=o.which;if(u!==l)return;a=String.fromCharCode(u);break;case d.topTextInput:if(a=o.data,a===p)return;break;default:return}else{switch(e){case d.topPaste:h=null;break;case d.topKeyPress:o.which&&!r(o)&&(h=String.fromCharCode(o.which));break;case d.topCompositionEnd:h=o.data}if(null===h)return;a=h}if(a){var v=s.getPooled(f.beforeInput,n,o);return v.data=a,h=null,i.accumulateTwoPhaseDispatches(v),v}}};t.exports=v},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./SyntheticInputEvent":95,"./keyOf":138}],3:[function(e,t){var n=e("./invariant"),r={addClass:function(e,t){return n(!/\s/.test(t)),t&&(e.classList?e.classList.add(t):r.hasClass(e,t)||(e.className=e.className+" "+t)),e},removeClass:function(e,t){return n(!/\s/.test(t)),t&&(e.classList?e.classList.remove(t):r.hasClass(e,t)&&(e.className=e.className.replace(new RegExp("(^|\\s)"+t+"(?:\\s|$)","g"),"$1").replace(/\s+/g," ").replace(/^\s*|\s*$/g,""))),e},conditionClass:function(e,t,n){return(n?r.addClass:r.removeClass)(e,t)},hasClass:function(e,t){return n(!/\s/.test(t)),e.classList?!!t&&e.classList.contains(t):(" "+e.className+" ").indexOf(" "+t+" ")>-1}};t.exports=r},{"./invariant":131}],4:[function(e,t){"use strict";function n(e,t){return e+t.charAt(0).toUpperCase()+t.substring(1)}var r={columnCount:!0,fillOpacity:!0,flex:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},o=["Webkit","ms","Moz","O"];Object.keys(r).forEach(function(e){o.forEach(function(t){r[n(t,e)]=r[e]})});var i={background:{backgroundImage:!0,backgroundPosition:!0,backgroundRepeat:!0,backgroundColor:!0},border:{borderWidth:!0,borderStyle:!0,borderColor:!0},borderBottom:{borderBottomWidth:!0,borderBottomStyle:!0,borderBottomColor:!0},borderLeft:{borderLeftWidth:!0,borderLeftStyle:!0,borderLeftColor:!0},borderRight:{borderRightWidth:!0,borderRightStyle:!0,borderRightColor:!0},borderTop:{borderTopWidth:!0,borderTopStyle:!0,borderTopColor:!0},font:{fontStyle:!0,fontVariant:!0,fontWeight:!0,fontSize:!0,lineHeight:!0,fontFamily:!0}},a={isUnitlessNumber:r,shorthandPropertyExpansions:i};t.exports=a},{}],5:[function(e,t){"use strict";var n=e("./CSSProperty"),r=e("./dangerousStyleValue"),o=e("./hyphenateStyleName"),i=e("./memoizeStringOnly"),a=i(function(e){return o(e)}),s={createMarkupForStyles:function(e){var t="";for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];null!=o&&(t+=a(n)+":",t+=r(n,o)+";")}return t||null},setValueForStyles:function(e,t){var o=e.style;for(var i in t)if(t.hasOwnProperty(i)){var a=r(i,t[i]);if(a)o[i]=a;else{var s=n.shorthandPropertyExpansions[i];if(s)for(var u in s)o[u]="";else o[i]=""}}}};t.exports=s},{"./CSSProperty":4,"./dangerousStyleValue":112,"./hyphenateStyleName":129,"./memoizeStringOnly":140}],6:[function(e,t){"use strict";function n(){this._callbacks=null,this._contexts=null}var r=e("./PooledClass"),o=e("./invariant"),i=e("./mixInto");i(n,{enqueue:function(e,t){this._callbacks=this._callbacks||[],this._contexts=this._contexts||[],this._callbacks.push(e),this._contexts.push(t)},notifyAll:function(){var e=this._callbacks,t=this._contexts;if(e){o(e.length===t.length),this._callbacks=null,this._contexts=null;for(var n=0,r=e.length;r>n;n++)e[n].call(t[n]);e.length=0,t.length=0}},reset:function(){this._callbacks=null,this._contexts=null},destructor:function(){this.reset()}}),r.addPoolingTo(n),t.exports=n},{"./PooledClass":28,"./invariant":131,"./mixInto":144}],7:[function(e,t){"use strict";function n(e){return"SELECT"===e.nodeName||"INPUT"===e.nodeName&&"file"===e.type}function r(e){var t=M.getPooled(P.change,S,e);C.accumulateTwoPhaseDispatches(t),R.batchedUpdates(o,t)}function o(e){y.enqueueEvents(e),y.processEventQueue()}function i(e,t){T=e,S=t,T.attachEvent("onchange",r)}function a(){T&&(T.detachEvent("onchange",r),T=null,S=null)}function s(e,t,n){return e===O.topChange?n:void 0}function u(e,t,n){e===O.topFocus?(a(),i(t,n)):e===O.topBlur&&a()}function c(e,t){T=e,S=t,w=e.value,_=Object.getOwnPropertyDescriptor(e.constructor.prototype,"value"),Object.defineProperty(T,"value",k),T.attachEvent("onpropertychange",p)}function l(){T&&(delete T.value,T.detachEvent("onpropertychange",p),T=null,S=null,w=null,_=null)}function p(e){if("value"===e.propertyName){var t=e.srcElement.value;t!==w&&(w=t,r(e))}}function d(e,t,n){return e===O.topInput?n:void 0}function f(e,t,n){e===O.topFocus?(l(),c(t,n)):e===O.topBlur&&l()}function h(e){return e!==O.topSelectionChange&&e!==O.topKeyUp&&e!==O.topKeyDown||!T||T.value===w?void 0:(w=T.value,S)}function v(e){return"INPUT"===e.nodeName&&("checkbox"===e.type||"radio"===e.type)}function m(e,t,n){return e===O.topClick?n:void 0}var g=e("./EventConstants"),y=e("./EventPluginHub"),C=e("./EventPropagators"),E=e("./ExecutionEnvironment"),R=e("./ReactUpdates"),M=e("./SyntheticEvent"),D=e("./isEventSupported"),x=e("./isTextInputElement"),b=e("./keyOf"),O=g.topLevelTypes,P={change:{phasedRegistrationNames:{bubbled:b({onChange:null}),captured:b({onChangeCapture:null})},dependencies:[O.topBlur,O.topChange,O.topClick,O.topFocus,O.topInput,O.topKeyDown,O.topKeyUp,O.topSelectionChange]}},T=null,S=null,w=null,_=null,I=!1;E.canUseDOM&&(I=D("change")&&(!("documentMode"in document)||document.documentMode>8));var N=!1;E.canUseDOM&&(N=D("input")&&(!("documentMode"in document)||document.documentMode>9));var k={get:function(){return _.get.call(this)},set:function(e){w=""+e,_.set.call(this,e)}},A={eventTypes:P,extractEvents:function(e,t,r,o){var i,a;if(n(t)?I?i=s:a=u:x(t)?N?i=d:(i=h,a=f):v(t)&&(i=m),i){var c=i(e,t,r);if(c){var l=M.getPooled(P.change,c,o);return C.accumulateTwoPhaseDispatches(l),l}}a&&a(e,t,r)}};t.exports=A},{"./EventConstants":16,"./EventPluginHub":18,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactUpdates":84,"./SyntheticEvent":93,"./isEventSupported":132,"./isTextInputElement":134,"./keyOf":138}],8:[function(e,t){"use strict";var n=0,r={createReactRootIndex:function(){return n++}};t.exports=r},{}],9:[function(e,t){"use strict";function n(e){switch(e){case g.topCompositionStart:return C.compositionStart;case g.topCompositionEnd:return C.compositionEnd;case g.topCompositionUpdate:return C.compositionUpdate}}function r(e,t){return e===g.topKeyDown&&t.keyCode===h}function o(e,t){switch(e){case g.topKeyUp:return-1!==f.indexOf(t.keyCode);case g.topKeyDown:return t.keyCode!==h;case g.topKeyPress:case g.topMouseDown:case g.topBlur:return!0;default:return!1}}function i(e){this.root=e,this.startSelection=c.getSelection(e),this.startValue=this.getText()}var a=e("./EventConstants"),s=e("./EventPropagators"),u=e("./ExecutionEnvironment"),c=e("./ReactInputSelection"),l=e("./SyntheticCompositionEvent"),p=e("./getTextContentAccessor"),d=e("./keyOf"),f=[9,13,27,32],h=229,v=u.canUseDOM&&"CompositionEvent"in window,m=!v||"documentMode"in document&&document.documentMode>8&&document.documentMode<=11,g=a.topLevelTypes,y=null,C={compositionEnd:{phasedRegistrationNames:{bubbled:d({onCompositionEnd:null}),captured:d({onCompositionEndCapture:null})},dependencies:[g.topBlur,g.topCompositionEnd,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:d({onCompositionStart:null}),captured:d({onCompositionStartCapture:null})},dependencies:[g.topBlur,g.topCompositionStart,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:d({onCompositionUpdate:null}),captured:d({onCompositionUpdateCapture:null})},dependencies:[g.topBlur,g.topCompositionUpdate,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]}};i.prototype.getText=function(){return this.root.value||this.root[p()]},i.prototype.getData=function(){var e=this.getText(),t=this.startSelection.start,n=this.startValue.length-this.startSelection.end;return e.substr(t,e.length-n-t)};var E={eventTypes:C,extractEvents:function(e,t,a,u){var c,p;if(v?c=n(e):y?o(e,u)&&(c=C.compositionEnd):r(e,u)&&(c=C.compositionStart),m&&(y||c!==C.compositionStart?c===C.compositionEnd&&y&&(p=y.getData(),y=null):y=new i(t)),c){var d=l.getPooled(c,a,u);return p&&(d.data=p),s.accumulateTwoPhaseDispatches(d),d}}};t.exports=E},{"./EventConstants":16,"./EventPropagators":21,"./ExecutionEnvironment":22,"./ReactInputSelection":61,"./SyntheticCompositionEvent":91,"./getTextContentAccessor":126,"./keyOf":138}],10:[function(e,t){"use strict";function n(e,t,n){e.insertBefore(t,e.childNodes[n]||null)}var r,o=e("./Danger"),i=e("./ReactMultiChildUpdateTypes"),a=e("./getTextContentAccessor"),s=e("./invariant"),u=a();r="textContent"===u?function(e,t){e.textContent=t}:function(e,t){for(;e.firstChild;)e.removeChild(e.firstChild);if(t){var n=e.ownerDocument||document;e.appendChild(n.createTextNode(t))}};var c={dangerouslyReplaceNodeWithMarkup:o.dangerouslyReplaceNodeWithMarkup,updateTextContent:r,processUpdates:function(e,t){for(var a,u=null,c=null,l=0;a=e[l];l++)if(a.type===i.MOVE_EXISTING||a.type===i.REMOVE_NODE){var p=a.fromIndex,d=a.parentNode.childNodes[p],f=a.parentID;s(d),u=u||{},u[f]=u[f]||[],u[f][p]=d,c=c||[],c.push(d)}var h=o.dangerouslyRenderMarkup(t);if(c)for(var v=0;v<c.length;v++)c[v].parentNode.removeChild(c[v]);for(var m=0;a=e[m];m++)switch(a.type){case i.INSERT_MARKUP:n(a.parentNode,h[a.markupIndex],a.toIndex);break;case i.MOVE_EXISTING:n(a.parentNode,u[a.parentID][a.fromIndex],a.toIndex);break;case i.TEXT_CONTENT:r(a.parentNode,a.textContent);break;case i.REMOVE_NODE:}}};t.exports=c},{"./Danger":13,"./ReactMultiChildUpdateTypes":67,"./getTextContentAccessor":126,"./invariant":131}],11:[function(e,t){"use strict";var n=e("./invariant"),r={MUST_USE_ATTRIBUTE:1,MUST_USE_PROPERTY:2,HAS_SIDE_EFFECTS:4,HAS_BOOLEAN_VALUE:8,HAS_NUMERIC_VALUE:16,HAS_POSITIVE_NUMERIC_VALUE:48,HAS_OVERLOADED_BOOLEAN_VALUE:64,injectDOMPropertyConfig:function(e){var t=e.Properties||{},o=e.DOMAttributeNames||{},a=e.DOMPropertyNames||{},s=e.DOMMutationMethods||{};e.isCustomAttribute&&i._isCustomAttributeFunctions.push(e.isCustomAttribute);for(var u in t){n(!i.isStandardName.hasOwnProperty(u)),i.isStandardName[u]=!0;var c=u.toLowerCase();if(i.getPossibleStandardName[c]=u,o.hasOwnProperty(u)){var l=o[u];i.getPossibleStandardName[l]=u,i.getAttributeName[u]=l}else i.getAttributeName[u]=c;i.getPropertyName[u]=a.hasOwnProperty(u)?a[u]:u,i.getMutationMethod[u]=s.hasOwnProperty(u)?s[u]:null;var p=t[u];i.mustUseAttribute[u]=p&r.MUST_USE_ATTRIBUTE,i.mustUseProperty[u]=p&r.MUST_USE_PROPERTY,i.hasSideEffects[u]=p&r.HAS_SIDE_EFFECTS,i.hasBooleanValue[u]=p&r.HAS_BOOLEAN_VALUE,i.hasNumericValue[u]=p&r.HAS_NUMERIC_VALUE,i.hasPositiveNumericValue[u]=p&r.HAS_POSITIVE_NUMERIC_VALUE,i.hasOverloadedBooleanValue[u]=p&r.HAS_OVERLOADED_BOOLEAN_VALUE,n(!i.mustUseAttribute[u]||!i.mustUseProperty[u]),n(i.mustUseProperty[u]||!i.hasSideEffects[u]),n(!!i.hasBooleanValue[u]+!!i.hasNumericValue[u]+!!i.hasOverloadedBooleanValue[u]<=1)}}},o={},i={ID_ATTRIBUTE_NAME:"data-reactid",isStandardName:{},getPossibleStandardName:{},getAttributeName:{},getPropertyName:{},getMutationMethod:{},mustUseAttribute:{},mustUseProperty:{},hasSideEffects:{},hasBooleanValue:{},hasNumericValue:{},hasPositiveNumericValue:{},hasOverloadedBooleanValue:{},_isCustomAttributeFunctions:[],isCustomAttribute:function(e){for(var t=0;t<i._isCustomAttributeFunctions.length;t++){var n=i._isCustomAttributeFunctions[t];if(n(e))return!0}return!1},getDefaultValueForProperty:function(e,t){var n,r=o[e];return r||(o[e]=r={}),t in r||(n=document.createElement(e),r[t]=n[t]),r[t]},injection:r};t.exports=i},{"./invariant":131}],12:[function(e,t){"use strict";function n(e,t){return null==t||r.hasBooleanValue[e]&&!t||r.hasNumericValue[e]&&isNaN(t)||r.hasPositiveNumericValue[e]&&1>t||r.hasOverloadedBooleanValue[e]&&t===!1}var r=e("./DOMProperty"),o=e("./escapeTextForBrowser"),i=e("./memoizeStringOnly"),a=(e("./warning"),i(function(e){return o(e)+'="'})),s={createMarkupForID:function(e){return a(r.ID_ATTRIBUTE_NAME)+o(e)+'"'},createMarkupForProperty:function(e,t){if(r.isStandardName.hasOwnProperty(e)&&r.isStandardName[e]){if(n(e,t))return"";var i=r.getAttributeName[e];return r.hasBooleanValue[e]||r.hasOverloadedBooleanValue[e]&&t===!0?o(i):a(i)+o(t)+'"'}return r.isCustomAttribute(e)?null==t?"":a(e)+o(t)+'"':null},setValueForProperty:function(e,t,o){if(r.isStandardName.hasOwnProperty(t)&&r.isStandardName[t]){var i=r.getMutationMethod[t];if(i)i(e,o);else if(n(t,o))this.deleteValueForProperty(e,t);else if(r.mustUseAttribute[t])e.setAttribute(r.getAttributeName[t],""+o);else{var a=r.getPropertyName[t];r.hasSideEffects[t]&&e[a]===o||(e[a]=o)}}else r.isCustomAttribute(t)&&(null==o?e.removeAttribute(t):e.setAttribute(t,""+o))},deleteValueForProperty:function(e,t){if(r.isStandardName.hasOwnProperty(t)&&r.isStandardName[t]){var n=r.getMutationMethod[t];if(n)n(e,void 0);else if(r.mustUseAttribute[t])e.removeAttribute(r.getAttributeName[t]);else{var o=r.getPropertyName[t],i=r.getDefaultValueForProperty(e.nodeName,o);r.hasSideEffects[t]&&e[o]===i||(e[o]=i)}}else r.isCustomAttribute(t)&&e.removeAttribute(t)}};t.exports=s},{"./DOMProperty":11,"./escapeTextForBrowser":115,"./memoizeStringOnly":140,"./warning":153}],13:[function(e,t){"use strict";function n(e){return e.substring(1,e.indexOf(" "))}var r=e("./ExecutionEnvironment"),o=e("./createNodesFromMarkup"),i=e("./emptyFunction"),a=e("./getMarkupWrap"),s=e("./invariant"),u=/^(<[^ \/>]+)/,c="data-danger-index",l={dangerouslyRenderMarkup:function(e){s(r.canUseDOM);for(var t,l={},p=0;p<e.length;p++)s(e[p]),t=n(e[p]),t=a(t)?t:"*",l[t]=l[t]||[],l[t][p]=e[p];var d=[],f=0;for(t in l)if(l.hasOwnProperty(t)){var h=l[t];for(var v in h)if(h.hasOwnProperty(v)){var m=h[v];h[v]=m.replace(u,"$1 "+c+'="'+v+'" ')}var g=o(h.join(""),i);for(p=0;p<g.length;++p){var y=g[p];y.hasAttribute&&y.hasAttribute(c)&&(v=+y.getAttribute(c),y.removeAttribute(c),s(!d.hasOwnProperty(v)),d[v]=y,f+=1)}}return s(f===d.length),s(d.length===e.length),d},dangerouslyReplaceNodeWithMarkup:function(e,t){s(r.canUseDOM),s(t),s("html"!==e.tagName.toLowerCase());var n=o(t,i)[0];e.parentNode.replaceChild(n,e)}};t.exports=l},{"./ExecutionEnvironment":22,"./createNodesFromMarkup":110,"./emptyFunction":113,"./getMarkupWrap":123,"./invariant":131}],14:[function(e,t){"use strict";var n=e("./keyOf"),r=[n({ResponderEventPlugin:null}),n({SimpleEventPlugin:null}),n({TapEventPlugin:null}),n({EnterLeaveEventPlugin:null}),n({ChangeEventPlugin:null}),n({SelectEventPlugin:null}),n({CompositionEventPlugin:null}),n({BeforeInputEventPlugin:null}),n({AnalyticsEventPlugin:null}),n({MobileSafariClickEventPlugin:null})];t.exports=r},{"./keyOf":138}],15:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./EventPropagators"),o=e("./SyntheticMouseEvent"),i=e("./ReactMount"),a=e("./keyOf"),s=n.topLevelTypes,u=i.getFirstReactDOM,c={mouseEnter:{registrationName:a({onMouseEnter:null}),dependencies:[s.topMouseOut,s.topMouseOver]},mouseLeave:{registrationName:a({onMouseLeave:null}),dependencies:[s.topMouseOut,s.topMouseOver]}},l=[null,null],p={eventTypes:c,extractEvents:function(e,t,n,a){if(e===s.topMouseOver&&(a.relatedTarget||a.fromElement))return null;if(e!==s.topMouseOut&&e!==s.topMouseOver)return null;var p;if(t.window===t)p=t;else{var d=t.ownerDocument;p=d?d.defaultView||d.parentWindow:window}var f,h;if(e===s.topMouseOut?(f=t,h=u(a.relatedTarget||a.toElement)||p):(f=p,h=t),f===h)return null;var v=f?i.getID(f):"",m=h?i.getID(h):"",g=o.getPooled(c.mouseLeave,v,a);g.type="mouseleave",g.target=f,g.relatedTarget=h;var y=o.getPooled(c.mouseEnter,m,a);return y.type="mouseenter",y.target=h,y.relatedTarget=f,r.accumulateEnterLeaveDispatches(g,y,v,m),l[0]=g,l[1]=y,l}};t.exports=p},{"./EventConstants":16,"./EventPropagators":21,"./ReactMount":65,"./SyntheticMouseEvent":97,"./keyOf":138}],16:[function(e,t){"use strict";var n=e("./keyMirror"),r=n({bubbled:null,captured:null}),o=n({topBlur:null,topChange:null,topClick:null,topCompositionEnd:null,topCompositionStart:null,topCompositionUpdate:null,topContextMenu:null,topCopy:null,topCut:null,topDoubleClick:null,topDrag:null,topDragEnd:null,topDragEnter:null,topDragExit:null,topDragLeave:null,topDragOver:null,topDragStart:null,topDrop:null,topError:null,topFocus:null,topInput:null,topKeyDown:null,topKeyPress:null,topKeyUp:null,topLoad:null,topMouseDown:null,topMouseMove:null,topMouseOut:null,topMouseOver:null,topMouseUp:null,topPaste:null,topReset:null,topScroll:null,topSelectionChange:null,topSubmit:null,topTextInput:null,topTouchCancel:null,topTouchEnd:null,topTouchMove:null,topTouchStart:null,topWheel:null}),i={topLevelTypes:o,PropagationPhases:r};t.exports=i},{"./keyMirror":137}],17:[function(e,t){var n=e("./emptyFunction"),r={listen:function(e,t,n){return e.addEventListener?(e.addEventListener(t,n,!1),{remove:function(){e.removeEventListener(t,n,!1)}}):e.attachEvent?(e.attachEvent("on"+t,n),{remove:function(){e.detachEvent("on"+t,n)}}):void 0},capture:function(e,t,r){return e.addEventListener?(e.addEventListener(t,r,!0),{remove:function(){e.removeEventListener(t,r,!0)}}):{remove:n}},registerDefault:function(){}};t.exports=r},{"./emptyFunction":113}],18:[function(e,t){"use strict";var n=e("./EventPluginRegistry"),r=e("./EventPluginUtils"),o=e("./accumulate"),i=e("./forEachAccumulated"),a=e("./invariant"),s=(e("./isEventSupported"),e("./monitorCodeUse"),{}),u=null,c=function(e){if(e){var t=r.executeDispatch,o=n.getPluginModuleForEvent(e);o&&o.executeDispatch&&(t=o.executeDispatch),r.executeDispatchesInOrder(e,t),e.isPersistent()||e.constructor.release(e)}},l=null,p={injection:{injectMount:r.injection.injectMount,injectInstanceHandle:function(e){l=e},getInstanceHandle:function(){return l},injectEventPluginOrder:n.injectEventPluginOrder,injectEventPluginsByName:n.injectEventPluginsByName},eventNameDispatchConfigs:n.eventNameDispatchConfigs,registrationNameModules:n.registrationNameModules,putListener:function(e,t,n){a(!n||"function"==typeof n);var r=s[t]||(s[t]={});r[e]=n},getListener:function(e,t){var n=s[t];return n&&n[e]},deleteListener:function(e,t){var n=s[t];n&&delete n[e]},deleteAllListeners:function(e){for(var t in s)delete s[t][e]},extractEvents:function(e,t,r,i){for(var a,s=n.plugins,u=0,c=s.length;c>u;u++){var l=s[u];if(l){var p=l.extractEvents(e,t,r,i);p&&(a=o(a,p))}}return a},enqueueEvents:function(e){e&&(u=o(u,e))},processEventQueue:function(){var e=u;u=null,i(e,c),a(!u)},__purge:function(){s={}},__getListenerBank:function(){return s}};t.exports=p},{"./EventPluginRegistry":19,"./EventPluginUtils":20,"./accumulate":103,"./forEachAccumulated":118,"./invariant":131,"./isEventSupported":132,"./monitorCodeUse":145}],19:[function(e,t){"use strict";function n(){if(a)for(var e in s){var t=s[e],n=a.indexOf(e);if(i(n>-1),!u.plugins[n]){i(t.extractEvents),u.plugins[n]=t;var o=t.eventTypes;for(var c in o)i(r(o[c],t,c))}}}function r(e,t,n){i(!u.eventNameDispatchConfigs.hasOwnProperty(n)),u.eventNameDispatchConfigs[n]=e;var r=e.phasedRegistrationNames;if(r){for(var a in r)if(r.hasOwnProperty(a)){var s=r[a];o(s,t,n)}return!0}return e.registrationName?(o(e.registrationName,t,n),!0):!1}function o(e,t,n){i(!u.registrationNameModules[e]),u.registrationNameModules[e]=t,u.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var i=e("./invariant"),a=null,s={},u={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(e){i(!a),a=Array.prototype.slice.call(e),n()},injectEventPluginsByName:function(e){var t=!1;for(var r in e)if(e.hasOwnProperty(r)){var o=e[r];s.hasOwnProperty(r)&&s[r]===o||(i(!s[r]),s[r]=o,t=!0)}t&&n()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return u.registrationNameModules[t.registrationName]||null;for(var n in t.phasedRegistrationNames)if(t.phasedRegistrationNames.hasOwnProperty(n)){var r=u.registrationNameModules[t.phasedRegistrationNames[n]];if(r)return r}return null},_resetEventPlugins:function(){a=null;for(var e in s)s.hasOwnProperty(e)&&delete s[e];u.plugins.length=0;var t=u.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=u.registrationNameModules;for(var o in r)r.hasOwnProperty(o)&&delete r[o]}};t.exports=u},{"./invariant":131}],20:[function(e,t){"use strict";function n(e){return e===v.topMouseUp||e===v.topTouchEnd||e===v.topTouchCancel}function r(e){return e===v.topMouseMove||e===v.topTouchMove}function o(e){return e===v.topMouseDown||e===v.topTouchStart}function i(e,t){var n=e._dispatchListeners,r=e._dispatchIDs;if(Array.isArray(n))for(var o=0;o<n.length&&!e.isPropagationStopped();o++)t(e,n[o],r[o]);else n&&t(e,n,r)}function a(e,t,n){e.currentTarget=h.Mount.getNode(n);var r=t(e,n);return e.currentTarget=null,r}function s(e,t){i(e,t),e._dispatchListeners=null,e._dispatchIDs=null}function u(e){var t=e._dispatchListeners,n=e._dispatchIDs;if(Array.isArray(t)){for(var r=0;r<t.length&&!e.isPropagationStopped();r++)if(t[r](e,n[r]))return n[r]}else if(t&&t(e,n))return n;return null}function c(e){var t=u(e);return e._dispatchIDs=null,e._dispatchListeners=null,t}function l(e){var t=e._dispatchListeners,n=e._dispatchIDs;f(!Array.isArray(t));var r=t?t(e,n):null;return e._dispatchListeners=null,e._dispatchIDs=null,r}function p(e){return!!e._dispatchListeners}var d=e("./EventConstants"),f=e("./invariant"),h={Mount:null,injectMount:function(e){h.Mount=e}},v=d.topLevelTypes,m={isEndish:n,isMoveish:r,isStartish:o,executeDirectDispatch:l,executeDispatch:a,executeDispatchesInOrder:s,executeDispatchesInOrderStopAtTrue:c,hasDispatches:p,injection:h,useTouchEvents:!1};t.exports=m},{"./EventConstants":16,"./invariant":131}],21:[function(e,t){"use strict";function n(e,t,n){var r=t.dispatchConfig.phasedRegistrationNames[n];return v(e,r)}function r(e,t,r){var o=t?h.bubbled:h.captured,i=n(e,r,o);i&&(r._dispatchListeners=d(r._dispatchListeners,i),r._dispatchIDs=d(r._dispatchIDs,e))}function o(e){e&&e.dispatchConfig.phasedRegistrationNames&&p.injection.getInstanceHandle().traverseTwoPhase(e.dispatchMarker,r,e)}function i(e,t,n){if(n&&n.dispatchConfig.registrationName){var r=n.dispatchConfig.registrationName,o=v(e,r);o&&(n._dispatchListeners=d(n._dispatchListeners,o),n._dispatchIDs=d(n._dispatchIDs,e))}}function a(e){e&&e.dispatchConfig.registrationName&&i(e.dispatchMarker,null,e)}function s(e){f(e,o)}function u(e,t,n,r){p.injection.getInstanceHandle().traverseEnterLeave(n,r,i,e,t)}function c(e){f(e,a)}var l=e("./EventConstants"),p=e("./EventPluginHub"),d=e("./accumulate"),f=e("./forEachAccumulated"),h=l.PropagationPhases,v=p.getListener,m={accumulateTwoPhaseDispatches:s,accumulateDirectDispatches:c,accumulateEnterLeaveDispatches:u};t.exports=m},{"./EventConstants":16,"./EventPluginHub":18,"./accumulate":103,"./forEachAccumulated":118}],22:[function(e,t){"use strict";var n=!("undefined"==typeof window||!window.document||!window.document.createElement),r={canUseDOM:n,canUseWorkers:"undefined"!=typeof Worker,canUseEventListeners:n&&!(!window.addEventListener&&!window.attachEvent),canUseViewport:n&&!!window.screen,isInWorker:!n};t.exports=r},{}],23:[function(e,t){"use strict";var n,r=e("./DOMProperty"),o=e("./ExecutionEnvironment"),i=r.injection.MUST_USE_ATTRIBUTE,a=r.injection.MUST_USE_PROPERTY,s=r.injection.HAS_BOOLEAN_VALUE,u=r.injection.HAS_SIDE_EFFECTS,c=r.injection.HAS_NUMERIC_VALUE,l=r.injection.HAS_POSITIVE_NUMERIC_VALUE,p=r.injection.HAS_OVERLOADED_BOOLEAN_VALUE;if(o.canUseDOM){var d=document.implementation;n=d&&d.hasFeature&&d.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}var f={isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),Properties:{accept:null,accessKey:null,action:null,allowFullScreen:i|s,allowTransparency:i,alt:null,async:s,autoComplete:null,autoPlay:s,cellPadding:null,cellSpacing:null,charSet:i,checked:a|s,className:n?i:a,cols:i|l,colSpan:null,content:null,contentEditable:null,contextMenu:i,controls:a|s,coords:null,crossOrigin:null,data:null,dateTime:i,defer:s,dir:null,disabled:i|s,download:p,draggable:null,encType:null,form:i,formNoValidate:s,frameBorder:i,height:i,hidden:i|s,href:null,hrefLang:null,htmlFor:null,httpEquiv:null,icon:null,id:a,label:null,lang:null,list:null,loop:a|s,max:null,maxLength:i,media:i,mediaGroup:null,method:null,min:null,multiple:a|s,muted:a|s,name:null,noValidate:s,open:null,pattern:null,placeholder:null,poster:null,preload:null,radioGroup:null,readOnly:a|s,rel:null,required:s,role:i,rows:i|l,rowSpan:null,sandbox:null,scope:null,scrollLeft:a,scrolling:null,scrollTop:a,seamless:i|s,selected:a|s,shape:null,size:i|l,sizes:i,span:l,spellCheck:null,src:null,srcDoc:a,srcSet:i,start:c,step:null,style:null,tabIndex:null,target:null,title:null,type:null,useMap:null,value:a|u,width:i,wmode:i,autoCapitalize:null,autoCorrect:null,itemProp:i,itemScope:i|s,itemType:i,property:null},DOMAttributeNames:{className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{autoCapitalize:"autocapitalize",autoComplete:"autocomplete",autoCorrect:"autocorrect",autoFocus:"autofocus",autoPlay:"autoplay",encType:"enctype",hrefLang:"hreflang",radioGroup:"radiogroup",spellCheck:"spellcheck",srcDoc:"srcdoc",srcSet:"srcset"}};t.exports=f},{"./DOMProperty":11,"./ExecutionEnvironment":22}],24:[function(e,t){"use strict";var n=e("./ReactLink"),r=e("./ReactStateSetters"),o={linkState:function(e){return new n(this.state[e],r.createStateKeySetter(this,e))}};t.exports=o},{"./ReactLink":63,"./ReactStateSetters":79}],25:[function(e,t){"use strict";function n(e){u(null==e.props.checkedLink||null==e.props.valueLink)}function r(e){n(e),u(null==e.props.value&&null==e.props.onChange)}function o(e){n(e),u(null==e.props.checked&&null==e.props.onChange)}function i(e){this.props.valueLink.requestChange(e.target.value)}function a(e){this.props.checkedLink.requestChange(e.target.checked)}var s=e("./ReactPropTypes"),u=e("./invariant"),c={button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0},l={Mixin:{propTypes:{value:function(e,t){return!e[t]||c[e.type]||e.onChange||e.readOnly||e.disabled?void 0:new Error("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.")},checked:function(e,t){return!e[t]||e.onChange||e.readOnly||e.disabled?void 0:new Error("You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")},onChange:s.func}},getValue:function(e){return e.props.valueLink?(r(e),e.props.valueLink.value):e.props.value},getChecked:function(e){return e.props.checkedLink?(o(e),e.props.checkedLink.value):e.props.checked},getOnChange:function(e){return e.props.valueLink?(r(e),i):e.props.checkedLink?(o(e),a):e.props.onChange}};t.exports=l},{"./ReactPropTypes":73,"./invariant":131}],26:[function(e,t){"use strict";function n(e){e.remove()}var r=e("./ReactBrowserEventEmitter"),o=e("./accumulate"),i=e("./forEachAccumulated"),a=e("./invariant"),s={trapBubbledEvent:function(e,t){a(this.isMounted());var n=r.trapBubbledEvent(e,t,this.getDOMNode());this._localEventListeners=o(this._localEventListeners,n)},componentWillUnmount:function(){this._localEventListeners&&i(this._localEventListeners,n)}};t.exports=s},{"./ReactBrowserEventEmitter":31,"./accumulate":103,"./forEachAccumulated":118,"./invariant":131}],27:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./emptyFunction"),o=n.topLevelTypes,i={eventTypes:null,extractEvents:function(e,t,n,i){if(e===o.topTouchStart){var a=i.target;a&&!a.onclick&&(a.onclick=r)}}};t.exports=i},{"./EventConstants":16,"./emptyFunction":113}],28:[function(e,t){"use strict";var n=e("./invariant"),r=function(e){var t=this;if(t.instancePool.length){var n=t.instancePool.pop();return t.call(n,e),n}return new t(e)},o=function(e,t){var n=this;if(n.instancePool.length){var r=n.instancePool.pop();return n.call(r,e,t),r}return new n(e,t)},i=function(e,t,n){var r=this;if(r.instancePool.length){var o=r.instancePool.pop();return r.call(o,e,t,n),o}return new r(e,t,n)},a=function(e,t,n,r,o){var i=this;if(i.instancePool.length){var a=i.instancePool.pop();return i.call(a,e,t,n,r,o),a}return new i(e,t,n,r,o)},s=function(e){var t=this;n(e instanceof t),e.destructor&&e.destructor(),t.instancePool.length<t.poolSize&&t.instancePool.push(e)},u=10,c=r,l=function(e,t){var n=e;return n.instancePool=[],n.getPooled=t||c,n.poolSize||(n.poolSize=u),n.release=s,n},p={addPoolingTo:l,oneArgumentPooler:r,twoArgumentPooler:o,threeArgumentPooler:i,fiveArgumentPooler:a};t.exports=p},{"./invariant":131}],29:[function(e,t){"use strict";function n(e){var t=Array.prototype.slice.call(arguments,1);return e.apply(null,t)}{var r=e("./DOMPropertyOperations"),o=e("./EventPluginUtils"),i=e("./ReactChildren"),a=e("./ReactComponent"),s=e("./ReactCompositeComponent"),u=e("./ReactContext"),c=e("./ReactCurrentOwner"),l=e("./ReactDescriptor"),p=e("./ReactDOM"),d=e("./ReactDOMComponent"),f=e("./ReactDefaultInjection"),h=e("./ReactInstanceHandles"),v=e("./ReactMount"),m=e("./ReactMultiChild"),g=e("./ReactPerf"),y=e("./ReactPropTypes"),C=e("./ReactServerRendering"),E=e("./ReactTextComponent"),R=e("./onlyChild");e("./warning")}f.inject();var M={Children:{map:i.map,forEach:i.forEach,count:i.count,only:R},DOM:p,PropTypes:y,initializeTouchEvents:function(e){o.useTouchEvents=e},createClass:s.createClass,createDescriptor:function(){return n.apply(this,arguments)},createElement:n,constructAndRenderComponent:v.constructAndRenderComponent,constructAndRenderComponentByID:v.constructAndRenderComponentByID,renderComponent:g.measure("React","renderComponent",v.renderComponent),renderComponentToString:C.renderComponentToString,renderComponentToStaticMarkup:C.renderComponentToStaticMarkup,unmountComponentAtNode:v.unmountComponentAtNode,isValidClass:l.isValidFactory,isValidComponent:l.isValidDescriptor,withContext:u.withContext,__internals:{Component:a,CurrentOwner:c,DOMComponent:d,DOMPropertyOperations:r,InstanceHandles:h,Mount:v,MultiChild:m,TextComponent:E}};M.version="0.11.2",t.exports=M},{"./DOMPropertyOperations":12,"./EventPluginUtils":20,"./ReactChildren":34,"./ReactComponent":35,"./ReactCompositeComponent":38,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDOM":41,"./ReactDOMComponent":43,"./ReactDefaultInjection":53,"./ReactDescriptor":54,"./ReactInstanceHandles":62,"./ReactMount":65,"./ReactMultiChild":66,"./ReactPerf":69,"./ReactPropTypes":73,"./ReactServerRendering":77,"./ReactTextComponent":80,"./onlyChild":146,"./warning":153}],30:[function(e,t){"use strict";
+var n=e("./ReactEmptyComponent"),r=e("./ReactMount"),o=e("./invariant"),i={getDOMNode:function(){return o(this.isMounted()),n.isNullComponentID(this._rootNodeID)?null:r.getNode(this._rootNodeID)}};t.exports=i},{"./ReactEmptyComponent":56,"./ReactMount":65,"./invariant":131}],31:[function(e,t){"use strict";function n(e){return Object.prototype.hasOwnProperty.call(e,h)||(e[h]=d++,l[e[h]]={}),l[e[h]]}var r=e("./EventConstants"),o=e("./EventPluginHub"),i=e("./EventPluginRegistry"),a=e("./ReactEventEmitterMixin"),s=e("./ViewportMetrics"),u=e("./isEventSupported"),c=e("./merge"),l={},p=!1,d=0,f={topBlur:"blur",topChange:"change",topClick:"click",topCompositionEnd:"compositionend",topCompositionStart:"compositionstart",topCompositionUpdate:"compositionupdate",topContextMenu:"contextmenu",topCopy:"copy",topCut:"cut",topDoubleClick:"dblclick",topDrag:"drag",topDragEnd:"dragend",topDragEnter:"dragenter",topDragExit:"dragexit",topDragLeave:"dragleave",topDragOver:"dragover",topDragStart:"dragstart",topDrop:"drop",topFocus:"focus",topInput:"input",topKeyDown:"keydown",topKeyPress:"keypress",topKeyUp:"keyup",topMouseDown:"mousedown",topMouseMove:"mousemove",topMouseOut:"mouseout",topMouseOver:"mouseover",topMouseUp:"mouseup",topPaste:"paste",topScroll:"scroll",topSelectionChange:"selectionchange",topTextInput:"textInput",topTouchCancel:"touchcancel",topTouchEnd:"touchend",topTouchMove:"touchmove",topTouchStart:"touchstart",topWheel:"wheel"},h="_reactListenersID"+String(Math.random()).slice(2),v=c(a,{ReactEventListener:null,injection:{injectReactEventListener:function(e){e.setHandleTopLevel(v.handleTopLevel),v.ReactEventListener=e}},setEnabled:function(e){v.ReactEventListener&&v.ReactEventListener.setEnabled(e)},isEnabled:function(){return!(!v.ReactEventListener||!v.ReactEventListener.isEnabled())},listenTo:function(e,t){for(var o=t,a=n(o),s=i.registrationNameDependencies[e],c=r.topLevelTypes,l=0,p=s.length;p>l;l++){var d=s[l];a.hasOwnProperty(d)&&a[d]||(d===c.topWheel?u("wheel")?v.ReactEventListener.trapBubbledEvent(c.topWheel,"wheel",o):u("mousewheel")?v.ReactEventListener.trapBubbledEvent(c.topWheel,"mousewheel",o):v.ReactEventListener.trapBubbledEvent(c.topWheel,"DOMMouseScroll",o):d===c.topScroll?u("scroll",!0)?v.ReactEventListener.trapCapturedEvent(c.topScroll,"scroll",o):v.ReactEventListener.trapBubbledEvent(c.topScroll,"scroll",v.ReactEventListener.WINDOW_HANDLE):d===c.topFocus||d===c.topBlur?(u("focus",!0)?(v.ReactEventListener.trapCapturedEvent(c.topFocus,"focus",o),v.ReactEventListener.trapCapturedEvent(c.topBlur,"blur",o)):u("focusin")&&(v.ReactEventListener.trapBubbledEvent(c.topFocus,"focusin",o),v.ReactEventListener.trapBubbledEvent(c.topBlur,"focusout",o)),a[c.topBlur]=!0,a[c.topFocus]=!0):f.hasOwnProperty(d)&&v.ReactEventListener.trapBubbledEvent(d,f[d],o),a[d]=!0)}},trapBubbledEvent:function(e,t,n){return v.ReactEventListener.trapBubbledEvent(e,t,n)},trapCapturedEvent:function(e,t,n){return v.ReactEventListener.trapCapturedEvent(e,t,n)},ensureScrollValueMonitoring:function(){if(!p){var e=s.refreshScrollValues;v.ReactEventListener.monitorScrollValue(e),p=!0}},eventNameDispatchConfigs:o.eventNameDispatchConfigs,registrationNameModules:o.registrationNameModules,putListener:o.putListener,getListener:o.getListener,deleteListener:o.deleteListener,deleteAllListeners:o.deleteAllListeners});t.exports=v},{"./EventConstants":16,"./EventPluginHub":18,"./EventPluginRegistry":19,"./ReactEventEmitterMixin":58,"./ViewportMetrics":102,"./isEventSupported":132,"./merge":141}],32:[function(e,t){"use strict";var n=e("./React"),r=e("./ReactTransitionGroup"),o=e("./ReactCSSTransitionGroupChild"),i=n.createClass({displayName:"ReactCSSTransitionGroup",propTypes:{transitionName:n.PropTypes.string.isRequired,transitionEnter:n.PropTypes.bool,transitionLeave:n.PropTypes.bool},getDefaultProps:function(){return{transitionEnter:!0,transitionLeave:!0}},_wrapChild:function(e){return o({name:this.props.transitionName,enter:this.props.transitionEnter,leave:this.props.transitionLeave},e)},render:function(){return this.transferPropsTo(r({childFactory:this._wrapChild},this.props.children))}});t.exports=i},{"./React":29,"./ReactCSSTransitionGroupChild":33,"./ReactTransitionGroup":83}],33:[function(e,t){"use strict";var n=e("./React"),r=e("./CSSCore"),o=e("./ReactTransitionEvents"),i=e("./onlyChild"),a=17,s=n.createClass({displayName:"ReactCSSTransitionGroupChild",transition:function(e,t){var n=this.getDOMNode(),i=this.props.name+"-"+e,a=i+"-active",s=function(){r.removeClass(n,i),r.removeClass(n,a),o.removeEndEventListener(n,s),t&&t()};o.addEndEventListener(n,s),r.addClass(n,i),this.queueClass(a)},queueClass:function(e){this.classNameQueue.push(e),this.timeout||(this.timeout=setTimeout(this.flushClassNameQueue,a))},flushClassNameQueue:function(){this.isMounted()&&this.classNameQueue.forEach(r.addClass.bind(r,this.getDOMNode())),this.classNameQueue.length=0,this.timeout=null},componentWillMount:function(){this.classNameQueue=[]},componentWillUnmount:function(){this.timeout&&clearTimeout(this.timeout)},componentWillEnter:function(e){this.props.enter?this.transition("enter",e):e()},componentWillLeave:function(e){this.props.leave?this.transition("leave",e):e()},render:function(){return i(this.props.children)}});t.exports=s},{"./CSSCore":3,"./React":29,"./ReactTransitionEvents":82,"./onlyChild":146}],34:[function(e,t){"use strict";function n(e,t){this.forEachFunction=e,this.forEachContext=t}function r(e,t,n,r){var o=e;o.forEachFunction.call(o.forEachContext,t,r)}function o(e,t,o){if(null==e)return e;var i=n.getPooled(t,o);p(e,r,i),n.release(i)}function i(e,t,n){this.mapResult=e,this.mapFunction=t,this.mapContext=n}function a(e,t,n,r){var o=e,i=o.mapResult,a=!i.hasOwnProperty(n);if(a){var s=o.mapFunction.call(o.mapContext,t,r);i[n]=s}}function s(e,t,n){if(null==e)return e;var r={},o=i.getPooled(r,t,n);return p(e,a,o),i.release(o),r}function u(){return null}function c(e){return p(e,u,null)}var l=e("./PooledClass"),p=e("./traverseAllChildren"),d=(e("./warning"),l.twoArgumentPooler),f=l.threeArgumentPooler;l.addPoolingTo(n,d),l.addPoolingTo(i,f);var h={forEach:o,map:s,count:c};t.exports=h},{"./PooledClass":28,"./traverseAllChildren":151,"./warning":153}],35:[function(e,t){"use strict";var n=e("./ReactDescriptor"),r=e("./ReactOwner"),o=e("./ReactUpdates"),i=e("./invariant"),a=e("./keyMirror"),s=e("./merge"),u=a({MOUNTED:null,UNMOUNTED:null}),c=!1,l=null,p=null,d={injection:{injectEnvironment:function(e){i(!c),p=e.mountImageIntoNode,l=e.unmountIDFromEnvironment,d.BackendIDOperations=e.BackendIDOperations,c=!0}},LifeCycle:u,BackendIDOperations:null,Mixin:{isMounted:function(){return this._lifeCycleState===u.MOUNTED},setProps:function(e,t){var n=this._pendingDescriptor||this._descriptor;this.replaceProps(s(n.props,e),t)},replaceProps:function(e,t){i(this.isMounted()),i(0===this._mountDepth),this._pendingDescriptor=n.cloneAndReplaceProps(this._pendingDescriptor||this._descriptor,e),o.enqueueUpdate(this,t)},_setPropsInternal:function(e,t){var r=this._pendingDescriptor||this._descriptor;this._pendingDescriptor=n.cloneAndReplaceProps(r,s(r.props,e)),o.enqueueUpdate(this,t)},construct:function(e){this.props=e.props,this._owner=e._owner,this._lifeCycleState=u.UNMOUNTED,this._pendingCallbacks=null,this._descriptor=e,this._pendingDescriptor=null},mountComponent:function(e,t,n){i(!this.isMounted());var o=this._descriptor.props;if(null!=o.ref){var a=this._descriptor._owner;r.addComponentAsRefTo(this,o.ref,a)}this._rootNodeID=e,this._lifeCycleState=u.MOUNTED,this._mountDepth=n},unmountComponent:function(){i(this.isMounted());var e=this.props;null!=e.ref&&r.removeComponentAsRefFrom(this,e.ref,this._owner),l(this._rootNodeID),this._rootNodeID=null,this._lifeCycleState=u.UNMOUNTED},receiveComponent:function(e,t){i(this.isMounted()),this._pendingDescriptor=e,this.performUpdateIfNecessary(t)},performUpdateIfNecessary:function(e){if(null!=this._pendingDescriptor){var t=this._descriptor,n=this._pendingDescriptor;this._descriptor=n,this.props=n.props,this._owner=n._owner,this._pendingDescriptor=null,this.updateComponent(e,t)}},updateComponent:function(e,t){var n=this._descriptor;(n._owner!==t._owner||n.props.ref!==t.props.ref)&&(null!=t.props.ref&&r.removeComponentAsRefFrom(this,t.props.ref,t._owner),null!=n.props.ref&&r.addComponentAsRefTo(this,n.props.ref,n._owner))},mountComponentIntoNode:function(e,t,n){var r=o.ReactReconcileTransaction.getPooled();r.perform(this._mountComponentIntoNode,this,e,t,r,n),o.ReactReconcileTransaction.release(r)},_mountComponentIntoNode:function(e,t,n,r){var o=this.mountComponent(e,n,0);p(o,t,r)},isOwnedBy:function(e){return this._owner===e},getSiblingByRef:function(e){var t=this._owner;return t&&t.refs?t.refs[e]:null}}};t.exports=d},{"./ReactDescriptor":54,"./ReactOwner":68,"./ReactUpdates":84,"./invariant":131,"./keyMirror":137,"./merge":141}],36:[function(e,t){"use strict";var n=e("./ReactDOMIDOperations"),r=e("./ReactMarkupChecksum"),o=e("./ReactMount"),i=e("./ReactPerf"),a=e("./ReactReconcileTransaction"),s=e("./getReactRootElementInContainer"),u=e("./invariant"),c=e("./setInnerHTML"),l=1,p=9,d={ReactReconcileTransaction:a,BackendIDOperations:n,unmountIDFromEnvironment:function(e){o.purgeID(e)},mountImageIntoNode:i.measure("ReactComponentBrowserEnvironment","mountImageIntoNode",function(e,t,n){if(u(t&&(t.nodeType===l||t.nodeType===p)),n){if(r.canReuseMarkup(e,s(t)))return;u(t.nodeType!==p)}u(t.nodeType!==p),c(t,e)})};t.exports=d},{"./ReactDOMIDOperations":45,"./ReactMarkupChecksum":64,"./ReactMount":65,"./ReactPerf":69,"./ReactReconcileTransaction":75,"./getReactRootElementInContainer":125,"./invariant":131,"./setInnerHTML":147}],37:[function(e,t){"use strict";var n=e("./shallowEqual"),r={shouldComponentUpdate:function(e,t){return!n(this.props,e)||!n(this.state,t)}};t.exports=r},{"./shallowEqual":148}],38:[function(e,t){"use strict";function n(e){var t=e._owner||null;return t&&t.constructor&&t.constructor.displayName?" Check the render method of `"+t.constructor.displayName+"`.":""}function r(e,t){for(var n in t)t.hasOwnProperty(n)&&D("function"==typeof t[n])}function o(e,t){var n=_.hasOwnProperty(t)?_[t]:null;k.hasOwnProperty(t)&&D(n===S.OVERRIDE_BASE),e.hasOwnProperty(t)&&D(n===S.DEFINE_MANY||n===S.DEFINE_MANY_MERGED)}function i(e){var t=e._compositeLifeCycleState;D(e.isMounted()||t===N.MOUNTING),D(t!==N.RECEIVING_STATE),D(t!==N.UNMOUNTING)}function a(e,t){D(!h.isValidFactory(t)),D(!h.isValidDescriptor(t));var n=e.prototype;for(var r in t){var i=t[r];if(t.hasOwnProperty(r))if(o(n,r),I.hasOwnProperty(r))I[r](e,i);else{var a=_.hasOwnProperty(r),s=n.hasOwnProperty(r),u=i&&i.__reactDontBind,p="function"==typeof i,d=p&&!a&&!s&&!u;if(d)n.__reactAutoBindMap||(n.__reactAutoBindMap={}),n.__reactAutoBindMap[r]=i,n[r]=i;else if(s){var f=_[r];D(a&&(f===S.DEFINE_MANY_MERGED||f===S.DEFINE_MANY)),f===S.DEFINE_MANY_MERGED?n[r]=c(n[r],i):f===S.DEFINE_MANY&&(n[r]=l(n[r],i))}else n[r]=i}}}function s(e,t){if(t)for(var n in t){var r=t[n];if(t.hasOwnProperty(n)){var o=n in e,i=r;if(o){var a=e[n],s=typeof a,u=typeof r;D("function"===s&&"function"===u),i=l(a,r)}e[n]=i}}}function u(e,t){return D(e&&t&&"object"==typeof e&&"object"==typeof t),P(t,function(t,n){D(void 0===e[n]),e[n]=t}),e}function c(e,t){return function(){var n=e.apply(this,arguments),r=t.apply(this,arguments);return null==n?r:null==r?n:u(n,r)}}function l(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}var p=e("./ReactComponent"),d=e("./ReactContext"),f=e("./ReactCurrentOwner"),h=e("./ReactDescriptor"),v=(e("./ReactDescriptorValidator"),e("./ReactEmptyComponent")),m=e("./ReactErrorUtils"),g=e("./ReactOwner"),y=e("./ReactPerf"),C=e("./ReactPropTransferer"),E=e("./ReactPropTypeLocations"),R=(e("./ReactPropTypeLocationNames"),e("./ReactUpdates")),M=e("./instantiateReactComponent"),D=e("./invariant"),x=e("./keyMirror"),b=e("./merge"),O=e("./mixInto"),P=(e("./monitorCodeUse"),e("./mapObject")),T=e("./shouldUpdateReactComponent"),S=(e("./warning"),x({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null})),w=[],_={mixins:S.DEFINE_MANY,statics:S.DEFINE_MANY,propTypes:S.DEFINE_MANY,contextTypes:S.DEFINE_MANY,childContextTypes:S.DEFINE_MANY,getDefaultProps:S.DEFINE_MANY_MERGED,getInitialState:S.DEFINE_MANY_MERGED,getChildContext:S.DEFINE_MANY_MERGED,render:S.DEFINE_ONCE,componentWillMount:S.DEFINE_MANY,componentDidMount:S.DEFINE_MANY,componentWillReceiveProps:S.DEFINE_MANY,shouldComponentUpdate:S.DEFINE_ONCE,componentWillUpdate:S.DEFINE_MANY,componentDidUpdate:S.DEFINE_MANY,componentWillUnmount:S.DEFINE_MANY,updateComponent:S.OVERRIDE_BASE},I={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n<t.length;n++)a(e,t[n])},childContextTypes:function(e,t){r(e,t,E.childContext),e.childContextTypes=b(e.childContextTypes,t)},contextTypes:function(e,t){r(e,t,E.context),e.contextTypes=b(e.contextTypes,t)},getDefaultProps:function(e,t){e.getDefaultProps=e.getDefaultProps?c(e.getDefaultProps,t):t},propTypes:function(e,t){r(e,t,E.prop),e.propTypes=b(e.propTypes,t)},statics:function(e,t){s(e,t)}},N=x({MOUNTING:null,UNMOUNTING:null,RECEIVING_PROPS:null,RECEIVING_STATE:null}),k={construct:function(){p.Mixin.construct.apply(this,arguments),g.Mixin.construct.apply(this,arguments),this.state=null,this._pendingState=null,this.context=null,this._compositeLifeCycleState=null},isMounted:function(){return p.Mixin.isMounted.call(this)&&this._compositeLifeCycleState!==N.MOUNTING},mountComponent:y.measure("ReactCompositeComponent","mountComponent",function(e,t,n){p.Mixin.mountComponent.call(this,e,t,n),this._compositeLifeCycleState=N.MOUNTING,this.__reactAutoBindMap&&this._bindAutoBindMethods(),this.context=this._processContext(this._descriptor._context),this.props=this._processProps(this.props),this.state=this.getInitialState?this.getInitialState():null,D("object"==typeof this.state&&!Array.isArray(this.state)),this._pendingState=null,this._pendingForceUpdate=!1,this.componentWillMount&&(this.componentWillMount(),this._pendingState&&(this.state=this._pendingState,this._pendingState=null)),this._renderedComponent=M(this._renderValidatedComponent()),this._compositeLifeCycleState=null;var r=this._renderedComponent.mountComponent(e,t,n+1);return this.componentDidMount&&t.getReactMountReady().enqueue(this.componentDidMount,this),r}),unmountComponent:function(){this._compositeLifeCycleState=N.UNMOUNTING,this.componentWillUnmount&&this.componentWillUnmount(),this._compositeLifeCycleState=null,this._renderedComponent.unmountComponent(),this._renderedComponent=null,p.Mixin.unmountComponent.call(this)},setState:function(e,t){D("object"==typeof e||null==e),this.replaceState(b(this._pendingState||this.state,e),t)},replaceState:function(e,t){i(this),this._pendingState=e,this._compositeLifeCycleState!==N.MOUNTING&&R.enqueueUpdate(this,t)},_processContext:function(e){var t=null,n=this.constructor.contextTypes;if(n){t={};for(var r in n)t[r]=e[r]}return t},_processChildContext:function(e){var t=this.getChildContext&&this.getChildContext();if(this.constructor.displayName||"ReactCompositeComponent",t){D("object"==typeof this.constructor.childContextTypes);for(var n in t)D(n in this.constructor.childContextTypes);return b(e,t)}return e},_processProps:function(e){var t,n=this.constructor.defaultProps;if(n){t=b(e);for(var r in n)"undefined"==typeof t[r]&&(t[r]=n[r])}else t=e;return t},_checkPropTypes:function(e,t,r){var o=this.constructor.displayName;for(var i in e)if(e.hasOwnProperty(i)){var a=e[i](t,i,o,r);a instanceof Error&&n(this)}},performUpdateIfNecessary:function(e){var t=this._compositeLifeCycleState;if(t!==N.MOUNTING&&t!==N.RECEIVING_PROPS&&(null!=this._pendingDescriptor||null!=this._pendingState||this._pendingForceUpdate)){var n=this.context,r=this.props,o=this._descriptor;null!=this._pendingDescriptor&&(o=this._pendingDescriptor,n=this._processContext(o._context),r=this._processProps(o.props),this._pendingDescriptor=null,this._compositeLifeCycleState=N.RECEIVING_PROPS,this.componentWillReceiveProps&&this.componentWillReceiveProps(r,n)),this._compositeLifeCycleState=N.RECEIVING_STATE;var i=this._pendingState||this.state;this._pendingState=null;try{var a=this._pendingForceUpdate||!this.shouldComponentUpdate||this.shouldComponentUpdate(r,i,n);a?(this._pendingForceUpdate=!1,this._performComponentUpdate(o,r,i,n,e)):(this._descriptor=o,this.props=r,this.state=i,this.context=n,this._owner=o._owner)}finally{this._compositeLifeCycleState=null}}},_performComponentUpdate:function(e,t,n,r,o){var i=this._descriptor,a=this.props,s=this.state,u=this.context;this.componentWillUpdate&&this.componentWillUpdate(t,n,r),this._descriptor=e,this.props=t,this.state=n,this.context=r,this._owner=e._owner,this.updateComponent(o,i),this.componentDidUpdate&&o.getReactMountReady().enqueue(this.componentDidUpdate.bind(this,a,s,u),this)},receiveComponent:function(e,t){(e!==this._descriptor||null==e._owner)&&p.Mixin.receiveComponent.call(this,e,t)},updateComponent:y.measure("ReactCompositeComponent","updateComponent",function(e,t){p.Mixin.updateComponent.call(this,e,t);var n=this._renderedComponent,r=n._descriptor,o=this._renderValidatedComponent();if(T(r,o))n.receiveComponent(o,e);else{var i=this._rootNodeID,a=n._rootNodeID;n.unmountComponent(),this._renderedComponent=M(o);var s=this._renderedComponent.mountComponent(i,e,this._mountDepth+1);p.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(a,s)}}),forceUpdate:function(e){var t=this._compositeLifeCycleState;D(this.isMounted()||t===N.MOUNTING),D(t!==N.RECEIVING_STATE&&t!==N.UNMOUNTING),this._pendingForceUpdate=!0,R.enqueueUpdate(this,e)},_renderValidatedComponent:y.measure("ReactCompositeComponent","_renderValidatedComponent",function(){var e,t=d.current;d.current=this._processChildContext(this._descriptor._context),f.current=this;try{e=this.render(),null===e||e===!1?(e=v.getEmptyComponent(),v.registerNullComponentID(this._rootNodeID)):v.deregisterNullComponentID(this._rootNodeID)}finally{d.current=t,f.current=null}return D(h.isValidDescriptor(e)),e}),_bindAutoBindMethods:function(){for(var e in this.__reactAutoBindMap)if(this.__reactAutoBindMap.hasOwnProperty(e)){var t=this.__reactAutoBindMap[e];this[e]=this._bindAutoBindMethod(m.guard(t,this.constructor.displayName+"."+e))}},_bindAutoBindMethod:function(e){var t=this,n=function(){return e.apply(t,arguments)};return n}},A=function(){};O(A,p.Mixin),O(A,g.Mixin),O(A,C.Mixin),O(A,k);var L={LifeCycle:N,Base:A,createClass:function(e){var t=function(e,t){this.construct(e,t)};t.prototype=new A,t.prototype.constructor=t,w.forEach(a.bind(null,t)),a(t,e),t.getDefaultProps&&(t.defaultProps=t.getDefaultProps()),D(t.prototype.render);for(var n in _)t.prototype[n]||(t.prototype[n]=null);var r=h.createFactory(t);return r},injection:{injectMixin:function(e){w.push(e)}}};t.exports=L},{"./ReactComponent":35,"./ReactContext":39,"./ReactCurrentOwner":40,"./ReactDescriptor":54,"./ReactDescriptorValidator":55,"./ReactEmptyComponent":56,"./ReactErrorUtils":57,"./ReactOwner":68,"./ReactPerf":69,"./ReactPropTransferer":70,"./ReactPropTypeLocationNames":71,"./ReactPropTypeLocations":72,"./ReactUpdates":84,"./instantiateReactComponent":130,"./invariant":131,"./keyMirror":137,"./mapObject":139,"./merge":141,"./mixInto":144,"./monitorCodeUse":145,"./shouldUpdateReactComponent":149,"./warning":153}],39:[function(e,t){"use strict";var n=e("./merge"),r={current:{},withContext:function(e,t){var o,i=r.current;r.current=n(i,e);try{o=t()}finally{r.current=i}return o}};t.exports=r},{"./merge":141}],40:[function(e,t){"use strict";var n={current:null};t.exports=n},{}],41:[function(e,t){"use strict";function n(e,t){var n=function(e){this.construct(e)};n.prototype=new o(t,e),n.prototype.constructor=n,n.displayName=t;var i=r.createFactory(n);return i}var r=e("./ReactDescriptor"),o=(e("./ReactDescriptorValidator"),e("./ReactDOMComponent")),i=e("./mergeInto"),a=e("./mapObject"),s=a({a:!1,abbr:!1,address:!1,area:!0,article:!1,aside:!1,audio:!1,b:!1,base:!0,bdi:!1,bdo:!1,big:!1,blockquote:!1,body:!1,br:!0,button:!1,canvas:!1,caption:!1,cite:!1,code:!1,col:!0,colgroup:!1,data:!1,datalist:!1,dd:!1,del:!1,details:!1,dfn:!1,dialog:!1,div:!1,dl:!1,dt:!1,em:!1,embed:!0,fieldset:!1,figcaption:!1,figure:!1,footer:!1,form:!1,h1:!1,h2:!1,h3:!1,h4:!1,h5:!1,h6:!1,head:!1,header:!1,hr:!0,html:!1,i:!1,iframe:!1,img:!0,input:!0,ins:!1,kbd:!1,keygen:!0,label:!1,legend:!1,li:!1,link:!0,main:!1,map:!1,mark:!1,menu:!1,menuitem:!1,meta:!0,meter:!1,nav:!1,noscript:!1,object:!1,ol:!1,optgroup:!1,option:!1,output:!1,p:!1,param:!0,picture:!1,pre:!1,progress:!1,q:!1,rp:!1,rt:!1,ruby:!1,s:!1,samp:!1,script:!1,section:!1,select:!1,small:!1,source:!0,span:!1,strong:!1,style:!1,sub:!1,summary:!1,sup:!1,table:!1,tbody:!1,td:!1,textarea:!1,tfoot:!1,th:!1,thead:!1,time:!1,title:!1,tr:!1,track:!0,u:!1,ul:!1,"var":!1,video:!1,wbr:!0,circle:!1,defs:!1,ellipse:!1,g:!1,line:!1,linearGradient:!1,mask:!1,path:!1,pattern:!1,polygon:!1,polyline:!1,radialGradient:!1,rect:!1,stop:!1,svg:!1,text:!1,tspan:!1},n),u={injectComponentClasses:function(e){i(s,e)}};s.injection=u,t.exports=s},{"./ReactDOMComponent":43,"./ReactDescriptor":54,"./ReactDescriptorValidator":55,"./mapObject":139,"./mergeInto":143}],42:[function(e,t){"use strict";var n=e("./AutoFocusMixin"),r=e("./ReactBrowserComponentMixin"),o=e("./ReactCompositeComponent"),i=e("./ReactDOM"),a=e("./keyMirror"),s=i.button,u=a({onClick:!0,onDoubleClick:!0,onMouseDown:!0,onMouseMove:!0,onMouseUp:!0,onClickCapture:!0,onDoubleClickCapture:!0,onMouseDownCapture:!0,onMouseMoveCapture:!0,onMouseUpCapture:!0}),c=o.createClass({displayName:"ReactDOMButton",mixins:[n,r],render:function(){var e={};for(var t in this.props)!this.props.hasOwnProperty(t)||this.props.disabled&&u[t]||(e[t]=this.props[t]);return s(e,this.props.children)}});t.exports=c},{"./AutoFocusMixin":1,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./keyMirror":137}],43:[function(e,t){"use strict";function n(e){e&&(v(null==e.children||null==e.dangerouslySetInnerHTML),v(null==e.style||"object"==typeof e.style))}function r(e,t,n,r){var o=p.findReactContainerForID(e);if(o){var i=o.nodeType===x?o.ownerDocument:o;E(t,i)}r.getPutListenerQueue().enqueuePutListener(e,t,n)}function o(e,t){this._tagOpen="<"+e,this._tagClose=t?"":"</"+e+">",this.tagName=e.toUpperCase()}var i=e("./CSSPropertyOperations"),a=e("./DOMProperty"),s=e("./DOMPropertyOperations"),u=e("./ReactBrowserComponentMixin"),c=e("./ReactComponent"),l=e("./ReactBrowserEventEmitter"),p=e("./ReactMount"),d=e("./ReactMultiChild"),f=e("./ReactPerf"),h=e("./escapeTextForBrowser"),v=e("./invariant"),m=e("./keyOf"),g=e("./merge"),y=e("./mixInto"),C=l.deleteListener,E=l.listenTo,R=l.registrationNameModules,M={string:!0,number:!0},D=m({style:null}),x=1;o.Mixin={mountComponent:f.measure("ReactDOMComponent","mountComponent",function(e,t,r){return c.Mixin.mountComponent.call(this,e,t,r),n(this.props),this._createOpenTagMarkupAndPutListeners(t)+this._createContentMarkup(t)+this._tagClose}),_createOpenTagMarkupAndPutListeners:function(e){var t=this.props,n=this._tagOpen;for(var o in t)if(t.hasOwnProperty(o)){var a=t[o];if(null!=a)if(R.hasOwnProperty(o))r(this._rootNodeID,o,a,e);else{o===D&&(a&&(a=t.style=g(t.style)),a=i.createMarkupForStyles(a));var u=s.createMarkupForProperty(o,a);u&&(n+=" "+u)}}if(e.renderToStaticMarkup)return n+">";var c=s.createMarkupForID(this._rootNodeID);return n+" "+c+">"},_createContentMarkup:function(e){var t=this.props.dangerouslySetInnerHTML;if(null!=t){if(null!=t.__html)return t.__html}else{var n=M[typeof this.props.children]?this.props.children:null,r=null!=n?null:this.props.children;if(null!=n)return h(n);if(null!=r){var o=this.mountChildren(r,e);return o.join("")}}return""},receiveComponent:function(e,t){(e!==this._descriptor||null==e._owner)&&c.Mixin.receiveComponent.call(this,e,t)},updateComponent:f.measure("ReactDOMComponent","updateComponent",function(e,t){n(this._descriptor.props),c.Mixin.updateComponent.call(this,e,t),this._updateDOMProperties(t.props,e),this._updateDOMChildren(t.props,e)}),_updateDOMProperties:function(e,t){var n,o,i,s=this.props;for(n in e)if(!s.hasOwnProperty(n)&&e.hasOwnProperty(n))if(n===D){var u=e[n];for(o in u)u.hasOwnProperty(o)&&(i=i||{},i[o]="")}else R.hasOwnProperty(n)?C(this._rootNodeID,n):(a.isStandardName[n]||a.isCustomAttribute(n))&&c.BackendIDOperations.deletePropertyByID(this._rootNodeID,n);for(n in s){var l=s[n],p=e[n];if(s.hasOwnProperty(n)&&l!==p)if(n===D)if(l&&(l=s.style=g(l)),p){for(o in p)!p.hasOwnProperty(o)||l&&l.hasOwnProperty(o)||(i=i||{},i[o]="");for(o in l)l.hasOwnProperty(o)&&p[o]!==l[o]&&(i=i||{},i[o]=l[o])}else i=l;else R.hasOwnProperty(n)?r(this._rootNodeID,n,l,t):(a.isStandardName[n]||a.isCustomAttribute(n))&&c.BackendIDOperations.updatePropertyByID(this._rootNodeID,n,l)}i&&c.BackendIDOperations.updateStylesByID(this._rootNodeID,i)},_updateDOMChildren:function(e,t){var n=this.props,r=M[typeof e.children]?e.children:null,o=M[typeof n.children]?n.children:null,i=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,a=n.dangerouslySetInnerHTML&&n.dangerouslySetInnerHTML.__html,s=null!=r?null:e.children,u=null!=o?null:n.children,l=null!=r||null!=i,p=null!=o||null!=a;null!=s&&null==u?this.updateChildren(null,t):l&&!p&&this.updateTextContent(""),null!=o?r!==o&&this.updateTextContent(""+o):null!=a?i!==a&&c.BackendIDOperations.updateInnerHTMLByID(this._rootNodeID,a):null!=u&&this.updateChildren(u,t)},unmountComponent:function(){this.unmountChildren(),l.deleteAllListeners(this._rootNodeID),c.Mixin.unmountComponent.call(this)}},y(o,c.Mixin),y(o,o.Mixin),y(o,d.Mixin),y(o,u),t.exports=o},{"./CSSPropertyOperations":5,"./DOMProperty":11,"./DOMPropertyOperations":12,"./ReactBrowserComponentMixin":30,"./ReactBrowserEventEmitter":31,"./ReactComponent":35,"./ReactMount":65,"./ReactMultiChild":66,"./ReactPerf":69,"./escapeTextForBrowser":115,"./invariant":131,"./keyOf":138,"./merge":141,"./mixInto":144}],44:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./LocalEventTrapMixin"),o=e("./ReactBrowserComponentMixin"),i=e("./ReactCompositeComponent"),a=e("./ReactDOM"),s=a.form,u=i.createClass({displayName:"ReactDOMForm",mixins:[o,r],render:function(){return this.transferPropsTo(s(null,this.props.children))},componentDidMount:function(){this.trapBubbledEvent(n.topLevelTypes.topReset,"reset"),this.trapBubbledEvent(n.topLevelTypes.topSubmit,"submit")}});t.exports=u},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],45:[function(e,t){"use strict";var n=e("./CSSPropertyOperations"),r=e("./DOMChildrenOperations"),o=e("./DOMPropertyOperations"),i=e("./ReactMount"),a=e("./ReactPerf"),s=e("./invariant"),u=e("./setInnerHTML"),c={dangerouslySetInnerHTML:"`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.",style:"`style` must be set using `updateStylesByID()`."},l={updatePropertyByID:a.measure("ReactDOMIDOperations","updatePropertyByID",function(e,t,n){var r=i.getNode(e);s(!c.hasOwnProperty(t)),null!=n?o.setValueForProperty(r,t,n):o.deleteValueForProperty(r,t)}),deletePropertyByID:a.measure("ReactDOMIDOperations","deletePropertyByID",function(e,t,n){var r=i.getNode(e);s(!c.hasOwnProperty(t)),o.deleteValueForProperty(r,t,n)}),updateStylesByID:a.measure("ReactDOMIDOperations","updateStylesByID",function(e,t){var r=i.getNode(e);n.setValueForStyles(r,t)}),updateInnerHTMLByID:a.measure("ReactDOMIDOperations","updateInnerHTMLByID",function(e,t){var n=i.getNode(e);u(n,t)}),updateTextContentByID:a.measure("ReactDOMIDOperations","updateTextContentByID",function(e,t){var n=i.getNode(e);r.updateTextContent(n,t)}),dangerouslyReplaceNodeWithMarkupByID:a.measure("ReactDOMIDOperations","dangerouslyReplaceNodeWithMarkupByID",function(e,t){var n=i.getNode(e);r.dangerouslyReplaceNodeWithMarkup(n,t)}),dangerouslyProcessChildrenUpdates:a.measure("ReactDOMIDOperations","dangerouslyProcessChildrenUpdates",function(e,t){for(var n=0;n<e.length;n++)e[n].parentNode=i.getNode(e[n].parentID);r.processUpdates(e,t)})};t.exports=l},{"./CSSPropertyOperations":5,"./DOMChildrenOperations":10,"./DOMPropertyOperations":12,"./ReactMount":65,"./ReactPerf":69,"./invariant":131,"./setInnerHTML":147}],46:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./LocalEventTrapMixin"),o=e("./ReactBrowserComponentMixin"),i=e("./ReactCompositeComponent"),a=e("./ReactDOM"),s=a.img,u=i.createClass({displayName:"ReactDOMImg",tagName:"IMG",mixins:[o,r],render:function(){return s(this.props)},componentDidMount:function(){this.trapBubbledEvent(n.topLevelTypes.topLoad,"load"),this.trapBubbledEvent(n.topLevelTypes.topError,"error")}});t.exports=u},{"./EventConstants":16,"./LocalEventTrapMixin":26,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41}],47:[function(e,t){"use strict";var n=e("./AutoFocusMixin"),r=e("./DOMPropertyOperations"),o=e("./LinkedValueUtils"),i=e("./ReactBrowserComponentMixin"),a=e("./ReactCompositeComponent"),s=e("./ReactDOM"),u=e("./ReactMount"),c=e("./invariant"),l=e("./merge"),p=s.input,d={},f=a.createClass({displayName:"ReactDOMInput",mixins:[n,o.Mixin,i],getInitialState:function(){var e=this.props.defaultValue;return{checked:this.props.defaultChecked||!1,value:null!=e?e:null}},shouldComponentUpdate:function(){return!this._isChanging},render:function(){var e=l(this.props);e.defaultChecked=null,e.defaultValue=null;var t=o.getValue(this);e.value=null!=t?t:this.state.value;var n=o.getChecked(this);return e.checked=null!=n?n:this.state.checked,e.onChange=this._handleChange,p(e,this.props.children)},componentDidMount:function(){var e=u.getID(this.getDOMNode());d[e]=this},componentWillUnmount:function(){var e=this.getDOMNode(),t=u.getID(e);delete d[t]},componentDidUpdate:function(){var e=this.getDOMNode();null!=this.props.checked&&r.setValueForProperty(e,"checked",this.props.checked||!1);var t=o.getValue(this);null!=t&&r.setValueForProperty(e,"value",""+t)},_handleChange:function(e){var t,n=o.getOnChange(this);n&&(this._isChanging=!0,t=n.call(this,e),this._isChanging=!1),this.setState({checked:e.target.checked,value:e.target.value});var r=this.props.name;if("radio"===this.props.type&&null!=r){for(var i=this.getDOMNode(),a=i;a.parentNode;)a=a.parentNode;for(var s=a.querySelectorAll("input[name="+JSON.stringify(""+r)+'][type="radio"]'),l=0,p=s.length;p>l;l++){var f=s[l];if(f!==i&&f.form===i.form){var h=u.getID(f);c(h);var v=d[h];c(v),v.setState({checked:!1})}}}return t}});t.exports=f},{"./AutoFocusMixin":1,"./DOMPropertyOperations":12,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./ReactMount":65,"./invariant":131,"./merge":141}],48:[function(e,t){"use strict";var n=e("./ReactBrowserComponentMixin"),r=e("./ReactCompositeComponent"),o=e("./ReactDOM"),i=(e("./warning"),o.option),a=r.createClass({displayName:"ReactDOMOption",mixins:[n],componentWillMount:function(){},render:function(){return i(this.props,this.props.children)}});t.exports=a},{"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./warning":153}],49:[function(e,t){"use strict";function n(e,t){if(null!=e[t])if(e.multiple){if(!Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be an array if `multiple` is true.")}else if(Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to <select> must be a scalar value if `multiple` is false.")}function r(e,t){var n,r,o,i=e.props.multiple,a=null!=t?t:e.state.value,s=e.getDOMNode().options;if(i)for(n={},r=0,o=a.length;o>r;++r)n[""+a[r]]=!0;else n=""+a;for(r=0,o=s.length;o>r;r++){var u=i?n.hasOwnProperty(s[r].value):s[r].value===n;u!==s[r].selected&&(s[r].selected=u)}}var o=e("./AutoFocusMixin"),i=e("./LinkedValueUtils"),a=e("./ReactBrowserComponentMixin"),s=e("./ReactCompositeComponent"),u=e("./ReactDOM"),c=e("./merge"),l=u.select,p=s.createClass({displayName:"ReactDOMSelect",mixins:[o,i.Mixin,a],propTypes:{defaultValue:n,value:n},getInitialState:function(){return{value:this.props.defaultValue||(this.props.multiple?[]:"")}
 },componentWillReceiveProps:function(e){!this.props.multiple&&e.multiple?this.setState({value:[this.state.value]}):this.props.multiple&&!e.multiple&&this.setState({value:this.state.value[0]})},shouldComponentUpdate:function(){return!this._isChanging},render:function(){var e=c(this.props);return e.onChange=this._handleChange,e.value=null,l(e,this.props.children)},componentDidMount:function(){r(this,i.getValue(this))},componentDidUpdate:function(e){var t=i.getValue(this),n=!!e.multiple,o=!!this.props.multiple;(null!=t||n!==o)&&r(this,t)},_handleChange:function(e){var t,n=i.getOnChange(this);n&&(this._isChanging=!0,t=n.call(this,e),this._isChanging=!1);var r;if(this.props.multiple){r=[];for(var o=e.target.options,a=0,s=o.length;s>a;a++)o[a].selected&&r.push(o[a].value)}else r=e.target.value;return this.setState({value:r}),t}});t.exports=p},{"./AutoFocusMixin":1,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./merge":141}],50:[function(e,t){"use strict";function n(e,t,n,r){return e===n&&t===r}function r(e){var t=document.selection,n=t.createRange(),r=n.text.length,o=n.duplicate();o.moveToElementText(e),o.setEndPoint("EndToStart",n);var i=o.text.length,a=i+r;return{start:i,end:a}}function o(e){var t=window.getSelection();if(0===t.rangeCount)return null;var r=t.anchorNode,o=t.anchorOffset,i=t.focusNode,a=t.focusOffset,s=t.getRangeAt(0),u=n(t.anchorNode,t.anchorOffset,t.focusNode,t.focusOffset),c=u?0:s.toString().length,l=s.cloneRange();l.selectNodeContents(e),l.setEnd(s.startContainer,s.startOffset);var p=n(l.startContainer,l.startOffset,l.endContainer,l.endOffset),d=p?0:l.toString().length,f=d+c,h=document.createRange();h.setStart(r,o),h.setEnd(i,a);var v=h.collapsed;return h.detach(),{start:v?f:d,end:v?d:f}}function i(e,t){var n,r,o=document.selection.createRange().duplicate();"undefined"==typeof t.end?(n=t.start,r=n):t.start>t.end?(n=t.end,r=t.start):(n=t.start,r=t.end),o.moveToElementText(e),o.moveStart("character",n),o.setEndPoint("EndToStart",o),o.moveEnd("character",r-n),o.select()}function a(e,t){var n=window.getSelection(),r=e[c()].length,o=Math.min(t.start,r),i="undefined"==typeof t.end?o:Math.min(t.end,r);if(!n.extend&&o>i){var a=i;i=o,o=a}var s=u(e,o),l=u(e,i);if(s&&l){var p=document.createRange();p.setStart(s.node,s.offset),n.removeAllRanges(),o>i?(n.addRange(p),n.extend(l.node,l.offset)):(p.setEnd(l.node,l.offset),n.addRange(p)),p.detach()}}var s=e("./ExecutionEnvironment"),u=e("./getNodeForCharacterOffset"),c=e("./getTextContentAccessor"),l=s.canUseDOM&&document.selection,p={getOffsets:l?r:o,setOffsets:l?i:a};t.exports=p},{"./ExecutionEnvironment":22,"./getNodeForCharacterOffset":124,"./getTextContentAccessor":126}],51:[function(e,t){"use strict";var n=e("./AutoFocusMixin"),r=e("./DOMPropertyOperations"),o=e("./LinkedValueUtils"),i=e("./ReactBrowserComponentMixin"),a=e("./ReactCompositeComponent"),s=e("./ReactDOM"),u=e("./invariant"),c=e("./merge"),l=(e("./warning"),s.textarea),p=a.createClass({displayName:"ReactDOMTextarea",mixins:[n,o.Mixin,i],getInitialState:function(){var e=this.props.defaultValue,t=this.props.children;null!=t&&(u(null==e),Array.isArray(t)&&(u(t.length<=1),t=t[0]),e=""+t),null==e&&(e="");var n=o.getValue(this);return{initialValue:""+(null!=n?n:e)}},shouldComponentUpdate:function(){return!this._isChanging},render:function(){var e=c(this.props);return u(null==e.dangerouslySetInnerHTML),e.defaultValue=null,e.value=null,e.onChange=this._handleChange,l(e,this.state.initialValue)},componentDidUpdate:function(){var e=o.getValue(this);if(null!=e){var t=this.getDOMNode();r.setValueForProperty(t,"value",""+e)}},_handleChange:function(e){var t,n=o.getOnChange(this);return n&&(this._isChanging=!0,t=n.call(this,e),this._isChanging=!1),this.setState({value:e.target.value}),t}});t.exports=p},{"./AutoFocusMixin":1,"./DOMPropertyOperations":12,"./LinkedValueUtils":25,"./ReactBrowserComponentMixin":30,"./ReactCompositeComponent":38,"./ReactDOM":41,"./invariant":131,"./merge":141,"./warning":153}],52:[function(e,t){"use strict";function n(){this.reinitializeTransaction()}var r=e("./ReactUpdates"),o=e("./Transaction"),i=e("./emptyFunction"),a=e("./mixInto"),s={initialize:i,close:function(){p.isBatchingUpdates=!1}},u={initialize:i,close:r.flushBatchedUpdates.bind(r)},c=[u,s];a(n,o.Mixin),a(n,{getTransactionWrappers:function(){return c}});var l=new n,p={isBatchingUpdates:!1,batchedUpdates:function(e,t,n){var r=p.isBatchingUpdates;p.isBatchingUpdates=!0,r?e(t,n):l.perform(e,null,t,n)}};t.exports=p},{"./ReactUpdates":84,"./Transaction":101,"./emptyFunction":113,"./mixInto":144}],53:[function(e,t){"use strict";function n(){x.EventEmitter.injectReactEventListener(D),x.EventPluginHub.injectEventPluginOrder(s),x.EventPluginHub.injectInstanceHandle(b),x.EventPluginHub.injectMount(O),x.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:S,EnterLeaveEventPlugin:u,ChangeEventPlugin:o,CompositionEventPlugin:a,MobileSafariClickEventPlugin:p,SelectEventPlugin:P,BeforeInputEventPlugin:r}),x.DOM.injectComponentClasses({button:m,form:g,img:y,input:C,option:E,select:R,textarea:M,html:_(v.html),head:_(v.head),body:_(v.body)}),x.CompositeComponent.injectMixin(d),x.DOMProperty.injectDOMPropertyConfig(l),x.DOMProperty.injectDOMPropertyConfig(w),x.EmptyComponent.injectEmptyComponent(v.noscript),x.Updates.injectReconcileTransaction(f.ReactReconcileTransaction),x.Updates.injectBatchingStrategy(h),x.RootIndex.injectCreateReactRootIndex(c.canUseDOM?i.createReactRootIndex:T.createReactRootIndex),x.Component.injectEnvironment(f)}var r=e("./BeforeInputEventPlugin"),o=e("./ChangeEventPlugin"),i=e("./ClientReactRootIndex"),a=e("./CompositionEventPlugin"),s=e("./DefaultEventPluginOrder"),u=e("./EnterLeaveEventPlugin"),c=e("./ExecutionEnvironment"),l=e("./HTMLDOMPropertyConfig"),p=e("./MobileSafariClickEventPlugin"),d=e("./ReactBrowserComponentMixin"),f=e("./ReactComponentBrowserEnvironment"),h=e("./ReactDefaultBatchingStrategy"),v=e("./ReactDOM"),m=e("./ReactDOMButton"),g=e("./ReactDOMForm"),y=e("./ReactDOMImg"),C=e("./ReactDOMInput"),E=e("./ReactDOMOption"),R=e("./ReactDOMSelect"),M=e("./ReactDOMTextarea"),D=e("./ReactEventListener"),x=e("./ReactInjection"),b=e("./ReactInstanceHandles"),O=e("./ReactMount"),P=e("./SelectEventPlugin"),T=e("./ServerReactRootIndex"),S=e("./SimpleEventPlugin"),w=e("./SVGDOMPropertyConfig"),_=e("./createFullPageComponent");t.exports={inject:n}},{"./BeforeInputEventPlugin":2,"./ChangeEventPlugin":7,"./ClientReactRootIndex":8,"./CompositionEventPlugin":9,"./DefaultEventPluginOrder":14,"./EnterLeaveEventPlugin":15,"./ExecutionEnvironment":22,"./HTMLDOMPropertyConfig":23,"./MobileSafariClickEventPlugin":27,"./ReactBrowserComponentMixin":30,"./ReactComponentBrowserEnvironment":36,"./ReactDOM":41,"./ReactDOMButton":42,"./ReactDOMForm":44,"./ReactDOMImg":46,"./ReactDOMInput":47,"./ReactDOMOption":48,"./ReactDOMSelect":49,"./ReactDOMTextarea":51,"./ReactDefaultBatchingStrategy":52,"./ReactEventListener":59,"./ReactInjection":60,"./ReactInstanceHandles":62,"./ReactMount":65,"./SVGDOMPropertyConfig":86,"./SelectEventPlugin":87,"./ServerReactRootIndex":88,"./SimpleEventPlugin":89,"./createFullPageComponent":109}],54:[function(e,t){"use strict";function n(e,t){if("function"==typeof t)for(var n in t)if(t.hasOwnProperty(n)){var r=t[n];if("function"==typeof r){var o=r.bind(t);for(var i in r)r.hasOwnProperty(i)&&(o[i]=r[i]);e[n]=o}else e[n]=r}}var r=e("./ReactContext"),o=e("./ReactCurrentOwner"),i=e("./merge"),a=(e("./warning"),function(){});a.createFactory=function(e){var t=Object.create(a.prototype),s=function(e,n){null==e?e={}:"object"==typeof e&&(e=i(e));var a=arguments.length-1;if(1===a)e.children=n;else if(a>1){for(var s=Array(a),u=0;a>u;u++)s[u]=arguments[u+1];e.children=s}var c=Object.create(t);return c._owner=o.current,c._context=r.current,c.props=e,c};return s.prototype=t,s.type=e,t.type=e,n(s,e),t.constructor=s,s},a.cloneAndReplaceProps=function(e,t){var n=Object.create(e.constructor.prototype);return n._owner=e._owner,n._context=e._context,n.props=t,n},a.isValidFactory=function(e){return"function"==typeof e&&e.prototype instanceof a},a.isValidDescriptor=function(e){return e instanceof a},t.exports=a},{"./ReactContext":39,"./ReactCurrentOwner":40,"./merge":141,"./warning":153}],55:[function(e,t){"use strict";function n(){var e=p.current;return e&&e.constructor.displayName||void 0}function r(e,t){e._store.validated||null!=e.props.key||(e._store.validated=!0,i("react_key_warning",'Each child in an array should have a unique "key" prop.',e,t))}function o(e,t,n){m.test(e)&&i("react_numeric_key_warning","Child objects should have non-numeric keys so ordering is preserved.",t,n)}function i(e,t,r,o){var i=n(),a=o.displayName,s=i||a,u=f[e];if(!u.hasOwnProperty(s)){u[s]=!0,t+=i?" Check the render method of "+i+".":" Check the renderComponent call using <"+a+">.";var c=null;r._owner&&r._owner!==p.current&&(c=r._owner.constructor.displayName,t+=" It was passed a child from "+c+"."),t+=" See http://fb.me/react-warning-keys for more information.",d(e,{component:s,componentOwner:c}),console.warn(t)}}function a(){var e=n()||"";h.hasOwnProperty(e)||(h[e]=!0,d("react_object_map_children"))}function s(e,t){if(Array.isArray(e))for(var n=0;n<e.length;n++){var i=e[n];c.isValidDescriptor(i)&&r(i,t)}else if(c.isValidDescriptor(e))e._store.validated=!0;else if(e&&"object"==typeof e){a();for(var s in e)o(s,e[s],t)}}function u(e,t,n,r){for(var o in t)if(t.hasOwnProperty(o)){var i;try{i=t[o](n,o,e,r)}catch(a){i=a}i instanceof Error&&!(i.message in v)&&(v[i.message]=!0,d("react_failed_descriptor_type_check",{message:i.message}))}}var c=e("./ReactDescriptor"),l=e("./ReactPropTypeLocations"),p=e("./ReactCurrentOwner"),d=e("./monitorCodeUse"),f={react_key_warning:{},react_numeric_key_warning:{}},h={},v={},m=/^\d+$/,g={createFactory:function(e,t,n){var r=function(){for(var r=e.apply(this,arguments),o=1;o<arguments.length;o++)s(arguments[o],r.type);var i=r.type.displayName;return t&&u(i,t,r.props,l.prop),n&&u(i,n,r._context,l.context),r};r.prototype=e.prototype,r.type=e.type;for(var o in e)e.hasOwnProperty(o)&&(r[o]=e[o]);return r}};t.exports=g},{"./ReactCurrentOwner":40,"./ReactDescriptor":54,"./ReactPropTypeLocations":72,"./monitorCodeUse":145}],56:[function(e,t){"use strict";function n(){return s(a),a()}function r(e){u[e]=!0}function o(e){delete u[e]}function i(e){return u[e]}var a,s=e("./invariant"),u={},c={injectEmptyComponent:function(e){a=e}},l={deregisterNullComponentID:o,getEmptyComponent:n,injection:c,isNullComponentID:i,registerNullComponentID:r};t.exports=l},{"./invariant":131}],57:[function(e,t){"use strict";var n={guard:function(e){return e}};t.exports=n},{}],58:[function(e,t){"use strict";function n(e){r.enqueueEvents(e),r.processEventQueue()}var r=e("./EventPluginHub"),o={handleTopLevel:function(e,t,o,i){var a=r.extractEvents(e,t,o,i);n(a)}};t.exports=o},{"./EventPluginHub":18}],59:[function(e,t){"use strict";function n(e){var t=l.getID(e),n=c.getReactRootIDFromNodeID(t),r=l.findReactContainerForID(n),o=l.getFirstReactDOM(r);return o}function r(e,t){this.topLevelType=e,this.nativeEvent=t,this.ancestors=[]}function o(e){for(var t=l.getFirstReactDOM(d(e.nativeEvent))||window,r=t;r;)e.ancestors.push(r),r=n(r);for(var o=0,i=e.ancestors.length;i>o;o++){t=e.ancestors[o];var a=l.getID(t)||"";v._handleTopLevel(e.topLevelType,t,a,e.nativeEvent)}}function i(e){var t=f(window);e(t)}var a=e("./EventListener"),s=e("./ExecutionEnvironment"),u=e("./PooledClass"),c=e("./ReactInstanceHandles"),l=e("./ReactMount"),p=e("./ReactUpdates"),d=e("./getEventTarget"),f=e("./getUnboundedScrollPosition"),h=e("./mixInto");h(r,{destructor:function(){this.topLevelType=null,this.nativeEvent=null,this.ancestors.length=0}}),u.addPoolingTo(r,u.twoArgumentPooler);var v={_enabled:!0,_handleTopLevel:null,WINDOW_HANDLE:s.canUseDOM?window:null,setHandleTopLevel:function(e){v._handleTopLevel=e},setEnabled:function(e){v._enabled=!!e},isEnabled:function(){return v._enabled},trapBubbledEvent:function(e,t,n){var r=n;return r?a.listen(r,t,v.dispatchEvent.bind(null,e)):void 0},trapCapturedEvent:function(e,t,n){var r=n;return r?a.capture(r,t,v.dispatchEvent.bind(null,e)):void 0},monitorScrollValue:function(e){var t=i.bind(null,e);a.listen(window,"scroll",t),a.listen(window,"resize",t)},dispatchEvent:function(e,t){if(v._enabled){var n=r.getPooled(e,t);try{p.batchedUpdates(o,n)}finally{r.release(n)}}}};t.exports=v},{"./EventListener":17,"./ExecutionEnvironment":22,"./PooledClass":28,"./ReactInstanceHandles":62,"./ReactMount":65,"./ReactUpdates":84,"./getEventTarget":122,"./getUnboundedScrollPosition":127,"./mixInto":144}],60:[function(e,t){"use strict";var n=e("./DOMProperty"),r=e("./EventPluginHub"),o=e("./ReactComponent"),i=e("./ReactCompositeComponent"),a=e("./ReactDOM"),s=e("./ReactEmptyComponent"),u=e("./ReactBrowserEventEmitter"),c=e("./ReactPerf"),l=e("./ReactRootIndex"),p=e("./ReactUpdates"),d={Component:o.injection,CompositeComponent:i.injection,DOMProperty:n.injection,EmptyComponent:s.injection,EventPluginHub:r.injection,DOM:a.injection,EventEmitter:u.injection,Perf:c.injection,RootIndex:l.injection,Updates:p.injection};t.exports=d},{"./DOMProperty":11,"./EventPluginHub":18,"./ReactBrowserEventEmitter":31,"./ReactComponent":35,"./ReactCompositeComponent":38,"./ReactDOM":41,"./ReactEmptyComponent":56,"./ReactPerf":69,"./ReactRootIndex":76,"./ReactUpdates":84}],61:[function(e,t){"use strict";function n(e){return o(document.documentElement,e)}var r=e("./ReactDOMSelection"),o=e("./containsNode"),i=e("./focusNode"),a=e("./getActiveElement"),s={hasSelectionCapabilities:function(e){return e&&("INPUT"===e.nodeName&&"text"===e.type||"TEXTAREA"===e.nodeName||"true"===e.contentEditable)},getSelectionInformation:function(){var e=a();return{focusedElem:e,selectionRange:s.hasSelectionCapabilities(e)?s.getSelection(e):null}},restoreSelection:function(e){var t=a(),r=e.focusedElem,o=e.selectionRange;t!==r&&n(r)&&(s.hasSelectionCapabilities(r)&&s.setSelection(r,o),i(r))},getSelection:function(e){var t;if("selectionStart"in e)t={start:e.selectionStart,end:e.selectionEnd};else if(document.selection&&"INPUT"===e.nodeName){var n=document.selection.createRange();n.parentElement()===e&&(t={start:-n.moveStart("character",-e.value.length),end:-n.moveEnd("character",-e.value.length)})}else t=r.getOffsets(e);return t||{start:0,end:0}},setSelection:function(e,t){var n=t.start,o=t.end;if("undefined"==typeof o&&(o=n),"selectionStart"in e)e.selectionStart=n,e.selectionEnd=Math.min(o,e.value.length);else if(document.selection&&"INPUT"===e.nodeName){var i=e.createTextRange();i.collapse(!0),i.moveStart("character",n),i.moveEnd("character",o-n),i.select()}else r.setOffsets(e,t)}};t.exports=s},{"./ReactDOMSelection":50,"./containsNode":106,"./focusNode":117,"./getActiveElement":119}],62:[function(e,t){"use strict";function n(e){return d+e.toString(36)}function r(e,t){return e.charAt(t)===d||t===e.length}function o(e){return""===e||e.charAt(0)===d&&e.charAt(e.length-1)!==d}function i(e,t){return 0===t.indexOf(e)&&r(t,e.length)}function a(e){return e?e.substr(0,e.lastIndexOf(d)):""}function s(e,t){if(p(o(e)&&o(t)),p(i(e,t)),e===t)return e;for(var n=e.length+f,a=n;a<t.length&&!r(t,a);a++);return t.substr(0,a)}function u(e,t){var n=Math.min(e.length,t.length);if(0===n)return"";for(var i=0,a=0;n>=a;a++)if(r(e,a)&&r(t,a))i=a;else if(e.charAt(a)!==t.charAt(a))break;var s=e.substr(0,i);return p(o(s)),s}function c(e,t,n,r,o,u){e=e||"",t=t||"",p(e!==t);var c=i(t,e);p(c||i(e,t));for(var l=0,d=c?a:s,f=e;;f=d(f,t)){var v;if(o&&f===e||u&&f===t||(v=n(f,c,r)),v===!1||f===t)break;p(l++<h)}}var l=e("./ReactRootIndex"),p=e("./invariant"),d=".",f=d.length,h=100,v={createReactRootID:function(){return n(l.createReactRootIndex())},createReactID:function(e,t){return e+t},getReactRootIDFromNodeID:function(e){if(e&&e.charAt(0)===d&&e.length>1){var t=e.indexOf(d,1);return t>-1?e.substr(0,t):e}return null},traverseEnterLeave:function(e,t,n,r,o){var i=u(e,t);i!==e&&c(e,i,n,r,!1,!0),i!==t&&c(i,t,n,o,!0,!1)},traverseTwoPhase:function(e,t,n){e&&(c("",e,t,n,!0,!1),c(e,"",t,n,!1,!0))},traverseAncestors:function(e,t,n){c("",e,t,n,!0,!1)},_getFirstCommonAncestorID:u,_getNextDescendantID:s,isAncestorIDOf:i,SEPARATOR:d};t.exports=v},{"./ReactRootIndex":76,"./invariant":131}],63:[function(e,t){"use strict";function n(e,t){this.value=e,this.requestChange=t}function r(e){var t={value:"undefined"==typeof e?o.PropTypes.any.isRequired:e.isRequired,requestChange:o.PropTypes.func.isRequired};return o.PropTypes.shape(t)}var o=e("./React");n.PropTypes={link:r},t.exports=n},{"./React":29}],64:[function(e,t){"use strict";var n=e("./adler32"),r={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(e){var t=n(e);return e.replace(">"," "+r.CHECKSUM_ATTR_NAME+'="'+t+'">')},canReuseMarkup:function(e,t){var o=t.getAttribute(r.CHECKSUM_ATTR_NAME);o=o&&parseInt(o,10);var i=n(e);return i===o}};t.exports=r},{"./adler32":104}],65:[function(e,t){"use strict";function n(e){var t=g(e);return t&&w.getID(t)}function r(e){var t=o(e);if(t)if(D.hasOwnProperty(t)){var n=D[t];n!==e&&(C(!s(n,t)),D[t]=e)}else D[t]=e;return t}function o(e){return e&&e.getAttribute&&e.getAttribute(M)||""}function i(e,t){var n=o(e);n!==t&&delete D[n],e.setAttribute(M,t),D[t]=e}function a(e){return D.hasOwnProperty(e)&&s(D[e],e)||(D[e]=w.findReactNodeByID(e)),D[e]}function s(e,t){if(e){C(o(e)===t);var n=w.findReactContainerForID(t);if(n&&m(n,e))return!0}return!1}function u(e){delete D[e]}function c(e){var t=D[e];return t&&s(t,e)?void(S=t):!1}function l(e){S=null,h.traverseAncestors(e,c);var t=S;return S=null,t}var p=e("./DOMProperty"),d=e("./ReactBrowserEventEmitter"),f=(e("./ReactCurrentOwner"),e("./ReactDescriptor")),h=e("./ReactInstanceHandles"),v=e("./ReactPerf"),m=e("./containsNode"),g=e("./getReactRootElementInContainer"),y=e("./instantiateReactComponent"),C=e("./invariant"),E=e("./shouldUpdateReactComponent"),R=(e("./warning"),h.SEPARATOR),M=p.ID_ATTRIBUTE_NAME,D={},x=1,b=9,O={},P={},T=[],S=null,w={_instancesByReactRootID:O,scrollMonitor:function(e,t){t()},_updateRootComponent:function(e,t,n,r){var o=t.props;return w.scrollMonitor(n,function(){e.replaceProps(o,r)}),e},_registerComponent:function(e,t){C(t&&(t.nodeType===x||t.nodeType===b)),d.ensureScrollValueMonitoring();var n=w.registerContainer(t);return O[n]=e,n},_renderNewRootComponent:v.measure("ReactMount","_renderNewRootComponent",function(e,t,n){var r=y(e),o=w._registerComponent(r,t);return r.mountComponentIntoNode(o,t,n),r}),renderComponent:function(e,t,r){C(f.isValidDescriptor(e));var o=O[n(t)];if(o){var i=o._descriptor;if(E(i,e))return w._updateRootComponent(o,e,t,r);w.unmountComponentAtNode(t)}var a=g(t),s=a&&w.isRenderedByReact(a),u=s&&!o,c=w._renderNewRootComponent(e,t,u);return r&&r.call(c),c},constructAndRenderComponent:function(e,t,n){return w.renderComponent(e(t),n)},constructAndRenderComponentByID:function(e,t,n){var r=document.getElementById(n);return C(r),w.constructAndRenderComponent(e,t,r)},registerContainer:function(e){var t=n(e);return t&&(t=h.getReactRootIDFromNodeID(t)),t||(t=h.createReactRootID()),P[t]=e,t},unmountComponentAtNode:function(e){var t=n(e),r=O[t];return r?(w.unmountComponentFromNode(r,e),delete O[t],delete P[t],!0):!1},unmountComponentFromNode:function(e,t){for(e.unmountComponent(),t.nodeType===b&&(t=t.documentElement);t.lastChild;)t.removeChild(t.lastChild)},findReactContainerForID:function(e){var t=h.getReactRootIDFromNodeID(e),n=P[t];return n},findReactNodeByID:function(e){var t=w.findReactContainerForID(e);return w.findComponentRoot(t,e)},isRenderedByReact:function(e){if(1!==e.nodeType)return!1;var t=w.getID(e);return t?t.charAt(0)===R:!1},getFirstReactDOM:function(e){for(var t=e;t&&t.parentNode!==t;){if(w.isRenderedByReact(t))return t;t=t.parentNode}return null},findComponentRoot:function(e,t){var n=T,r=0,o=l(t)||e;for(n[0]=o.firstChild,n.length=1;r<n.length;){for(var i,a=n[r++];a;){var s=w.getID(a);s?t===s?i=a:h.isAncestorIDOf(s,t)&&(n.length=r=0,n.push(a.firstChild)):n.push(a.firstChild),a=a.nextSibling}if(i)return n.length=0,i}n.length=0,C(!1)},getReactRootID:n,getID:r,setID:i,getNode:a,purgeID:u};t.exports=w},{"./DOMProperty":11,"./ReactBrowserEventEmitter":31,"./ReactCurrentOwner":40,"./ReactDescriptor":54,"./ReactInstanceHandles":62,"./ReactPerf":69,"./containsNode":106,"./getReactRootElementInContainer":125,"./instantiateReactComponent":130,"./invariant":131,"./shouldUpdateReactComponent":149,"./warning":153}],66:[function(e,t){"use strict";function n(e,t,n){h.push({parentID:e,parentNode:null,type:c.INSERT_MARKUP,markupIndex:v.push(t)-1,textContent:null,fromIndex:null,toIndex:n})}function r(e,t,n){h.push({parentID:e,parentNode:null,type:c.MOVE_EXISTING,markupIndex:null,textContent:null,fromIndex:t,toIndex:n})}function o(e,t){h.push({parentID:e,parentNode:null,type:c.REMOVE_NODE,markupIndex:null,textContent:null,fromIndex:t,toIndex:null})}function i(e,t){h.push({parentID:e,parentNode:null,type:c.TEXT_CONTENT,markupIndex:null,textContent:t,fromIndex:null,toIndex:null})}function a(){h.length&&(u.BackendIDOperations.dangerouslyProcessChildrenUpdates(h,v),s())}function s(){h.length=0,v.length=0}var u=e("./ReactComponent"),c=e("./ReactMultiChildUpdateTypes"),l=e("./flattenChildren"),p=e("./instantiateReactComponent"),d=e("./shouldUpdateReactComponent"),f=0,h=[],v=[],m={Mixin:{mountChildren:function(e,t){var n=l(e),r=[],o=0;this._renderedChildren=n;for(var i in n){var a=n[i];if(n.hasOwnProperty(i)){var s=p(a);n[i]=s;var u=this._rootNodeID+i,c=s.mountComponent(u,t,this._mountDepth+1);s._mountIndex=o,r.push(c),o++}}return r},updateTextContent:function(e){f++;var t=!0;try{var n=this._renderedChildren;for(var r in n)n.hasOwnProperty(r)&&this._unmountChildByName(n[r],r);this.setTextContent(e),t=!1}finally{f--,f||(t?s():a())}},updateChildren:function(e,t){f++;var n=!0;try{this._updateChildren(e,t),n=!1}finally{f--,f||(n?s():a())}},_updateChildren:function(e,t){var n=l(e),r=this._renderedChildren;if(n||r){var o,i=0,a=0;for(o in n)if(n.hasOwnProperty(o)){var s=r&&r[o],u=s&&s._descriptor,c=n[o];if(d(u,c))this.moveChild(s,a,i),i=Math.max(s._mountIndex,i),s.receiveComponent(c,t),s._mountIndex=a;else{s&&(i=Math.max(s._mountIndex,i),this._unmountChildByName(s,o));var f=p(c);this._mountChildByNameAtIndex(f,o,a,t)}a++}for(o in r)!r.hasOwnProperty(o)||n&&n[o]||this._unmountChildByName(r[o],o)}},unmountChildren:function(){var e=this._renderedChildren;for(var t in e){var n=e[t];n.unmountComponent&&n.unmountComponent()}this._renderedChildren=null},moveChild:function(e,t,n){e._mountIndex<n&&r(this._rootNodeID,e._mountIndex,t)},createChild:function(e,t){n(this._rootNodeID,t,e._mountIndex)},removeChild:function(e){o(this._rootNodeID,e._mountIndex)},setTextContent:function(e){i(this._rootNodeID,e)},_mountChildByNameAtIndex:function(e,t,n,r){var o=this._rootNodeID+t,i=e.mountComponent(o,r,this._mountDepth+1);e._mountIndex=n,this.createChild(e,i),this._renderedChildren=this._renderedChildren||{},this._renderedChildren[t]=e},_unmountChildByName:function(e,t){this.removeChild(e),e._mountIndex=null,e.unmountComponent(),delete this._renderedChildren[t]}}};t.exports=m},{"./ReactComponent":35,"./ReactMultiChildUpdateTypes":67,"./flattenChildren":116,"./instantiateReactComponent":130,"./shouldUpdateReactComponent":149}],67:[function(e,t){"use strict";var n=e("./keyMirror"),r=n({INSERT_MARKUP:null,MOVE_EXISTING:null,REMOVE_NODE:null,TEXT_CONTENT:null});t.exports=r},{"./keyMirror":137}],68:[function(e,t){"use strict";var n=e("./emptyObject"),r=e("./invariant"),o={isValidOwner:function(e){return!(!e||"function"!=typeof e.attachRef||"function"!=typeof e.detachRef)},addComponentAsRefTo:function(e,t,n){r(o.isValidOwner(n)),n.attachRef(t,e)},removeComponentAsRefFrom:function(e,t,n){r(o.isValidOwner(n)),n.refs[t]===e&&n.detachRef(t)},Mixin:{construct:function(){this.refs=n},attachRef:function(e,t){r(t.isOwnedBy(this));var o=this.refs===n?this.refs={}:this.refs;o[e]=t},detachRef:function(e){delete this.refs[e]}}};t.exports=o},{"./emptyObject":114,"./invariant":131}],69:[function(e,t){"use strict";function n(e,t,n){return n}var r={enableMeasure:!1,storedMeasure:n,measure:function(e,t,n){return n},injection:{injectMeasure:function(e){r.storedMeasure=e}}};t.exports=r},{}],70:[function(e,t){"use strict";function n(e){return function(t,n,r){t[n]=t.hasOwnProperty(n)?e(t[n],r):r}}function r(e,t){for(var n in t)if(t.hasOwnProperty(n)){var r=c[n];r&&c.hasOwnProperty(n)?r(e,n,t[n]):e.hasOwnProperty(n)||(e[n]=t[n])}return e}var o=e("./emptyFunction"),i=e("./invariant"),a=e("./joinClasses"),s=e("./merge"),u=n(function(e,t){return s(t,e)}),c={children:o,className:n(a),key:o,ref:o,style:u},l={TransferStrategies:c,mergeProps:function(e,t){return r(s(e),t)},Mixin:{transferPropsTo:function(e){return i(e._owner===this),r(e.props,this.props),e}}};t.exports=l},{"./emptyFunction":113,"./invariant":131,"./joinClasses":136,"./merge":141}],71:[function(e,t){"use strict";var n={};t.exports=n},{}],72:[function(e,t){"use strict";var n=e("./keyMirror"),r=n({prop:null,context:null,childContext:null});t.exports=r},{"./keyMirror":137}],73:[function(e,t){"use strict";function n(e){function t(t,n,r,o,i){if(o=o||C,null!=n[r])return e(n,r,o,i);var a=g[i];return t?new Error("Required "+a+" `"+r+"` was not specified in "+("`"+o+"`.")):void 0}var n=t.bind(null,!1);return n.isRequired=t.bind(null,!0),n}function r(e){function t(t,n,r,o){var i=t[n],a=h(i);if(a!==e){var s=g[o],u=v(i);return new Error("Invalid "+s+" `"+n+"` of type `"+u+"` "+("supplied to `"+r+"`, expected `"+e+"`."))}}return n(t)}function o(){return n(y.thatReturns())}function i(e){function t(t,n,r,o){var i=t[n];if(!Array.isArray(i)){var a=g[o],s=h(i);return new Error("Invalid "+a+" `"+n+"` of type "+("`"+s+"` supplied to `"+r+"`, expected an array."))}for(var u=0;u<i.length;u++){var c=e(i,u,r,o);if(c instanceof Error)return c}}return n(t)}function a(