Merge m-c to b2g-inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 19 Nov 2013 22:28:07 -0500
changeset 156469 ec6d7da7e373251008d70e3a5a290db080dcef58
parent 156468 6baf5058aeab381ac953eefb8dbf775e219e7e38 (current diff)
parent 156458 4f993fa378ebe15621a7e03114ae99552db757f5 (diff)
child 156470 8ce14ece95a27169e5b965257ed4a7652c91683d
push id25683
push userryanvm@gmail.com
push dateThu, 21 Nov 2013 01:42:57 +0000
treeherdermozilla-central@cf378dddfac8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to b2g-inbound.
browser/components/sessionstore/test/unit/test_startup_nosession_sync.js
browser/components/sessionstore/test/unit/test_startup_session_sync.js
dom/contacts/tests/test_contacts_upgrade.html
dom/indexedDB/test/test_globalObjects.html
dom/indexedDB/test/test_globalObjects.xul
dom/indexedDB/test/unit/test_globalObjects.js
mobile/android/base/resources/drawable-hdpi-v11/ic_menu_share.png
mobile/android/base/resources/drawable-hdpi/awesomebar_sep_left.9.png
mobile/android/base/resources/drawable-hdpi/awesomebar_sep_right.9.png
mobile/android/base/resources/drawable-hdpi/awesomebar_tab_center.9.png
mobile/android/base/resources/drawable-hdpi/awesomebar_tab_left.9.png
mobile/android/base/resources/drawable-hdpi/awesomebar_tab_right.9.png
mobile/android/base/resources/drawable-hdpi/ic_notif_button_cancel.png
mobile/android/base/resources/drawable-hdpi/ic_notif_button_pause.png
mobile/android/base/resources/drawable-hdpi/ic_notif_button_resume.png
mobile/android/base/resources/drawable-mdpi-v11/ic_menu_share.png
mobile/android/base/resources/drawable-mdpi/awesomebar_sep_left.9.png
mobile/android/base/resources/drawable-mdpi/awesomebar_sep_right.9.png
mobile/android/base/resources/drawable-mdpi/awesomebar_tab_center.9.png
mobile/android/base/resources/drawable-mdpi/awesomebar_tab_left.9.png
mobile/android/base/resources/drawable-mdpi/awesomebar_tab_right.9.png
mobile/android/base/resources/drawable-mdpi/crash_reporter.png
mobile/android/base/resources/drawable-mdpi/ic_notif_button_cancel.png
mobile/android/base/resources/drawable-mdpi/ic_notif_button_pause.png
mobile/android/base/resources/drawable-mdpi/ic_notif_button_resume.png
mobile/android/base/resources/drawable-xhdpi-v11/ic_menu_share.png
mobile/android/base/resources/drawable-xhdpi/awesomebar_sep_left.9.png
mobile/android/base/resources/drawable-xhdpi/awesomebar_sep_right.9.png
mobile/android/base/resources/drawable-xhdpi/awesomebar_tab_center.9.png
mobile/android/base/resources/drawable-xhdpi/awesomebar_tab_left.9.png
mobile/android/base/resources/drawable-xhdpi/awesomebar_tab_right.9.png
mobile/android/base/resources/drawable-xhdpi/ic_notif_button_cancel.png
mobile/android/base/resources/drawable-xhdpi/ic_notif_button_pause.png
mobile/android/base/resources/drawable-xhdpi/ic_notif_button_resume.png
mobile/android/base/resources/drawable-xlarge-hdpi-v11/awesomebar_sep_left.9.png
mobile/android/base/resources/drawable-xlarge-hdpi-v11/awesomebar_sep_right.9.png
mobile/android/base/resources/drawable-xlarge-hdpi-v11/awesomebar_tab_center.9.png
mobile/android/base/resources/drawable-xlarge-hdpi-v11/awesomebar_tab_left.9.png
mobile/android/base/resources/drawable-xlarge-hdpi-v11/awesomebar_tab_right.9.png
mobile/android/base/resources/drawable-xlarge-mdpi-v11/awesomebar_sep_left.9.png
mobile/android/base/resources/drawable-xlarge-mdpi-v11/awesomebar_sep_right.9.png
mobile/android/base/resources/drawable-xlarge-mdpi-v11/awesomebar_tab_center.9.png
mobile/android/base/resources/drawable-xlarge-mdpi-v11/awesomebar_tab_left.9.png
mobile/android/base/resources/drawable-xlarge-mdpi-v11/awesomebar_tab_right.9.png
mobile/android/base/resources/drawable-xlarge-xhdpi-v11/awesomebar_sep_left.9.png
mobile/android/base/resources/drawable-xlarge-xhdpi-v11/awesomebar_sep_right.9.png
mobile/android/base/resources/drawable-xlarge-xhdpi-v11/awesomebar_tab_center.9.png
mobile/android/base/resources/drawable-xlarge-xhdpi-v11/awesomebar_tab_left.9.png
mobile/android/base/resources/drawable-xlarge-xhdpi-v11/awesomebar_tab_right.9.png
mobile/android/base/resources/layout/crash_reporter.xml
mobile/android/branding/aurora/content/fennec_144x144.png
mobile/android/branding/aurora/content/fennec_48x48.png
mobile/android/branding/aurora/content/fennec_72x72.png
mobile/android/branding/aurora/content/fennec_96x96.png
mobile/android/branding/beta/content/fennec_144x144.png
mobile/android/branding/beta/content/fennec_48x48.png
mobile/android/branding/beta/content/fennec_72x72.png
mobile/android/branding/beta/content/fennec_96x96.png
mobile/android/branding/nightly/content/fennec_144x144.png
mobile/android/branding/nightly/content/fennec_48x48.png
mobile/android/branding/nightly/content/fennec_72x72.png
mobile/android/branding/nightly/content/fennec_96x96.png
mobile/android/branding/official/content/fennec_144x144.png
mobile/android/branding/official/content/fennec_48x48.png
mobile/android/branding/official/content/fennec_72x72.png
mobile/android/branding/official/content/fennec_96x96.png
mobile/android/branding/unofficial/content/fennec_144x144.png
mobile/android/branding/unofficial/content/fennec_48x48.png
mobile/android/branding/unofficial/content/fennec_72x72.png
mobile/android/branding/unofficial/content/fennec_96x96.png
--- a/CLOBBER
+++ b/CLOBBER
@@ -13,9 +13,11 @@
 #          |               |
 #          O <-- Clobber   O  <-- Clobber
 #
 # Note: The description below will be part of the error message shown to users.
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
-Australis landing.
+Bug 934646 needs a clobber -- the icon resources previously copied
+into $OBJDIR/mobile/android/base/res will conflict with those in
+$BRANDING_DIRECTORY/res.
--- a/accessible/src/atk/nsMaiInterfaceValue.cpp
+++ b/accessible/src/atk/nsMaiInterfaceValue.cpp
@@ -1,122 +1,100 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "InterfaceInitFuncs.h"
-#include "mozilla/Likely.h"
 
 #include "AccessibleWrap.h"
 #include "nsMai.h"
 
+#include "mozilla/FloatingPoint.h"
+#include "mozilla/Likely.h"
+
+using namespace mozilla;
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static void
 getCurrentValueCB(AtkValue *obj, GValue *value)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleValue> accValue;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleValue),
-                            getter_AddRefs(accValue));
-    if (!accValue)
-        return;
+  memset (value,  0, sizeof (GValue));
+  double accValue = accWrap->CurValue();
+  if (IsNaN(accValue))
+    return;
 
-    memset (value,  0, sizeof (GValue));
-    double accDouble;
-    if (NS_FAILED(accValue->GetCurrentValue(&accDouble)))
-        return;
-    g_value_init (value, G_TYPE_DOUBLE);
-    g_value_set_double (value, accDouble);
+  g_value_init (value, G_TYPE_DOUBLE);
+  g_value_set_double (value, accValue);
 }
 
 static void
 getMaximumValueCB(AtkValue *obj, GValue *value)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleValue> accValue;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleValue),
-                            getter_AddRefs(accValue));
-    if (!accValue)
-        return;
+  memset(value,  0, sizeof (GValue));
+  double accValue = accWrap->MaxValue();
+  if (IsNaN(accValue))
+    return;
 
-    memset (value,  0, sizeof (GValue));
-    double accDouble;
-    if (NS_FAILED(accValue->GetMaximumValue(&accDouble)))
-        return;
-    g_value_init (value, G_TYPE_DOUBLE);
-    g_value_set_double (value, accDouble);
+  g_value_init(value, G_TYPE_DOUBLE);
+  g_value_set_double(value, accValue);
 }
 
 static void
 getMinimumValueCB(AtkValue *obj, GValue *value)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleValue> accValue;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleValue),
-                            getter_AddRefs(accValue));
-    if (!accValue)
-        return;
+  memset(value,  0, sizeof (GValue));
+  double accValue = accWrap->MinValue();
+  if (IsNaN(accValue))
+    return;
 
-    memset (value,  0, sizeof (GValue));
-    double accDouble;
-    if (NS_FAILED(accValue->GetMinimumValue(&accDouble)))
-        return;
-    g_value_init (value, G_TYPE_DOUBLE);
-    g_value_set_double (value, accDouble);
+  g_value_init(value, G_TYPE_DOUBLE);
+  g_value_set_double(value, accValue);
 }
 
 static void
 getMinimumIncrementCB(AtkValue *obj, GValue *minimumIncrement)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
   if (!accWrap)
     return;
 
-    nsCOMPtr<nsIAccessibleValue> accValue;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleValue),
-                            getter_AddRefs(accValue));
-    if (!accValue)
-        return;
+  memset(minimumIncrement,  0, sizeof (GValue));
+  double accValue = accWrap->Step();
+  if (IsNaN(accValue))
+    accValue = 0; // zero if the minimum increment is undefined
 
-    memset (minimumIncrement,  0, sizeof (GValue));
-    double accDouble;
-    if (NS_FAILED(accValue->GetMinimumIncrement(&accDouble)))
-        return;
-    g_value_init (minimumIncrement, G_TYPE_DOUBLE);
-    g_value_set_double (minimumIncrement, accDouble);
+  g_value_init(minimumIncrement, G_TYPE_DOUBLE);
+  g_value_set_double(minimumIncrement, accValue);
 }
 
 static gboolean
 setCurrentValueCB(AtkValue *obj, const GValue *value)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(obj));
   if (!accWrap)
     return FALSE;
 
-    nsCOMPtr<nsIAccessibleValue> accValue;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleValue),
-                            getter_AddRefs(accValue));
-    NS_ENSURE_TRUE(accValue, FALSE);
-
-    double accDouble =g_value_get_double (value);
-    return !NS_FAILED(accValue->SetCurrentValue(accDouble));
+  double accValue =g_value_get_double(value);
+  return accWrap->SetCurValue(accValue);
 }
 }
 
 void
 valueInterfaceInitCB(AtkValueIface* aIface)
 {
   NS_ASSERTION(aIface, "Invalid aIface");
   if (MOZ_UNLIKELY(!aIface))
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -73,16 +73,17 @@
 #include "nsNetUtil.h"
 #include "nsEventStates.h"
 
 #ifdef DEBUG
 #include "nsIDOMCharacterData.h"
 #endif
 
 #include "mozilla/Assertions.h"
+#include "mozilla/FloatingPoint.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/unused.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
@@ -1667,71 +1668,63 @@ Accessible::Value(nsString& aValue)
         option = listbox->GetSelectedItem(0);
     }
 
     if (option)
       nsTextEquivUtils::GetTextEquivFromSubtree(option, aValue);
   }
 }
 
-// nsIAccessibleValue
-NS_IMETHODIMP
-Accessible::GetMaximumValue(double *aMaximumValue)
+double
+Accessible::MaxValue() const
 {
-  return GetAttrValue(nsGkAtoms::aria_valuemax, aMaximumValue);
+  return AttrNumericValue(nsGkAtoms::aria_valuemax);
 }
 
-NS_IMETHODIMP
-Accessible::GetMinimumValue(double *aMinimumValue)
+double
+Accessible::MinValue() const
 {
-  return GetAttrValue(nsGkAtoms::aria_valuemin, aMinimumValue);
+  return AttrNumericValue(nsGkAtoms::aria_valuemin);
 }
 
-NS_IMETHODIMP
-Accessible::GetMinimumIncrement(double *aMinIncrement)
+double
+Accessible::Step() const
 {
-  NS_ENSURE_ARG_POINTER(aMinIncrement);
-  *aMinIncrement = 0;
-
-  // No mimimum increment in dynamic content spec right now
-  return NS_OK_NO_ARIA_VALUE;
+  return UnspecifiedNaN(); // no mimimum increment (step) in ARIA.
 }
 
-NS_IMETHODIMP
-Accessible::GetCurrentValue(double *aValue)
+double
+Accessible::CurValue() const
 {
-  return GetAttrValue(nsGkAtoms::aria_valuenow, aValue);
+  return AttrNumericValue(nsGkAtoms::aria_valuenow);
 }
 
-NS_IMETHODIMP
-Accessible::SetCurrentValue(double aValue)
+bool
+Accessible::SetCurValue(double aValue)
 {
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
   if (!mRoleMapEntry || mRoleMapEntry->valueRule == eNoValue)
-    return NS_OK_NO_ARIA_VALUE;
+    return false;
 
   const uint32_t kValueCannotChange = states::READONLY | states::UNAVAILABLE;
-
   if (State() & kValueCannotChange)
-    return NS_ERROR_FAILURE;
-
-  double minValue = 0;
-  if (NS_SUCCEEDED(GetMinimumValue(&minValue)) && aValue < minValue)
-    return NS_ERROR_INVALID_ARG;
-
-  double maxValue = 0;
-  if (NS_SUCCEEDED(GetMaximumValue(&maxValue)) && aValue > maxValue)
-    return NS_ERROR_INVALID_ARG;
-
-  nsAutoString newValue;
-  newValue.AppendFloat(aValue);
-  return mContent->SetAttr(kNameSpaceID_None,
-                           nsGkAtoms::aria_valuenow, newValue, true);
+    return false;
+
+  double checkValue = MinValue();
+  if (!IsNaN(checkValue) && aValue < checkValue)
+    return false;
+
+  checkValue = MaxValue();
+  if (!IsNaN(checkValue) && aValue > checkValue)
+    return false;
+
+  nsAutoString strValue;
+  strValue.AppendFloat(aValue);
+
+  return NS_SUCCEEDED(
+    mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow, strValue, true));
 }
 
 /* void setName (in DOMString name); */
 NS_IMETHODIMP
 Accessible::SetName(const nsAString& aName)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
@@ -3111,41 +3104,29 @@ Accessible::GetFirstAvailableAccessible(
     Accessible* accessible = mDoc->GetAccessible(node);
     if (accessible)
       return accessible;
   }
 
   return nullptr;
 }
 
-nsresult
-Accessible::GetAttrValue(nsIAtom *aProperty, double *aValue)
+double
+Accessible::AttrNumericValue(nsIAtom* aAttr) const
 {
-  NS_ENSURE_ARG_POINTER(aValue);
-  *aValue = 0;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;  // Node already shut down
-
- if (!mRoleMapEntry || mRoleMapEntry->valueRule == eNoValue)
-    return NS_OK_NO_ARIA_VALUE;
+  if (!mRoleMapEntry || mRoleMapEntry->valueRule == eNoValue)
+    return UnspecifiedNaN();
 
   nsAutoString attrValue;
-  mContent->GetAttr(kNameSpaceID_None, aProperty, attrValue);
-
-  // Return zero value if there is no attribute or its value is empty.
-  if (attrValue.IsEmpty())
-    return NS_OK;
+  if (!mContent->GetAttr(kNameSpaceID_None, aAttr, attrValue))
+    return UnspecifiedNaN();
 
   nsresult error = NS_OK;
   double value = attrValue.ToDouble(&error);
-  if (NS_SUCCEEDED(error))
-    *aValue = value;
-
-  return NS_OK;
+  return NS_FAILED(error) ? UnspecifiedNaN() : value;
 }
 
 uint32_t
 Accessible::GetActionRule()
 {
   if (!HasOwnContent() || (InteractiveState() & states::UNAVAILABLE))
     return eNoAction;
 
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -8,19 +8,19 @@
 
 #include "mozilla/a11y/AccTypes.h"
 #include "mozilla/a11y/RelationType.h"
 #include "mozilla/a11y/Role.h"
 #include "mozilla/a11y/States.h"
 
 #include "nsIAccessible.h"
 #include "nsIAccessibleHyperLink.h"
-#include "nsIAccessibleValue.h"
 #include "nsIAccessibleStates.h"
 #include "xpcAccessibleSelectable.h"
+#include "xpcAccessibleValue.h"
 
 #include "nsIContent.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
 
 struct nsRoleMapEntry;
 
@@ -100,28 +100,27 @@ typedef nsRefPtrHashtable<nsPtrHashKey<c
   0x4913,                                               \
   0x4355,                                               \
   { 0xbd, 0x50, 0x42, 0x6b, 0xd1, 0xd6, 0xe1, 0xad }    \
 }
 
 class Accessible : public nsIAccessible,
                    public nsIAccessibleHyperLink,
                    public xpcAccessibleSelectable,
-                   public nsIAccessibleValue
+                   public xpcAccessibleValue
 {
 public:
   Accessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~Accessible();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(Accessible, nsIAccessible)
 
   NS_DECL_NSIACCESSIBLE
   NS_DECL_NSIACCESSIBLEHYPERLINK
-  NS_DECL_NSIACCESSIBLEVALUE
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_IID)
 
   //////////////////////////////////////////////////////////////////////////////
   // Public methods
 
   /**
    * Return the document accessible for this accessible.
    */
@@ -684,16 +683,25 @@ public:
   virtual bool SelectAll();
 
   /**
    * Unselect all items. Return true if success.
    */
   virtual bool UnselectAll();
 
   //////////////////////////////////////////////////////////////////////////////
+  // Value (numeric value interface)
+
+  virtual double MaxValue() const;
+  virtual double MinValue() const;
+  virtual double CurValue() const;
+  virtual double Step() const;
+  virtual bool SetCurValue(double aValue);
+
+  //////////////////////////////////////////////////////////////////////////////
   // Widgets
 
   /**
    * Return true if accessible is a widget, i.e. control or accessible that
    * manages its items. Note, being a widget the accessible may be a part of
    * composite widget.
    */
   virtual bool IsWidget() const;
@@ -906,24 +914,22 @@ protected:
 
   /**
    *  Get the container node for an atomic region, defined by aria-atomic="true"
    *  @return the container node
    */
   nsIContent* GetAtomicRegion() const;
 
   /**
-   * Get numeric value of the given ARIA attribute.
+   * Return numeric value of the given ARIA attribute, NaN if not applicable.
    *
-   * @param aAriaProperty - the ARIA property we're using
-   * @param aValue - value of the attribute
-   *
-   * @return - NS_OK_NO_ARIA_VALUE if there is no setted ARIA attribute
+   * @param aARIAProperty  [in] the ARIA property we're using
+   * @return  a numeric value
    */
-  nsresult GetAttrValue(nsIAtom *aAriaProperty, double *aValue);
+  double AttrNumericValue(nsIAtom* aARIAAttr) const;
 
   /**
    * Return the action rule based on ARIA enum constants EActionRule
    * (see ARIAMap.h). Used by ActionCount() and GetActionName().
    */
   uint32_t GetActionRule();
 
   /**
--- a/accessible/src/generic/FormControlAccessible.cpp
+++ b/accessible/src/generic/FormControlAccessible.cpp
@@ -3,16 +3,17 @@
  * 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/. */
 
 // NOTE: alphabetically ordered
 
 #include "FormControlAccessible.h"
 #include "Role.h"
 
+#include "mozilla/FloatingPoint.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULControlElement.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // ProgressMeterAccessible
@@ -77,106 +78,89 @@ ProgressMeterAccessible<Max>::IsWidget()
 template<int Max>
 void
 ProgressMeterAccessible<Max>::Value(nsString& aValue)
 {
   LeafAccessible::Value(aValue);
   if (!aValue.IsEmpty())
     return;
 
-  double maxValue = 0;
-  nsresult rv = GetMaximumValue(&maxValue);
-  if (NS_FAILED(rv) || maxValue == 0)
+  double maxValue = MaxValue();
+  if (IsNaN(maxValue) || maxValue == 0)
     return;
 
-  double curValue = 0;
-  GetCurrentValue(&curValue);
-  if (NS_FAILED(rv))
+  double curValue = CurValue();
+  if (IsNaN(curValue))
     return;
 
   // Treat the current value bigger than maximum as 100%.
   double percentValue = (curValue < maxValue) ?
     (curValue / maxValue) * 100 : 100;
 
   aValue.AppendFloat(percentValue);
   aValue.AppendLiteral("%");
 }
 
 template<int Max>
-NS_IMETHODIMP
-ProgressMeterAccessible<Max>::GetMaximumValue(double* aMaximumValue)
+double
+ProgressMeterAccessible<Max>::MaxValue() const
 {
-  nsresult rv = LeafAccessible::GetMaximumValue(aMaximumValue);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
+  double value = LeafAccessible::MaxValue();
+  if (!IsNaN(value))
+    return value;
 
-  nsAutoString value;
-  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::max, value)) {
+  nsAutoString strValue;
+  if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::max, strValue)) {
     nsresult result = NS_OK;
-    *aMaximumValue = value.ToDouble(&result);
-    return result;
+    value = strValue.ToDouble(&result);
+    if (NS_SUCCEEDED(result))
+      return value;
   }
 
-  *aMaximumValue = Max;
-  return NS_OK;
+  return Max;
 }
 
 template<int Max>
-NS_IMETHODIMP
-ProgressMeterAccessible<Max>::GetMinimumValue(double* aMinimumValue)
+double
+ProgressMeterAccessible<Max>::MinValue() const
 {
-  nsresult rv = LeafAccessible::GetMinimumValue(aMinimumValue);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  *aMinimumValue = 0;
-  return NS_OK;
+  double value = LeafAccessible::MinValue();
+  return IsNaN(value) ? 0 : value;
 }
 
 template<int Max>
-NS_IMETHODIMP
-ProgressMeterAccessible<Max>::GetMinimumIncrement(double* aMinimumIncrement)
+double
+ProgressMeterAccessible<Max>::Step() const
 {
-  nsresult rv = LeafAccessible::GetMinimumIncrement(aMinimumIncrement);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  *aMinimumIncrement = 0;
-  return NS_OK;
+  double value = LeafAccessible::Step();
+  return IsNaN(value) ? 0 : value;
 }
 
 template<int Max>
-NS_IMETHODIMP
-ProgressMeterAccessible<Max>::GetCurrentValue(double* aCurrentValue)
+double
+ProgressMeterAccessible<Max>::CurValue() const
 {
-  nsresult rv = LeafAccessible::GetCurrentValue(aCurrentValue);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
+  double value = LeafAccessible::CurValue();
+  if (!IsNaN(value))
+    return value;
 
   nsAutoString attrValue;
-  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue);
-
-  // Return zero value if there is no attribute or its value is empty.
-  if (attrValue.IsEmpty())
-    return NS_OK;
+  if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, attrValue))
+    return UnspecifiedNaN();
 
   nsresult error = NS_OK;
-  double value = attrValue.ToDouble(&error);
-  if (NS_FAILED(error))
-    return NS_OK; // Zero value because of wrong markup.
-
-  *aCurrentValue = value;
-  return NS_OK;
+  value = attrValue.ToDouble(&error);
+  return NS_FAILED(error) ? UnspecifiedNaN() : value;
 }
 
 template<int Max>
-NS_IMETHODIMP
-ProgressMeterAccessible<Max>::SetCurrentValue(double aValue)
+bool
+ProgressMeterAccessible<Max>::SetCurValue(double aValue)
 {
-  return NS_ERROR_FAILURE; // Progress meters are readonly.
+  return false; // progress meters are readonly.
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // RadioButtonAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 RadioButtonAccessible::
   RadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
--- a/accessible/src/generic/FormControlAccessible.h
+++ b/accessible/src/generic/FormControlAccessible.h
@@ -23,23 +23,29 @@ public:
   {
     // Ignore 'ValueChange' DOM event in lieu of @value attribute change
     // notifications.
     mStateFlags |= eHasNumericValue | eIgnoreDOMUIEvent;
     mType = eProgressType;
   }
 
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBLEVALUE
 
   // Accessible
   virtual void Value(nsString& aValue);
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t NativeState();
 
+  // Value
+  virtual double MaxValue() const MOZ_OVERRIDE;
+  virtual double MinValue() const MOZ_OVERRIDE;
+  virtual double CurValue() const MOZ_OVERRIDE;
+  virtual double Step() const MOZ_OVERRIDE;
+  virtual bool SetCurValue(double aValue) MOZ_OVERRIDE;
+
   // Widgets
   virtual bool IsWidget() const;
 };
 
 /**
   * Generic class used for radio buttons.
   */
 class RadioButtonAccessible : public LeafAccessible
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -22,16 +22,17 @@
 #include "nsIEditor.h"
 #include "nsIFormControl.h"
 #include "nsINameSpaceManager.h"
 #include "nsIPersistentProperties2.h"
 #include "nsISelectionController.h"
 #include "nsIServiceManager.h"
 #include "nsITextControlFrame.h"
 
+#include "mozilla/FloatingPoint.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLCheckboxAccessible
@@ -540,19 +541,16 @@ HTMLFileInputAccessible::HandleAccEvent(
   return NS_OK;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLRangeAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-NS_IMPL_ISUPPORTS_INHERITED1(HTMLRangeAccessible, LeafAccessible,
-                             nsIAccessibleValue)
-
 role
 HTMLRangeAccessible::NativeRole()
 {
   return roles::SLIDER;
 }
 
 bool
 HTMLRangeAccessible::IsWidget() const
@@ -565,68 +563,63 @@ HTMLRangeAccessible::Value(nsString& aVa
 {
   LeafAccessible::Value(aValue);
   if (!aValue.IsEmpty())
     return;
 
   HTMLInputElement::FromContent(mContent)->GetValue(aValue);
 }
 
-NS_IMETHODIMP
-HTMLRangeAccessible::GetMaximumValue(double* aMaximumValue)
+double
+HTMLRangeAccessible::MaxValue() const
 {
-  nsresult rv = LeafAccessible::GetMaximumValue(aMaximumValue);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  *aMaximumValue = HTMLInputElement::FromContent(mContent)->GetMaximum().toDouble();
-  return NS_OK;
-}
+  double value = LeafAccessible::MaxValue();
+  if (!IsNaN(value))
+    return value;
 
-
-NS_IMETHODIMP
-HTMLRangeAccessible::GetMinimumValue(double* aMinimumValue)
-{
-  nsresult rv = LeafAccessible::GetMinimumValue(aMinimumValue);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  *aMinimumValue = HTMLInputElement::FromContent(mContent)->GetMinimum().toDouble();
-  return NS_OK;
+  return HTMLInputElement::FromContent(mContent)->GetMaximum().toDouble();
 }
 
 
-NS_IMETHODIMP
-HTMLRangeAccessible::GetMinimumIncrement(double* aMinimumIncrement)
+double
+HTMLRangeAccessible::MinValue() const
 {
-  nsresult rv = LeafAccessible::GetMinimumIncrement(aMinimumIncrement);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
+  double value = LeafAccessible::MinValue();
+  if (!IsNaN(value))
+    return value;
 
-  *aMinimumIncrement = HTMLInputElement::FromContent(mContent)->GetStep().toDouble();
-  return NS_OK;
+  return HTMLInputElement::FromContent(mContent)->GetMinimum().toDouble();
 }
 
-NS_IMETHODIMP
-HTMLRangeAccessible::GetCurrentValue(double* aCurrentValue)
+double
+HTMLRangeAccessible::Step() const
 {
-  nsresult rv = LeafAccessible::GetCurrentValue(aCurrentValue);
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
+  double value = LeafAccessible::Step();
+  if (!IsNaN(value))
+    return value;
 
-  *aCurrentValue = HTMLInputElement::FromContent(mContent)->GetValueAsDecimal().toDouble();
-  return NS_OK;
+  return HTMLInputElement::FromContent(mContent)->GetStep().toDouble();
 }
 
-NS_IMETHODIMP
-HTMLRangeAccessible::SetCurrentValue(double aValue)
+double
+HTMLRangeAccessible::CurValue() const
+{
+  double value = LeafAccessible::CurValue();
+  if (!IsNaN(value))
+    return value;
+
+  return HTMLInputElement::FromContent(mContent)->GetValueAsDecimal().toDouble();
+}
+
+bool
+HTMLRangeAccessible::SetCurValue(double aValue)
 {
   ErrorResult er;
   HTMLInputElement::FromContent(mContent)->SetValueAsNumber(aValue, er);
-  return er.ErrorCode();
+  return !er.Failed();
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLGroupboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 HTMLGroupboxAccessible::
--- a/accessible/src/html/HTMLFormControlAccessible.h
+++ b/accessible/src/html/HTMLFormControlAccessible.h
@@ -167,23 +167,27 @@ class HTMLRangeAccessible : public LeafA
 {
 public:
   HTMLRangeAccessible(nsIContent* aContent, DocAccessible* aDoc) :
     LeafAccessible(aContent, aDoc)
   {
     mStateFlags |= eHasNumericValue;
   }
 
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBLEVALUE
-
   // Accessible
   virtual void Value(nsString& aValue);
   virtual mozilla::a11y::role NativeRole();
 
+  // Value
+  virtual double MaxValue() const MOZ_OVERRIDE;
+  virtual double MinValue() const MOZ_OVERRIDE;
+  virtual double CurValue() const MOZ_OVERRIDE;
+  virtual double Step() const MOZ_OVERRIDE;
+  virtual bool SetCurValue(double aValue) MOZ_OVERRIDE;
+
   // Widgets
   virtual bool IsWidget() const;
 };
 
 
 /**
  * Accessible for HTML fieldset element.
  */
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -81,17 +81,17 @@ this.AccessFu = {
     if (this._enabled)
       return;
     this._enabled = true;
 
     Cu.import('resource://gre/modules/accessibility/Utils.jsm');
     Cu.import('resource://gre/modules/accessibility/TouchAdapter.jsm');
     Cu.import('resource://gre/modules/accessibility/Presentation.jsm');
 
-    Logger.info('enable');
+    Logger.info('Enabled');
 
     for each (let mm in Utils.AllMessageManagers) {
       this._addMessageListeners(mm);
       this._loadFrameScript(mm);
     }
 
     // Add stylesheet
     let stylesheetURL = 'chrome://global/content/accessibility/AccessFu.css';
@@ -140,17 +140,17 @@ this.AccessFu = {
    * Disable AccessFu and return to default interaction mode.
    */
   _disable: function _disable() {
     if (!this._enabled)
       return;
 
     this._enabled = false;
 
-    Logger.info('disable');
+    Logger.info('Disabled');
 
     Utils.win.document.removeChild(this.stylesheet.get());
 
     for each (let mm in Utils.AllMessageManagers) {
       mm.sendAsyncMessage('AccessFu:Stop');
       this._removeMessageListeners(mm);
     }
 
@@ -519,19 +519,18 @@ var Output = {
 
     output: function output(aActions) {
       if (!this.inited) {
         this.init();
       }
 
       for (let action of aActions) {
         let window = Utils.win;
-        Logger.info('tts.' + action.method,
-                    '"' + action.data + '"',
-                    JSON.stringify(action.options));
+        Logger.debug('tts.' + action.method, '"' + action.data + '"',
+                     JSON.stringify(action.options));
 
         if (!action.options.enqueue && this.webspeechEnabled) {
           window.speechSynthesis.cancel();
         }
 
         if (action.method === 'speak' && this.webspeechEnabled) {
           window.speechSynthesis.speak(
             new window.SpeechSynthesisUtterance(action.data));
@@ -710,18 +709,18 @@ var Input = {
       }
     } catch (x) {
       Logger.logException(x);
     }
   },
 
   _handleGesture: function _handleGesture(aGesture) {
     let gestureName = aGesture.type + aGesture.touches.length;
-    Logger.info('Gesture', aGesture.type,
-                '(fingers: ' + aGesture.touches.length + ')');
+    Logger.debug('Gesture', aGesture.type,
+                 '(fingers: ' + aGesture.touches.length + ')');
 
     switch (gestureName) {
       case 'dwell1':
       case 'explore1':
         this.moveToPoint('Simple', aGesture.x, aGesture.y);
         break;
       case 'doubletap1':
         this.activateCurrent();
new file mode 100644
--- /dev/null
+++ b/accessible/src/jsat/Constants.jsm
@@ -0,0 +1,39 @@
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+this.EXPORTED_SYMBOLS = ['Roles', 'Events', 'Relations', 'Filters'];
+
+function ConstantsMap (aObject, aPrefix) {
+  let offset = aPrefix.length;
+  for (var name in aObject) {
+    if (name.indexOf(aPrefix) === 0) {
+      this[name.slice(offset)] = aObject[name];
+    }
+  }
+}
+
+XPCOMUtils.defineLazyGetter(
+  this, 'Roles',
+  function() {
+    return new ConstantsMap(Ci.nsIAccessibleRole, 'ROLE_');
+  });
+
+XPCOMUtils.defineLazyGetter(
+  this, 'Events',
+  function() {
+    return new ConstantsMap(Ci.nsIAccessibleEvent, 'EVENT_');
+  });
+
+XPCOMUtils.defineLazyGetter(
+  this, 'Relations',
+  function() {
+    return new ConstantsMap(Ci.nsIAccessibleRelation, 'RELATION_');
+  });
+
+XPCOMUtils.defineLazyGetter(
+  this, 'Filters',
+  function() {
+    return new ConstantsMap(Ci.nsIAccessibleTraversalRule, 'FILTER_');
+  });
--- a/accessible/src/jsat/EventManager.jsm
+++ b/accessible/src/jsat/EventManager.jsm
@@ -2,44 +2,33 @@
  * 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 Ci = Components.interfaces;
 const Cu = Components.utils;
 
-const EVENT_VIRTUALCURSOR_CHANGED = Ci.nsIAccessibleEvent.EVENT_VIRTUALCURSOR_CHANGED;
-const EVENT_STATE_CHANGE = Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE;
-const EVENT_SCROLLING_START = Ci.nsIAccessibleEvent.EVENT_SCROLLING_START;
-const EVENT_TEXT_CARET_MOVED = Ci.nsIAccessibleEvent.EVENT_TEXT_CARET_MOVED;
-const EVENT_TEXT_INSERTED = Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED;
-const EVENT_TEXT_REMOVED = Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED;
-const EVENT_FOCUS = Ci.nsIAccessibleEvent.EVENT_FOCUS;
-const EVENT_SHOW = Ci.nsIAccessibleEvent.EVENT_SHOW;
-const EVENT_HIDE = Ci.nsIAccessibleEvent.EVENT_HIDE;
-
-const ROLE_INTERNAL_FRAME = Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME;
-const ROLE_DOCUMENT = Ci.nsIAccessibleRole.ROLE_DOCUMENT;
-const ROLE_CHROME_WINDOW = Ci.nsIAccessibleRole.ROLE_CHROME_WINDOW;
-const ROLE_TEXT_LEAF = Ci.nsIAccessibleRole.ROLE_TEXT_LEAF;
-
 const TEXT_NODE = 3;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Services',
   'resource://gre/modules/Services.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
   'resource://gre/modules/accessibility/Presentation.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules',
   'resource://gre/modules/accessibility/TraversalRules.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
+  'resource://gre/modules/accessibility/Constants.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Events',
+  'resource://gre/modules/accessibility/Constants.jsm');
 
 this.EXPORTED_SYMBOLS = ['EventManager'];
 
 this.EventManager = function EventManager(aContentScope) {
   this.contentScope = aContentScope;
   this.addEventListener = this.contentScope.addEventListener.bind(
     this.contentScope);
   this.removeEventListener = this.contentScope.removeEventListener.bind(
@@ -52,17 +41,17 @@ this.EventManager = function EventManage
 };
 
 this.EventManager.prototype = {
   editState: {},
 
   start: function start() {
     try {
       if (!this._started) {
-        Logger.info('EventManager.start', Utils.MozBuildApp);
+        Logger.debug('EventManager.start');
 
         this._started = true;
 
         AccessibilityEventObserver.addListener(this);
 
         this.webProgress.addProgressListener(this,
           (Ci.nsIWebProgress.NOTIFY_STATE_ALL |
            Ci.nsIWebProgress.NOTIFY_LOCATION));
@@ -79,17 +68,17 @@ this.EventManager.prototype = {
   },
 
   // XXX: Stop is not called when the tab is closed (|TabClose| event is too
   // late). It is only called when the AccessFu is disabled explicitly.
   stop: function stop() {
     if (!this._started) {
       return;
     }
-    Logger.info('EventManager.stop', Utils.MozBuildApp);
+    Logger.debug('EventManager.stop');
     AccessibilityEventObserver.removeListener(this);
     try {
       this.webProgress.removeProgressListener(this);
       this.removeEventListener('scroll', this, true);
       this.removeEventListener('resize', this, true);
       // XXX: Ideally this would be an a11y event. Bug #742280.
       this.removeEventListener('DOMActivate', this, true);
     } catch (x) {
@@ -139,70 +128,70 @@ this.EventManager.prototype = {
 
   handleAccEvent: function handleAccEvent(aEvent) {
     if (Logger.logLevel >= Logger.DEBUG)
       Logger.debug('A11yEvent', Logger.eventToString(aEvent),
                    Logger.accessibleToString(aEvent.accessible));
 
     // Don't bother with non-content events in firefox.
     if (Utils.MozBuildApp == 'browser' &&
-        aEvent.eventType != EVENT_VIRTUALCURSOR_CHANGED &&
+        aEvent.eventType != Events.VIRTUALCURSOR_CHANGED &&
         // XXX Bug 442005 results in DocAccessible::getDocType returning
         // NS_ERROR_FAILURE. Checking for aEvent.accessibleDocument.docType ==
         // 'window' does not currently work.
         (aEvent.accessibleDocument.DOMDocument.doctype &&
          aEvent.accessibleDocument.DOMDocument.doctype.name === 'window')) {
       return;
     }
 
     switch (aEvent.eventType) {
-      case EVENT_VIRTUALCURSOR_CHANGED:
+      case Events.VIRTUALCURSOR_CHANGED:
       {
         let pivot = aEvent.accessible.
           QueryInterface(Ci.nsIAccessibleDocument).virtualCursor;
         let position = pivot.position;
-        if (position && position.role == ROLE_INTERNAL_FRAME)
+        if (position && position.role == Roles.INTERNAL_FRAME)
           break;
         let event = aEvent.
           QueryInterface(Ci.nsIAccessibleVirtualCursorChangeEvent);
         let reason = event.reason;
 
         if (this.editState.editing) {
           aEvent.accessibleDocument.takeFocus();
         }
         this.present(
           Presentation.pivotChanged(position, event.oldAccessible, reason,
                                     pivot.startOffset, pivot.endOffset));
 
         break;
       }
-      case EVENT_STATE_CHANGE:
+      case Events.STATE_CHANGE:
       {
         let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
         if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED &&
             !(event.isExtraState)) {
           this.present(
             Presentation.
               actionInvoked(aEvent.accessible,
                             event.isEnabled ? 'check' : 'uncheck'));
         } else if (event.state == Ci.nsIAccessibleStates.STATE_SELECTED) {
           this.present(
             Presentation.
               actionInvoked(aEvent.accessible,
                             event.isEnabled ? 'select' : 'unselect'));
         }
         break;
       }
-      case EVENT_SCROLLING_START:
+      case Events.SCROLLING_START:
       {
         let vc = Utils.getVirtualCursor(aEvent.accessibleDocument);
         vc.moveNext(TraversalRules.Simple, aEvent.accessible, true);
         break;
       }
-      case EVENT_TEXT_CARET_MOVED:
+      case Events.TEXT_CARET_MOVED:
       {
         let acc = aEvent.accessible;
         let characterCount = acc.
           QueryInterface(Ci.nsIAccessibleText).characterCount;
         let caretOffset = aEvent.
           QueryInterface(Ci.nsIAccessibleCaretMoveEvent).caretOffset;
 
         // Update editing state, both for presenter and other things
@@ -228,66 +217,66 @@ this.EventManager.prototype = {
           this.sendMsgFunc("AccessFu:Input", editState);
 
         this.present(Presentation.textSelectionChanged(acc.getText(0,-1),
                      caretOffset, caretOffset, 0, 0, aEvent.isFromUserInput));
 
         this.editState = editState;
         break;
       }
-      case EVENT_SHOW:
+      case Events.SHOW:
       {
         let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
           ['additions', 'all']);
         // Only handle show if it is a relevant live region.
         if (!liveRegion) {
           break;
         }
         // Show for text is handled by the EVENT_TEXT_INSERTED handler.
-        if (aEvent.accessible.role === ROLE_TEXT_LEAF) {
+        if (aEvent.accessible.role === Roles.TEXT_LEAF) {
           break;
         }
-        this._dequeueLiveEvent(EVENT_HIDE, liveRegion);
+        this._dequeueLiveEvent(Events.HIDE, liveRegion);
         this.present(Presentation.liveRegion(liveRegion, isPolite, false));
         break;
       }
-      case EVENT_HIDE:
+      case Events.HIDE:
       {
         let {liveRegion, isPolite} = this._handleLiveRegion(
           aEvent.QueryInterface(Ci.nsIAccessibleHideEvent),
           ['removals', 'all']);
         // Only handle hide if it is a relevant live region.
         if (!liveRegion) {
           break;
         }
         // Hide for text is handled by the EVENT_TEXT_REMOVED handler.
-        if (aEvent.accessible.role === ROLE_TEXT_LEAF) {
+        if (aEvent.accessible.role === Roles.TEXT_LEAF) {
           break;
         }
-        this._queueLiveEvent(EVENT_HIDE, liveRegion, isPolite);
+        this._queueLiveEvent(Events.HIDE, liveRegion, isPolite);
         break;
       }
-      case EVENT_TEXT_INSERTED:
-      case EVENT_TEXT_REMOVED:
+      case Events.TEXT_INSERTED:
+      case Events.TEXT_REMOVED:
       {
         let {liveRegion, isPolite} = this._handleLiveRegion(aEvent,
           ['text', 'all']);
         if (aEvent.isFromUserInput || liveRegion) {
           // Handle all text mutations coming from the user or if they happen
           // on a live region.
           this._handleText(aEvent, liveRegion, isPolite);
         }
         break;
       }
-      case EVENT_FOCUS:
+      case Events.FOCUS:
       {
         // Put vc where the focus is at
         let acc = aEvent.accessible;
         let doc = aEvent.accessibleDocument;
-        if (acc.role != ROLE_DOCUMENT && doc.role != ROLE_CHROME_WINDOW) {
+        if (acc.role != Roles.DOCUMENT && doc.role != Roles.CHROME_WINDOW) {
           let vc = Utils.getVirtualCursor(doc);
           vc.moveNext(TraversalRules.Simple, acc, true);
         }
         break;
       }
     }
   },
 
@@ -309,21 +298,21 @@ this.EventManager.prototype = {
     // If there are embedded objects in the text, ignore them.
     // Assuming changes to the descendants would already be handled by the
     // show/hide event.
     let modifiedText = event.modifiedText.replace(/\uFFFC/g, '').trim();
     if (!modifiedText) {
       return;
     }
     if (aLiveRegion) {
-      if (aEvent.eventType === EVENT_TEXT_REMOVED) {
-        this._queueLiveEvent(EVENT_TEXT_REMOVED, aLiveRegion, aIsPolite,
+      if (aEvent.eventType === Events.TEXT_REMOVED) {
+        this._queueLiveEvent(Events.TEXT_REMOVED, aLiveRegion, aIsPolite,
           modifiedText);
       } else {
-        this._dequeueLiveEvent(EVENT_TEXT_REMOVED, aLiveRegion);
+        this._dequeueLiveEvent(Events.TEXT_REMOVED, aLiveRegion);
         this.present(Presentation.liveRegion(aLiveRegion, aIsPolite, false,
           modifiedText));
       }
     } else {
       this.present(Presentation.textChanged(isInserted, event.start,
         event.length, text, modifiedText));
     }
   },
--- a/accessible/src/jsat/Makefile.in
+++ b/accessible/src/jsat/Makefile.in
@@ -1,19 +1,3 @@
 # 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/.
-
-INSTALL_TARGETS += ACCESSFU
-
-ACCESSFU_FILES := \
-  AccessFu.jsm \
-  EventManager.jsm \
-  jar.mn \
-  Makefile.in \
-  OutputGenerator.jsm \
-  Presentation.jsm \
-  TouchAdapter.jsm \
-  TraversalRules.jsm \
-  Utils.jsm \
-  $(NULL)
-
-ACCESSFU_DEST = $(FINAL_TARGET)/modules/accessibility
--- a/accessible/src/jsat/OutputGenerator.jsm
+++ b/accessible/src/jsat/OutputGenerator.jsm
@@ -13,29 +13,27 @@ const INCLUDE_DESC = 0x01;
 const INCLUDE_NAME = 0x02;
 const INCLUDE_VALUE = 0x04;
 const INCLUDE_CUSTOM = 0x08;
 const NAME_FROM_SUBTREE_RULE = 0x10;
 
 const OUTPUT_DESC_FIRST = 0;
 const OUTPUT_DESC_LAST = 1;
 
-const ROLE_LISTITEM = Ci.nsIAccessibleRole.ROLE_LISTITEM;
-const ROLE_STATICTEXT = Ci.nsIAccessibleRole.ROLE_STATICTEXT;
-const ROLE_LINK = Ci.nsIAccessibleRole.ROLE_LINK;
-
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'PrefCache',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'PluralForm',
   'resource://gre/modules/PluralForm.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
+  'resource://gre/modules/accessibility/Constants.jsm');
 
 var gStringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
   getService(Ci.nsIStringBundleService).
   createBundle('chrome://global/locale/AccessFu.properties');
 
 this.EXPORTED_SYMBOLS = ['UtteranceGenerator', 'BrailleGenerator'];
 
 this.OutputGenerator = {
@@ -692,18 +690,18 @@ this.BrailleGenerator = {
   objectOutputFunctions: {
 
     __proto__: OutputGenerator.objectOutputFunctions,
 
     defaultFunc: function defaultFunc(aAccessible, aRoleStr, aStates, aFlags) {
       let braille = this.objectOutputFunctions._generateBaseOutput.apply(this, arguments);
 
       if (aAccessible.indexInParent === 1 &&
-          aAccessible.parent.role == ROLE_LISTITEM &&
-          aAccessible.previousSibling.role == ROLE_STATICTEXT) {
+          aAccessible.parent.role == Roles.LISTITEM &&
+          aAccessible.previousSibling.role == Roles.STATICTEXT) {
         if (aAccessible.parent.parent && aAccessible.parent.parent.DOMNode &&
             aAccessible.parent.parent.DOMNode.nodeName == 'UL') {
           braille.unshift('*');
         } else {
           braille.unshift(aAccessible.previousSibling.name);
         }
       }
 
@@ -750,17 +748,17 @@ this.BrailleGenerator = {
 
     rowheader: function rowheader() {
       return this.objectOutputFunctions.cell.apply(this, arguments);
     },
 
     statictext: function statictext(aAccessible, aRoleStr, aStates, aFlags) {
       // Since we customize the list bullet's output, we add the static
       // text from the first node in each listitem, so skip it here.
-      if (aAccessible.parent.role == ROLE_LISTITEM) {
+      if (aAccessible.parent.role == Roles.LISTITEM) {
         return [];
       }
 
       return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
     },
 
     _useStateNotRole: function _useStateNotRole(aAccessible, aRoleStr, aStates, aFlags) {
       let braille = [];
@@ -783,17 +781,17 @@ this.BrailleGenerator = {
     },
 
     togglebutton: function radiobutton(aAccessible, aRoleStr, aStates, aFlags) {
       return this.objectOutputFunctions._useStateNotRole.apply(this, arguments);
     }
   },
 
   _getContextStart: function _getContextStart(aContext) {
-    if (aContext.accessible.parent.role == ROLE_LINK) {
+    if (aContext.accessible.parent.role == Roles.LINK) {
       return [aContext.accessible.parent];
     }
 
     return [];
   },
 
   _getOutputName: function _getOutputName(aName) {
     return OutputGenerator._getOutputName(aName) + 'Abbr';
--- a/accessible/src/jsat/TouchAdapter.jsm
+++ b/accessible/src/jsat/TouchAdapter.jsm
@@ -41,17 +41,17 @@ this.TouchAdapter = {
 
   // The virtual touch ID generated by a mouse event.
   MOUSE_ID: 'mouse',
 
   // Synthesized touch ID.
   SYNTH_ID: -1,
 
   start: function TouchAdapter_start() {
-    Logger.info('TouchAdapter.start');
+    Logger.debug('TouchAdapter.start');
 
     this._touchPoints = {};
     this._dwellTimeout = 0;
     this._prevGestures = {};
     this._lastExploreTime = 0;
     this._dpi = Utils.win.QueryInterface(Ci.nsIInterfaceRequestor).
       getInterface(Ci.nsIDOMWindowUtils).displayDPI;
 
@@ -59,17 +59,17 @@ this.TouchAdapter = {
 
     for (let eventType in this.eventsOfInterest) {
       target.addEventListener(eventType, this, true, true);
     }
 
   },
 
   stop: function TouchAdapter_stop() {
-    Logger.info('TouchAdapter.stop');
+    Logger.debug('TouchAdapter.stop');
 
     let target = Utils.win;
 
     for (let eventType in this.eventsOfInterest) {
       target.removeEventListener(eventType, this, true, true);
     }
   },
 
--- a/accessible/src/jsat/TraversalRules.jsm
+++ b/accessible/src/jsat/TraversalRules.jsm
@@ -4,308 +4,271 @@
 
 'use strict';
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
-const FILTER_IGNORE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE;
-const FILTER_MATCH = Ci.nsIAccessibleTraversalRule.FILTER_MATCH;
-const FILTER_IGNORE_SUBTREE = Ci.nsIAccessibleTraversalRule.FILTER_IGNORE_SUBTREE;
-
-const ROLE_MENUITEM = Ci.nsIAccessibleRole.ROLE_MENUITEM;
-const ROLE_LINK = Ci.nsIAccessibleRole.ROLE_LINK;
-const ROLE_PAGETAB = Ci.nsIAccessibleRole.ROLE_PAGETAB;
-const ROLE_GRAPHIC = Ci.nsIAccessibleRole.ROLE_GRAPHIC;
-const ROLE_STATICTEXT = Ci.nsIAccessibleRole.ROLE_STATICTEXT;
-const ROLE_TEXT_LEAF = Ci.nsIAccessibleRole.ROLE_TEXT_LEAF;
-const ROLE_PUSHBUTTON = Ci.nsIAccessibleRole.ROLE_PUSHBUTTON;
-const ROLE_SPINBUTTON = Ci.nsIAccessibleRole.ROLE_SPINBUTTON;
-const ROLE_CHECKBUTTON = Ci.nsIAccessibleRole.ROLE_CHECKBUTTON;
-const ROLE_RADIOBUTTON = Ci.nsIAccessibleRole.ROLE_RADIOBUTTON;
-const ROLE_COMBOBOX = Ci.nsIAccessibleRole.ROLE_COMBOBOX;
-const ROLE_PROGRESSBAR = Ci.nsIAccessibleRole.ROLE_PROGRESSBAR;
-const ROLE_BUTTONDROPDOWN = Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWN;
-const ROLE_BUTTONMENU = Ci.nsIAccessibleRole.ROLE_BUTTONMENU;
-const ROLE_CHECK_MENU_ITEM = Ci.nsIAccessibleRole.ROLE_CHECK_MENU_ITEM;
-const ROLE_PASSWORD_TEXT = Ci.nsIAccessibleRole.ROLE_PASSWORD_TEXT;
-const ROLE_RADIO_MENU_ITEM = Ci.nsIAccessibleRole.ROLE_RADIO_MENU_ITEM;
-const ROLE_TOGGLE_BUTTON = Ci.nsIAccessibleRole.ROLE_TOGGLE_BUTTON;
-const ROLE_KEY = Ci.nsIAccessibleRole.ROLE_KEY;
-const ROLE_ENTRY = Ci.nsIAccessibleRole.ROLE_ENTRY;
-const ROLE_LIST = Ci.nsIAccessibleRole.ROLE_LIST;
-const ROLE_DEFINITION_LIST = Ci.nsIAccessibleRole.ROLE_DEFINITION_LIST;
-const ROLE_LISTITEM = Ci.nsIAccessibleRole.ROLE_LISTITEM;
-const ROLE_BUTTONDROPDOWNGRID = Ci.nsIAccessibleRole.ROLE_BUTTONDROPDOWNGRID;
-const ROLE_LISTBOX = Ci.nsIAccessibleRole.ROLE_LISTBOX;
-const ROLE_OPTION = Ci.nsIAccessibleRole.ROLE_OPTION;
-const ROLE_SLIDER = Ci.nsIAccessibleRole.ROLE_SLIDER;
-const ROLE_HEADING = Ci.nsIAccessibleRole.ROLE_HEADING;
-const ROLE_HEADER = Ci.nsIAccessibleRole.ROLE_HEADER;
-const ROLE_TERM = Ci.nsIAccessibleRole.ROLE_TERM;
-const ROLE_SEPARATOR = Ci.nsIAccessibleRole.ROLE_SEPARATOR;
-const ROLE_TABLE = Ci.nsIAccessibleRole.ROLE_TABLE;
-const ROLE_INTERNAL_FRAME = Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME;
-const ROLE_PARAGRAPH = Ci.nsIAccessibleRole.ROLE_PARAGRAPH;
-const ROLE_SECTION = Ci.nsIAccessibleRole.ROLE_SECTION;
-const ROLE_LABEL = Ci.nsIAccessibleRole.ROLE_LABEL;
-
 this.EXPORTED_SYMBOLS = ['TraversalRules'];
 
 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
+  'resource://gre/modules/accessibility/Constants.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Filters',
+  'resource://gre/modules/accessibility/Constants.jsm');
 
 let gSkipEmptyImages = new PrefCache('accessibility.accessfu.skip_empty_images');
 
 function BaseTraversalRule(aRoles, aMatchFunc) {
   this._explicitMatchRoles = new Set(aRoles);
   this._matchRoles = aRoles;
-  if (aRoles.indexOf(ROLE_LABEL) < 0) {
-    this._matchRoles.push(ROLE_LABEL);
+  if (aRoles.indexOf(Roles.LABEL) < 0) {
+    this._matchRoles.push(Roles.LABEL);
   }
-  this._matchFunc = aMatchFunc || function (acc) { return FILTER_MATCH; };
+  this._matchFunc = aMatchFunc || function (acc) { return Filters.MATCH; };
 }
 
 BaseTraversalRule.prototype = {
     getMatchRoles: function BaseTraversalRule_getmatchRoles(aRules) {
       aRules.value = this._matchRoles;
       return aRules.value.length;
     },
 
     preFilter: Ci.nsIAccessibleTraversalRule.PREFILTER_DEFUNCT |
     Ci.nsIAccessibleTraversalRule.PREFILTER_INVISIBLE |
     Ci.nsIAccessibleTraversalRule.PREFILTER_ARIA_HIDDEN |
     Ci.nsIAccessibleTraversalRule.PREFILTER_TRANSPARENT,
 
     match: function BaseTraversalRule_match(aAccessible)
     {
       let role = aAccessible.role;
-      if (role == ROLE_INTERNAL_FRAME) {
+      if (role == Roles.INTERNAL_FRAME) {
         return (Utils.getMessageManager(aAccessible.DOMNode)) ?
-          FILTER_MATCH  | FILTER_IGNORE_SUBTREE : FILTER_IGNORE;
+          Filters.MATCH  | Filters.IGNORE_SUBTREE : Filters.IGNORE;
       }
 
       let matchResult = this._explicitMatchRoles.has(role) ?
-          this._matchFunc(aAccessible) : FILTER_IGNORE;
+          this._matchFunc(aAccessible) : Filters.IGNORE;
 
       // If we are on a label that nests a checkbox/radio we should land on it.
       // It is a bigger touch target, and it reduces clutter.
-      if (role == ROLE_LABEL && !(matchResult & FILTER_IGNORE_SUBTREE)) {
+      if (role == Roles.LABEL && !(matchResult & Filters.IGNORE_SUBTREE)) {
         let control = Utils.getEmbeddedControl(aAccessible);
         if (control && this._explicitMatchRoles.has(control.role)) {
-          matchResult = this._matchFunc(control) | FILTER_IGNORE_SUBTREE;
+          matchResult = this._matchFunc(control) | Filters.IGNORE_SUBTREE;
         }
       }
 
       return matchResult;
     },
 
     QueryInterface: XPCOMUtils.generateQI([Ci.nsIAccessibleTraversalRule])
 };
 
 var gSimpleTraversalRoles =
-  [ROLE_MENUITEM,
-   ROLE_LINK,
-   ROLE_PAGETAB,
-   ROLE_GRAPHIC,
-   ROLE_STATICTEXT,
-   ROLE_TEXT_LEAF,
-   ROLE_PUSHBUTTON,
-   ROLE_CHECKBUTTON,
-   ROLE_RADIOBUTTON,
-   ROLE_COMBOBOX,
-   ROLE_PROGRESSBAR,
-   ROLE_BUTTONDROPDOWN,
-   ROLE_BUTTONMENU,
-   ROLE_CHECK_MENU_ITEM,
-   ROLE_PASSWORD_TEXT,
-   ROLE_RADIO_MENU_ITEM,
-   ROLE_TOGGLE_BUTTON,
-   ROLE_ENTRY,
-   ROLE_KEY,
-   ROLE_HEADER,
-   ROLE_HEADING,
-   ROLE_SLIDER,
-   ROLE_SPINBUTTON,
-   ROLE_OPTION,
+  [Roles.MENUITEM,
+   Roles.LINK,
+   Roles.PAGETAB,
+   Roles.GRAPHIC,
+   Roles.STATICTEXT,
+   Roles.TEXT_LEAF,
+   Roles.PUSHBUTTON,
+   Roles.CHECKBUTTON,
+   Roles.RADIOBUTTON,
+   Roles.COMBOBOX,
+   Roles.PROGRESSBAR,
+   Roles.BUTTONDROPDOWN,
+   Roles.BUTTONMENU,
+   Roles.CHECK_MENU_ITEM,
+   Roles.PASSWORD_TEXT,
+   Roles.RADIO_MENU_ITEM,
+   Roles.TOGGLE_BUTTON,
+   Roles.ENTRY,
+   Roles.KEY,
+   Roles.HEADER,
+   Roles.HEADING,
+   Roles.SLIDER,
+   Roles.SPINBUTTON,
+   Roles.OPTION,
    // Used for traversing in to child OOP frames.
-   ROLE_INTERNAL_FRAME];
+   Roles.INTERNAL_FRAME];
 
 this.TraversalRules = {
   Simple: new BaseTraversalRule(
     gSimpleTraversalRoles,
     function Simple_match(aAccessible) {
       function hasZeroOrSingleChildDescendants () {
         for (let acc = aAccessible; acc.childCount > 0; acc = acc.firstChild) {
           if (acc.childCount > 1) {
             return false;
           }
         }
 
         return true;
       }
 
       switch (aAccessible.role) {
-      case ROLE_COMBOBOX:
+      case Roles.COMBOBOX:
         // We don't want to ignore the subtree because this is often
         // where the list box hangs out.
-        return FILTER_MATCH;
-      case ROLE_TEXT_LEAF:
+        return Filters.MATCH;
+      case Roles.TEXT_LEAF:
         {
           // Nameless text leaves are boring, skip them.
           let name = aAccessible.name;
           if (name && name.trim())
-            return FILTER_MATCH;
+            return Filters.MATCH;
           else
-            return FILTER_IGNORE;
+            return Filters.IGNORE;
         }
-      case ROLE_STATICTEXT:
+      case Roles.STATICTEXT:
         {
           let parent = aAccessible.parent;
           // Ignore prefix static text in list items. They are typically bullets or numbers.
           if (parent.childCount > 1 && aAccessible.indexInParent == 0 &&
-              parent.role == ROLE_LISTITEM)
-            return FILTER_IGNORE;
+              parent.role == Roles.LISTITEM)
+            return Filters.IGNORE;
 
-          return FILTER_MATCH;
+          return Filters.MATCH;
         }
-      case ROLE_GRAPHIC:
+      case Roles.GRAPHIC:
         return TraversalRules._shouldSkipImage(aAccessible);
-      case ROLE_LINK:
-      case ROLE_HEADER:
-      case ROLE_HEADING:
+      case Roles.LINK:
+      case Roles.HEADER:
+      case Roles.HEADING:
         return hasZeroOrSingleChildDescendants() ?
-          (FILTER_MATCH | FILTER_IGNORE_SUBTREE) : (FILTER_IGNORE);
+          (Filters.MATCH | Filters.IGNORE_SUBTREE) : (Filters.IGNORE);
       default:
         // Ignore the subtree, if there is one. So that we don't land on
         // the same content that was already presented by its parent.
-        return FILTER_MATCH |
-          FILTER_IGNORE_SUBTREE;
+        return Filters.MATCH |
+          Filters.IGNORE_SUBTREE;
       }
     }
   ),
 
   Anchor: new BaseTraversalRule(
-    [ROLE_LINK],
+    [Roles.LINK],
     function Anchor_match(aAccessible)
     {
       // We want to ignore links, only focus named anchors.
       let state = {};
       let extraState = {};
       aAccessible.getState(state, extraState);
       if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
-        return FILTER_IGNORE;
+        return Filters.IGNORE;
       } else {
-        return FILTER_MATCH;
+        return Filters.MATCH;
       }
     }),
 
   Button: new BaseTraversalRule(
-    [ROLE_PUSHBUTTON,
-     ROLE_SPINBUTTON,
-     ROLE_TOGGLE_BUTTON,
-     ROLE_BUTTONDROPDOWN,
-     ROLE_BUTTONDROPDOWNGRID]),
+    [Roles.PUSHBUTTON,
+     Roles.SPINBUTTON,
+     Roles.TOGGLE_BUTTON,
+     Roles.BUTTONDROPDOWN,
+     Roles.BUTTONDROPDOWNGRID]),
 
   Combobox: new BaseTraversalRule(
-    [ROLE_COMBOBOX,
-     ROLE_LISTBOX]),
+    [Roles.COMBOBOX,
+     Roles.LISTBOX]),
 
   Landmark: new BaseTraversalRule(
     [],
     function Landmark_match(aAccessible) {
-      return Utils.getLandmarkName(aAccessible) ? FILTER_MATCH :
-        FILTER_IGNORE;
+      return Utils.getLandmarkName(aAccessible) ? Filters.MATCH :
+        Filters.IGNORE;
     }
   ),
 
   Entry: new BaseTraversalRule(
-    [ROLE_ENTRY,
-     ROLE_PASSWORD_TEXT]),
+    [Roles.ENTRY,
+     Roles.PASSWORD_TEXT]),
 
   FormElement: new BaseTraversalRule(
-    [ROLE_PUSHBUTTON,
-     ROLE_SPINBUTTON,
-     ROLE_TOGGLE_BUTTON,
-     ROLE_BUTTONDROPDOWN,
-     ROLE_BUTTONDROPDOWNGRID,
-     ROLE_COMBOBOX,
-     ROLE_LISTBOX,
-     ROLE_ENTRY,
-     ROLE_PASSWORD_TEXT,
-     ROLE_PAGETAB,
-     ROLE_RADIOBUTTON,
-     ROLE_RADIO_MENU_ITEM,
-     ROLE_SLIDER,
-     ROLE_CHECKBUTTON,
-     ROLE_CHECK_MENU_ITEM]),
+    [Roles.PUSHBUTTON,
+     Roles.SPINBUTTON,
+     Roles.TOGGLE_BUTTON,
+     Roles.BUTTONDROPDOWN,
+     Roles.BUTTONDROPDOWNGRID,
+     Roles.COMBOBOX,
+     Roles.LISTBOX,
+     Roles.ENTRY,
+     Roles.PASSWORD_TEXT,
+     Roles.PAGETAB,
+     Roles.RADIOBUTTON,
+     Roles.RADIO_MENU_ITEM,
+     Roles.SLIDER,
+     Roles.CHECKBUTTON,
+     Roles.CHECK_MENU_ITEM]),
 
   Graphic: new BaseTraversalRule(
-    [ROLE_GRAPHIC],
+    [Roles.GRAPHIC],
     function Graphic_match(aAccessible) {
       return TraversalRules._shouldSkipImage(aAccessible);
     }),
 
   Heading: new BaseTraversalRule(
-    [ROLE_HEADING]),
+    [Roles.HEADING]),
 
   ListItem: new BaseTraversalRule(
-    [ROLE_LISTITEM,
-     ROLE_TERM]),
+    [Roles.LISTITEM,
+     Roles.TERM]),
 
   Link: new BaseTraversalRule(
-    [ROLE_LINK],
+    [Roles.LINK],
     function Link_match(aAccessible)
     {
       // We want to ignore anchors, only focus real links.
       let state = {};
       let extraState = {};
       aAccessible.getState(state, extraState);
       if (state.value & Ci.nsIAccessibleStates.STATE_LINKED) {
-        return FILTER_MATCH;
+        return Filters.MATCH;
       } else {
-        return FILTER_IGNORE;
+        return Filters.IGNORE;
       }
     }),
 
   List: new BaseTraversalRule(
-    [ROLE_LIST,
-     ROLE_DEFINITION_LIST]),
+    [Roles.LIST,
+     Roles.DEFINITION_LIST]),
 
   PageTab: new BaseTraversalRule(
-    [ROLE_PAGETAB]),
+    [Roles.PAGETAB]),
 
   Paragraph: new BaseTraversalRule(
-    [ROLE_PARAGRAPH,
-     ROLE_SECTION],
+    [Roles.PARAGRAPH,
+     Roles.SECTION],
     function Paragraph_match(aAccessible) {
       for (let child = aAccessible.firstChild; child; child = child.nextSibling) {
-        if (child.role === ROLE_TEXT_LEAF) {
-          return FILTER_MATCH | FILTER_IGNORE_SUBTREE;
+        if (child.role === Roles.TEXT_LEAF) {
+          return Filters.MATCH | Filters.IGNORE_SUBTREE;
         }
       }
 
-      return FILTER_IGNORE;
+      return Filters.IGNORE;
     }),
 
   RadioButton: new BaseTraversalRule(
-    [ROLE_RADIOBUTTON,
-     ROLE_RADIO_MENU_ITEM]),
+    [Roles.RADIOBUTTON,
+     Roles.RADIO_MENU_ITEM]),
 
   Separator: new BaseTraversalRule(
-    [ROLE_SEPARATOR]),
+    [Roles.SEPARATOR]),
 
   Table: new BaseTraversalRule(
-    [ROLE_TABLE]),
+    [Roles.TABLE]),
 
   Checkbox: new BaseTraversalRule(
-    [ROLE_CHECKBUTTON,
-     ROLE_CHECK_MENU_ITEM]),
+    [Roles.CHECKBUTTON,
+     Roles.CHECK_MENU_ITEM]),
 
   _shouldSkipImage: function _shouldSkipImage(aAccessible) {
     if (gSkipEmptyImages.value && aAccessible.name === '') {
-      return FILTER_IGNORE;
+      return Filters.IGNORE;
     }
-    return FILTER_MATCH;
+    return Filters.MATCH;
   }
 };
--- a/accessible/src/jsat/Utils.jsm
+++ b/accessible/src/jsat/Utils.jsm
@@ -3,29 +3,27 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
-const EVENT_STATE_CHANGE = Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE;
-
-const ROLE_CELL = Ci.nsIAccessibleRole.ROLE_CELL;
-const ROLE_COLUMNHEADER = Ci.nsIAccessibleRole.ROLE_COLUMNHEADER;
-const ROLE_ROWHEADER = Ci.nsIAccessibleRole.ROLE_ROWHEADER;
-
-const RELATION_LABEL_FOR = Ci.nsIAccessibleRelation.RELATION_LABEL_FOR;
-
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, 'Services',
   'resource://gre/modules/Services.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Rect',
   'resource://gre/modules/Geometry.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
+  'resource://gre/modules/accessibility/Constants.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Events',
+  'resource://gre/modules/accessibility/Constants.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Relations',
+  'resource://gre/modules/accessibility/Constants.jsm');
 
 this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache'];
 
 this.Utils = {
   _buildAppMap: {
     '{3c2e2abc-06d4-11e1-ac3b-374f68613e61}': 'b2g',
     '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}': 'browser',
     '{aa3c5121-dab2-40e2-81ca-7ea25febc110}': 'mobile/android',
@@ -292,17 +290,17 @@ this.Utils = {
     }
 
     // Looking up a role that would match a landmark.
     return this.matchAttributeValue(roles, landmarks);
   },
 
   getEmbeddedControl: function getEmbeddedControl(aLabel) {
     if (aLabel) {
-      let relation = aLabel.getRelationByType(RELATION_LABEL_FOR);
+      let relation = aLabel.getRelationByType(Relations.LABEL_FOR);
       for (let i = 0; i < relation.targetsCount; i++) {
         let target = relation.getTarget(i);
         if (target.parent === aLabel) {
           return target;
         }
       }
     }
 
@@ -394,17 +392,17 @@ this.Logger = {
     } catch (x) {
     }
 
     return str;
   },
 
   eventToString: function eventToString(aEvent) {
     let str = Utils.AccRetrieval.getStringEventType(aEvent.eventType);
-    if (aEvent.eventType == EVENT_STATE_CHANGE) {
+    if (aEvent.eventType == Events.STATE_CHANGE) {
       let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
       let stateStrings = event.isExtraState ?
         Utils.AccRetrieval.getStringStates(0, event.state) :
         Utils.AccRetrieval.getStringStates(event.state, 0);
       str += ' (' + stateStrings.item(0) + ')';
     }
 
     return str;
@@ -628,17 +626,17 @@ PivotContext.prototype = {
       return this._cells.get(domNode);
     }
 
     let cellInfo = {};
     let getAccessibleCell = function getAccessibleCell(aAccessible) {
       if (!aAccessible) {
         return null;
       }
-      if ([ROLE_CELL, ROLE_COLUMNHEADER, ROLE_ROWHEADER].indexOf(
+      if ([Roles.CELL, Roles.COLUMNHEADER, Roles.ROWHEADER].indexOf(
         aAccessible.role) < 0) {
           return null;
       }
       try {
         return aAccessible.QueryInterface(Ci.nsIAccessibleTableCell);
       } catch (x) {
         Logger.logException(x);
         return null;
@@ -689,22 +687,22 @@ PivotContext.prototype = {
 
     cellInfo.rowExtent = cellInfo.current.rowExtent;
     cellInfo.columnExtent = cellInfo.current.columnExtent;
     cellInfo.columnIndex = cellInfo.current.columnIndex;
     cellInfo.rowIndex = cellInfo.current.rowIndex;
 
     cellInfo.columnHeaders = [];
     if (cellInfo.columnChanged && cellInfo.current.role !==
-      ROLE_COLUMNHEADER) {
+      Roles.COLUMNHEADER) {
       cellInfo.columnHeaders = [headers for (headers of getHeaders(
         cellInfo.current.columnHeaderCells))];
     }
     cellInfo.rowHeaders = [];
-    if (cellInfo.rowChanged && cellInfo.current.role === ROLE_CELL) {
+    if (cellInfo.rowChanged && cellInfo.current.role === Roles.CELL) {
       cellInfo.rowHeaders = [headers for (headers of getHeaders(
         cellInfo.current.rowHeaderCells))];
     }
 
     this._cells.set(domNode, cellInfo);
     return cellInfo;
   },
 
--- a/accessible/src/jsat/content-script.js
+++ b/accessible/src/jsat/content-script.js
@@ -1,18 +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/. */
 
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 
-const ROLE_ENTRY = Ci.nsIAccessibleRole.ROLE_ENTRY;
-const ROLE_INTERNAL_FRAME = Ci.nsIAccessibleRole.ROLE_INTERNAL_FRAME;
-
 const MOVEMENT_GRANULARITY_CHARACTER = 1;
 const MOVEMENT_GRANULARITY_WORD = 2;
 const MOVEMENT_GRANULARITY_PARAGRAPH = 8;
 
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Presentation',
@@ -20,16 +17,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, 'TraversalRules',
   'resource://gre/modules/accessibility/TraversalRules.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
   'resource://gre/modules/accessibility/Utils.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'EventManager',
   'resource://gre/modules/accessibility/EventManager.jsm');
 XPCOMUtils.defineLazyModuleGetter(this, 'ObjectWrapper',
   'resource://gre/modules/ObjectWrapper.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'Roles',
+  'resource://gre/modules/accessibility/Constants.jsm');
 
 Logger.debug('content-script.js');
 
 let eventManager = null;
 
 function moveCursor(aMessage) {
   if (Logger.logLevel >= Logger.DEBUG) {
     Logger.debug(aMessage.name, JSON.stringify(aMessage.json, null, ' '));
@@ -132,17 +131,17 @@ function forwardToParent(aMessage) {
   let newJSON = JSON.parse(JSON.stringify(aMessage.json));
   newJSON.origin = 'child';
   sendAsyncMessage(aMessage.name, newJSON);
 }
 
 function forwardToChild(aMessage, aListener, aVCPosition) {
   let acc = aVCPosition || Utils.getVirtualCursor(content.document).position;
 
-  if (!Utils.isAliveAndVisible(acc) || acc.role != ROLE_INTERNAL_FRAME) {
+  if (!Utils.isAliveAndVisible(acc) || acc.role != Roles.INTERNAL_FRAME) {
     return false;
   }
 
   if (Logger.logLevel >= Logger.DEBUG) {
     Logger.debug('forwardToChild', Logger.accessibleToString(acc),
                  aMessage.name, JSON.stringify(aMessage.json, null, '  '));
   }
 
@@ -160,17 +159,17 @@ function forwardToChild(aMessage, aListe
   mm.sendAsyncMessage(aMessage.name, newJSON);
   return true;
 }
 
 function activateCurrent(aMessage) {
   Logger.debug('activateCurrent');
   function activateAccessible(aAccessible) {
     if (aMessage.json.activateIfKey &&
-        aAccessible.role != Ci.nsIAccessibleRole.ROLE_KEY) {
+        aAccessible.role != Roles.KEY) {
       // Only activate keys, don't do anything on other objects.
       return;
     }
 
     if (aAccessible.actionCount > 0) {
       aAccessible.doAction(0);
     } else {
       let control = Utils.getEmbeddedControl(aAccessible);
@@ -214,17 +213,17 @@ function activateCurrent(aMessage) {
     if (aOffset >= 0 && aOffset <= accText.characterCount) {
       accText.caretOffset = aOffset;
     }
 
     presentCaretChange(text, oldOffset, accText.caretOffset);
   }
 
   let focusedAcc = Utils.AccRetrieval.getAccessibleFor(content.document.activeElement);
-  if (focusedAcc && focusedAcc.role === ROLE_ENTRY) {
+  if (focusedAcc && focusedAcc.role === Roles.ENTRY) {
     moveCaretTo(focusedAcc, aMessage.json.offset);
     return;
   }
 
   let position = Utils.getVirtualCursor(content.document).position;
   if (!forwardToChild(aMessage, activateCurrent, position)) {
     activateAccessible(position);
   }
--- a/accessible/src/jsat/moz.build
+++ b/accessible/src/jsat/moz.build
@@ -1,5 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
+
+JS_MODULES_PATH = 'modules/accessibility'
+
+EXTRA_JS_MODULES += [
+    'AccessFu.jsm',
+    'Constants.jsm',
+    'EventManager.jsm',
+    'OutputGenerator.jsm',
+    'Presentation.jsm',
+    'TouchAdapter.jsm',
+    'TraversalRules.jsm',
+    'Utils.jsm'
+]
--- a/accessible/src/windows/ia2/ia2AccessibleValue.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleValue.cpp
@@ -8,16 +8,18 @@
 #include "ia2AccessibleValue.h"
 
 #include "AccessibleValue_i.c"
 
 #include "AccessibleWrap.h"
 #include "Accessible-inl.h"
 #include "IUnknownImpl.h"
 
+#include "mozilla/FloatingPoint.h"
+
 using namespace mozilla::a11y;
 
 // IUnknown
 
 STDMETHODIMP
 ia2AccessibleValue::QueryInterface(REFIID iid, void** ppv)
 {
   if (!ppv)
@@ -50,20 +52,19 @@ ia2AccessibleValue::get_currentValue(VAR
     return E_INVALIDARG;
 
   VariantInit(aCurrentValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  double currentValue = 0;
-  nsresult rv = valueAcc->GetCurrentValue(&currentValue);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+  double currentValue = valueAcc->CurValue();
+  if (IsNaN(currentValue))
+    return S_FALSE;
 
   aCurrentValue->vt = VT_R8;
   aCurrentValue->dblVal = currentValue;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -74,18 +75,17 @@ ia2AccessibleValue::setCurrentValue(VARI
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   if (aValue.vt != VT_R8)
     return E_INVALIDARG;
 
-  nsresult rv = valueAcc->SetCurrentValue(aValue.dblVal);
-  return GetHRESULT(rv);
+  return valueAcc->SetCurValue(aValue.dblVal) ? S_OK : E_FAIL;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2AccessibleValue::get_maximumValue(VARIANT* aMaximumValue)
 {
   A11Y_TRYBLOCK_BEGIN
@@ -94,20 +94,19 @@ ia2AccessibleValue::get_maximumValue(VAR
     return E_INVALIDARG;
 
   VariantInit(aMaximumValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  double maximumValue = 0;
-  nsresult rv = valueAcc->GetMaximumValue(&maximumValue);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+  double maximumValue = valueAcc->MaxValue();
+  if (IsNaN(maximumValue))
+    return S_FALSE;
 
   aMaximumValue->vt = VT_R8;
   aMaximumValue->dblVal = maximumValue;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -120,20 +119,19 @@ ia2AccessibleValue::get_minimumValue(VAR
     return E_INVALIDARG;
 
   VariantInit(aMinimumValue);
 
   AccessibleWrap* valueAcc = static_cast<AccessibleWrap*>(this);
   if (valueAcc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  double minimumValue = 0;
-  nsresult rv = valueAcc->GetMinimumValue(&minimumValue);
-  if (NS_FAILED(rv))
-    return GetHRESULT(rv);
+  double minimumValue = valueAcc->MinValue();
+  if (IsNaN(minimumValue))
+    return S_FALSE;
 
   aMinimumValue->vt = VT_R8;
   aMinimumValue->dblVal = minimumValue;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
--- a/accessible/src/xpcom/moz.build
+++ b/accessible/src/xpcom/moz.build
@@ -2,24 +2,26 @@
 # vim: set filetype=python:
 # 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/.
 
 EXPORTS += [
     'xpcAccessibleHyperText.h',
     'xpcAccessibleSelectable.h',
+    'xpcAccessibleValue.h',
 ]
 
 UNIFIED_SOURCES += [
     'nsAccessibleRelation.cpp',
     'xpcAccessibleHyperText.cpp',
     'xpcAccessibleSelectable.cpp',
     'xpcAccessibleTable.cpp',
     'xpcAccessibleTableCell.cpp',
+    'xpcAccessibleValue.cpp',
 ]
 
 GENERATED_SOURCES += [
     'xpcAccEvents.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '../base',
new file mode 100644
--- /dev/null
+++ b/accessible/src/xpcom/xpcAccessibleValue.cpp
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "xpcAccessibleValue.h"
+#include "Accessible.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMaximumValue(double* aValue)
+{
+  NS_ENSURE_ARG_POINTER(aValue);
+  *aValue = 0;
+
+  Accessible* acc = static_cast<Accessible*>(this);
+  if (acc->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  double value = acc->MaxValue();
+  if (!IsNaN(value))
+    *aValue = value;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMinimumValue(double* aValue)
+{
+  NS_ENSURE_ARG_POINTER(aValue);
+  *aValue = 0;
+
+  Accessible* acc = static_cast<Accessible*>(this);
+  if (acc->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  double value = acc->MinValue();
+  if (!IsNaN(value))
+    *aValue = value;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetCurrentValue(double* aValue)
+{
+  NS_ENSURE_ARG_POINTER(aValue);
+  *aValue = 0;
+
+  Accessible* acc = static_cast<Accessible*>(this);
+  if (acc->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  double value = acc->CurValue();
+  if (!IsNaN(value))
+    *aValue = value;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::SetCurrentValue(double aValue)
+{
+  Accessible* acc = static_cast<Accessible*>(this);
+  if (acc->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  acc->SetCurValue(aValue);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMinimumIncrement(double* aValue)
+{
+  NS_ENSURE_ARG_POINTER(aValue);
+  *aValue = 0;
+
+  Accessible* acc = static_cast<Accessible*>(this);
+  if (acc->IsDefunct())
+    return NS_ERROR_FAILURE;
+
+  double value = acc->Step();
+  if (!IsNaN(value))
+    *aValue = value;
+
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/xpcom/xpcAccessibleValue.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleValue_h_
+#define mozilla_a11y_xpcAccessibleValue_h_
+
+#include "nsIAccessibleValue.h"
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleValue : public nsIAccessibleValue
+{
+public:
+  NS_IMETHOD GetMaximumValue(double* aValue) MOZ_FINAL MOZ_OVERRIDE;
+  NS_IMETHOD GetMinimumValue(double* aValue) MOZ_FINAL MOZ_OVERRIDE;
+  NS_IMETHOD GetCurrentValue(double* aValue) MOZ_FINAL MOZ_OVERRIDE;
+  NS_IMETHOD SetCurrentValue(double aValue) MOZ_FINAL MOZ_OVERRIDE;
+  NS_IMETHOD GetMinimumIncrement(double* aMinIncrement) MOZ_FINAL MOZ_OVERRIDE;
+
+private:
+  xpcAccessibleValue() { }
+  friend class Accessible;
+
+  xpcAccessibleValue(const xpcAccessibleValue&) MOZ_DELETE;
+  xpcAccessibleValue& operator =(const xpcAccessibleValue&) MOZ_DELETE;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/src/xul/XULSliderAccessible.cpp
+++ b/accessible/src/xul/XULSliderAccessible.cpp
@@ -6,36 +6,31 @@
 #include "XULSliderAccessible.h"
 
 #include "nsAccessibilityService.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsIFrame.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/FloatingPoint.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULSliderAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULSliderAccessible::
   XULSliderAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
 {
   mStateFlags |= eHasNumericValue;
 }
 
-// nsISupports
-
-NS_IMPL_ISUPPORTS_INHERITED1(XULSliderAccessible,
-                             AccessibleWrap,
-                             nsIAccessibleValue)
-
 // Accessible
 
 role
 XULSliderAccessible::NativeRole()
 {
   return roles::SLIDER;
 }
 
@@ -94,74 +89,49 @@ XULSliderAccessible::DoAction(uint8_t aI
 
   nsIContent* sliderElm = GetSliderElement();
   if (sliderElm)
     DoCommand(sliderElm);
 
   return NS_OK;
 }
 
-// nsIAccessibleValue
-
-NS_IMETHODIMP
-XULSliderAccessible::GetMaximumValue(double* aValue)
+double
+XULSliderAccessible::MaxValue() const
 {
-  nsresult rv = AccessibleWrap::GetMaximumValue(aValue);
-
-  // ARIA redefined maximum value.
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  return GetSliderAttr(nsGkAtoms::maxpos, aValue);
+  double value = AccessibleWrap::MaxValue();
+  return IsNaN(value) ? GetSliderAttr(nsGkAtoms::maxpos) : value;
 }
 
-NS_IMETHODIMP
-XULSliderAccessible::GetMinimumValue(double* aValue)
+double
+XULSliderAccessible::MinValue() const
 {
-  nsresult rv = AccessibleWrap::GetMinimumValue(aValue);
-
-  // ARIA redefined minmum value.
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  return GetSliderAttr(nsGkAtoms::minpos, aValue);
+  double value = AccessibleWrap::MinValue();
+  return IsNaN(value) ? GetSliderAttr(nsGkAtoms::minpos) : value;
 }
 
-NS_IMETHODIMP
-XULSliderAccessible::GetMinimumIncrement(double* aValue)
+double
+XULSliderAccessible::Step() const
 {
-  nsresult rv = AccessibleWrap::GetMinimumIncrement(aValue);
-
-  // ARIA redefined minimum increment value.
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  return GetSliderAttr(nsGkAtoms::increment, aValue);
+  double value = AccessibleWrap::Step();
+  return IsNaN(value) ? GetSliderAttr(nsGkAtoms::increment) : value;
 }
 
-NS_IMETHODIMP
-XULSliderAccessible::GetCurrentValue(double* aValue)
+double
+XULSliderAccessible::CurValue() const
 {
-  nsresult rv = AccessibleWrap::GetCurrentValue(aValue);
-
-  // ARIA redefined current value.
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
-
-  return GetSliderAttr(nsGkAtoms::curpos, aValue);
+  double value = AccessibleWrap::CurValue();
+  return IsNaN(value) ? GetSliderAttr(nsGkAtoms::curpos) : value;
 }
 
-NS_IMETHODIMP
-XULSliderAccessible::SetCurrentValue(double aValue)
+bool
+XULSliderAccessible::SetCurValue(double aValue)
 {
-  nsresult rv = AccessibleWrap::SetCurrentValue(aValue);
-
-  // ARIA redefined current value.
-  if (rv != NS_OK_NO_ARIA_VALUE)
-    return rv;
+  if (AccessibleWrap::SetCurValue(aValue))
+    return true;
 
   return SetSliderAttr(nsGkAtoms::curpos, aValue);
 }
 
 bool
 XULSliderAccessible::CanHaveAnonChildren()
 {
   // Do not allow anonymous xul:slider be accessible.
@@ -179,17 +149,17 @@ XULSliderAccessible::GetSliderElement() 
       GetAnonymousElementByAttribute(mContent, nsGkAtoms::anonid,
                                      NS_LITERAL_STRING("slider"));
   }
 
   return mSliderNode;
 }
 
 nsresult
-XULSliderAccessible::GetSliderAttr(nsIAtom* aName, nsAString& aValue)
+XULSliderAccessible::GetSliderAttr(nsIAtom* aName, nsAString& aValue) const
 {
   aValue.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   nsIContent* sliderElm = GetSliderElement();
   if (sliderElm)
@@ -206,45 +176,36 @@ XULSliderAccessible::SetSliderAttr(nsIAt
 
   nsIContent* sliderElm = GetSliderElement();
   if (sliderElm)
     sliderElm->SetAttr(kNameSpaceID_None, aName, aValue, true);
 
   return NS_OK;
 }
 
-nsresult
-XULSliderAccessible::GetSliderAttr(nsIAtom* aName, double* aValue)
+double
+XULSliderAccessible::GetSliderAttr(nsIAtom* aName) const
 {
-  NS_ENSURE_ARG_POINTER(aValue);
-  *aValue = 0;
-
   nsAutoString attrValue;
   nsresult rv = GetSliderAttr(aName, attrValue);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Return zero value if there is no attribute or its value is empty.
-  if (attrValue.IsEmpty())
-    return NS_OK;
+  if (NS_FAILED(rv))
+    return UnspecifiedNaN();
 
   nsresult error = NS_OK;
   double value = attrValue.ToDouble(&error);
-  if (NS_SUCCEEDED(error))
-    *aValue = value;
-
-  return NS_OK;
+  return NS_FAILED(error) ? UnspecifiedNaN() : value;
 }
 
-nsresult
+bool
 XULSliderAccessible::SetSliderAttr(nsIAtom* aName, double aValue)
 {
   nsAutoString value;
   value.AppendFloat(aValue);
 
-  return SetSliderAttr(aName, value);
+  return NS_SUCCEEDED(SetSliderAttr(aName, value));
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULThumbAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULThumbAccessible::
--- a/accessible/src/xul/XULSliderAccessible.h
+++ b/accessible/src/xul/XULSliderAccessible.h
@@ -16,47 +16,48 @@ namespace a11y {
 /**
  * Used for XUL slider and scale elements.
  */
 class XULSliderAccessible : public AccessibleWrap
 {
 public:
   XULSliderAccessible(nsIContent* aContent, DocAccessible* aDoc);
 
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
   // nsIAccessible
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
   NS_IMETHOD DoAction(uint8_t aIndex);
 
-  // nsIAccessibleValue
-  NS_DECL_NSIACCESSIBLEVALUE
-
   // Accessible
   virtual void Value(nsString& aValue);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeInteractiveState() const;
   virtual bool NativelyUnavailable() const;
   virtual bool CanHaveAnonChildren();
 
+  // Value
+  virtual double MaxValue() const MOZ_OVERRIDE;
+  virtual double MinValue() const MOZ_OVERRIDE;
+  virtual double CurValue() const MOZ_OVERRIDE;
+  virtual double Step() const MOZ_OVERRIDE;
+  virtual bool SetCurValue(double aValue) MOZ_OVERRIDE;
+
   // ActionAccessible
   virtual uint8_t ActionCount();
 
 protected:
   /**
    * Return anonymous slider element.
    */
   nsIContent* GetSliderElement() const;
 
-  nsresult GetSliderAttr(nsIAtom *aName, nsAString& aValue);
+  nsresult GetSliderAttr(nsIAtom *aName, nsAString& aValue) const;
   nsresult SetSliderAttr(nsIAtom *aName, const nsAString& aValue);
 
-  nsresult GetSliderAttr(nsIAtom *aName, double *aValue);
-  nsresult SetSliderAttr(nsIAtom *aName, double aValue);
+  double GetSliderAttr(nsIAtom *aName) const;
+  bool SetSliderAttr(nsIAtom *aName, double aValue);
 
 private:
   mutable nsCOMPtr<nsIContent> mSliderNode;
 };
 
 
 /**
  * Used for slider's thumb element.
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -87,16 +87,17 @@ var AccessFuTest = {
 
   waitForExplicitFinish: function AccessFuTest_waitForExplicitFinish() {
     this._waitForExplicitFinish = true;
   },
 
   finish: function AccessFuTest_finish() {
     // Disable the console service logging.
     Logger.test = false;
+    Logger.logLevel = Logger.INFO;
     AccessFu.doneCallback = function doneCallback() {
       // This is being called once AccessFu has been shut down.
       // Detach AccessFu from everything it attached itself to.
       AccessFu.detach();
       // and finish the test run.
       SimpleTest.finish();
     };
     // Tear down accessibility and make AccessFu stop.
@@ -131,16 +132,17 @@ var AccessFuTest = {
     // Start AccessFu and put it in stand-by.
     Components.utils.import("resource://gre/modules/accessibility/AccessFu.jsm");
 
     AccessFu.attach(getMainChromeWindow(window));
 
     AccessFu.readyCallback = function readyCallback() {
       // Enable logging to the console service.
       Logger.test = true;
+      Logger.logLevel = Logger.DEBUG;
       // This is being called once accessibility has been turned on.
 
       if (AccessFuTest._waitForExplicitFinish) {
         // Run all test functions asynchronously.
         AccessFuTest.nextTest();
       } else {
         // Run all test functions synchronously.
         [testFunc() for (testFunc of gTestFuncs)];
--- a/accessible/tests/mochitest/value/test_progress.html
+++ b/accessible/tests/mochitest/value/test_progress.html
@@ -16,17 +16,17 @@
 
   <script type="application/javascript"
           src="chrome://mochikit/content/chrome-harness.js"></script>
 
   <script type="application/javascript">
     function doTest()
     {
       // HTML5 progress element tests
-      testValue("pr_indeterminate", "0%", 0, 0, 1, 0);
+      testValue("pr_indeterminate", "", 0, 0, 1, 0);
       testValue("pr_zero", "0%", 0, 0, 1, 0);
       testValue("pr_zeropointfive", "50%", 0.5, 0, 1, 0);
       testValue("pr_one", "100%", 1, 0, 1, 0);
       testValue("pr_42", "100%", 42, 0, 1, 0);
       testValue("pr_21", "50%", 21, 0, 42, 0);
 
       SimpleTest.finish();
     }
--- a/accessible/tests/mochitest/value/test_progress.xul
+++ b/accessible/tests/mochitest/value/test_progress.xul
@@ -16,17 +16,17 @@
 
   <script type="application/javascript">
   <![CDATA[
     function doTest()
     {
       // progressmeter
       testValue("pm1", "50%", 50, 0, 100, 0);
       testValue("pm2", "50%", 500, 0, 1000, 0);
-      testValue("pm3", "0%", 0, 0, 100, 0);
+      testValue("pm3", "", 0, 0, 100, 0);
 
       // scale
       testValue("sc1", "500", 500, 0, 1000, 10);
       testValue("sc2", "", 0, 0, 0, 0);
 
       // aria progressbar
       testValue("ariapb1", "500", 500, 0, 1000, 0);
       testValue("ariapb2", "", 0, 0, 0, 0);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -6333,24 +6333,31 @@ var gIdentityHandler = {
                                 .QueryInterface(Components.interfaces.nsISSLStatusProvider)
                                 .SSLStatus;
     this._lastStatus = currentStatus;
     this._lastUri = uri;
 
     let nsIWebProgressListener = Ci.nsIWebProgressListener;
 
     // For some URIs like data: we can't get a host and so can't do
-    // anything useful here. Chrome URIs however get special treatment.
+    // anything useful here.
     let unknown = false;
     try {
       uri.host;
     } catch (e) { unknown = true; }
 
-    if ((uri.scheme == "chrome" || uri.scheme == "about") &&
-        uri.spec !== "about:blank") {
+    // Chrome URIs however get special treatment. Some chrome URIs are
+    // whitelisted to provide a positive security signal to the user.
+    let chromeWhitelist = ["about:addons", "about:app-manager", "about:config",
+                           "about:crashes", "about:healthreport", "about:home",
+                           "about:newaddon", "about:permissions", "about:preferences",
+                           "about:privatebrowsing", "about:sessionstore",
+                           "about:support", "about:welcomeback"];
+    let lowercaseSpec = uri.spec.toLowerCase();
+    if (chromeWhitelist.some(function(whitelistedSpec) lowercaseSpec.startsWith(whitelistedSpec))) {
       this.setMode(this.IDENTITY_MODE_CHROMEUI);
     } else if (unknown) {
       this.setMode(this.IDENTITY_MODE_UNKNOWN);
     } else if (state & nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) {
       this.setMode(this.IDENTITY_MODE_IDENTIFIED);
     } else if (state & nsIWebProgressListener.STATE_IS_SECURE) {
       this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED);
     } else if (state & nsIWebProgressListener.STATE_IS_BROKEN) {
--- a/browser/base/content/test/general/browser_bug590206.js
+++ b/browser/base/content/test/general/browser_bug590206.js
@@ -56,24 +56,26 @@ function test_blank() {
 
     runNextTest();
   });
 },
 
 function test_chrome() {
   let oldTab = gBrowser.selectedTab;
 
+  // Since users aren't likely to type in full chrome URLs, we won't show
+  // the positive security indicator on it, but we will show it on about:addons.
   loadNewTab("chrome://mozapps/content/extensions/extensions.xul", function(aNewTab) {
-    is(getIdentityMode(), "chromeUI", "Identity should be chrome");
+    is(getIdentityMode(), "unknownIdentity", "Identity should be unknown");
 
     gBrowser.selectedTab = oldTab;
     is(getIdentityMode(), "unknownIdentity", "Identity should be unknown");
 
     gBrowser.selectedTab = aNewTab;
-    is(getIdentityMode(), "chromeUI", "Identity should be chrome");
+    is(getIdentityMode(), "unknownIdentity", "Identity should be unknown");
 
     gBrowser.removeTab(aNewTab);
 
     runNextTest();
   });
 },
 
 function test_https() {
--- a/browser/components/customizableui/src/CustomizableUI.jsm
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -354,16 +354,22 @@ let CustomizableUIInternal = {
 
     if (!container) {
       throw new Error("Expected area " + aArea
                       + " to have a customizationTarget attribute.");
     }
 
     this.beginBatchUpdate();
 
+    // Restore nav-bar visibility since it may have been hidden
+    // through a migration path (bug 938980) or an add-on.
+    if (aArea == CustomizableUI.AREA_NAVBAR) {
+      aAreaNode.collapsed = false;
+    }
+
     let currentNode = container.firstChild;
     let placementsToRemove = new Set();
     for (let id of aPlacements) {
       while (currentNode && currentNode.getAttribute("skipintoolbarset") == "true") {
         currentNode = currentNode.nextSibling;
       }
 
       if (currentNode && currentNode.id == id) {
@@ -1073,29 +1079,33 @@ let CustomizableUIInternal = {
     while (panel && panel.localName != "panel")
       panel = panel.parentNode;
     return panel;
   },
 
   /*
    * If people put things in the panel which need more than single-click interaction,
    * we don't want to close it. Right now we check for text inputs and menu buttons.
-   * Anything else we should take care of?
+   * We also check for being outside of any toolbaritem/toolbarbutton, ie on a blank
+   * part of the menu.
    */
   _isOnInteractiveElement: function(aEvent) {
     let target = aEvent.originalTarget;
-    let panel = aEvent.currentTarget;
+    let panel = this._getPanelForNode(aEvent.currentTarget);
     let inInput = false;
     let inMenu = false;
-    while (!inInput && !inMenu && target != aEvent.currentTarget) {
-      inInput = target.localName == "input";
+    let inItem = false;
+    while (!inInput && !inMenu && !inItem && target != panel) {
+      let tagName = target.localName;
+      inInput = tagName == "input";
       inMenu = target.type == "menu";
+      inItem = tagName == "toolbaritem" || tagName == "toolbarbutton";
       target = target.parentNode;
     }
-    return inMenu || inInput;
+    return inMenu || inInput || !inItem;
   },
 
   hidePanelForNode: function(aNode) {
     let panel = this._getPanelForNode(aNode);
     if (panel) {
       panel.hidePopup();
     }
   },
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -30,9 +30,10 @@ skip-if = true
 [browser_918049_skipintoolbarset_dnd.js]
 [browser_923857_customize_mode_event_wrapping_during_reset.js]
 [browser_927717_customize_drag_empty_toolbar.js]
 
 [browser_934113_menubar_removable.js]
 # Because this test is about the menubar, it can't be run on mac
 skip-if = os == "mac"
 
+[browser_938980_navbar_collapsed.js]
 [browser_panel_toggle.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/customizableui/test/browser_938980_navbar_collapsed.js
@@ -0,0 +1,26 @@
+/* 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/. */
+
+let gTests = [
+  {
+    desc: "Customization reset should restore visibility to default-visible toolbars.",
+    setup: null,
+    run: function() {
+      let navbar = document.getElementById("nav-bar");
+      is(navbar.collapsed, false, "Test should start with navbar visible");
+      navbar.collapsed = true;
+      is(navbar.collapsed, true, "navbar should be hidden now");
+
+      yield resetCustomization();
+
+      is(navbar.collapsed, false, "Customization reset should restore visibility to the navbar");
+    },
+    teardown: null
+  },
+];
+
+function test() {
+  waitForExplicitFinish();
+  runTests(gTests);
+}
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -544,17 +544,17 @@ nsBrowserContentHandler.prototype = {
     if (!gFirstWindow) {
       gFirstWindow = true;
       if (PrivateBrowsingUtils.isInTemporaryAutoStartMode) {
         return "about:privatebrowsing";
       }
     }
 
     var overridePage = "";
-    var haveUpdateSession = false;
+    var willRestoreSession = false;
     try {
       // Read the old value of homepage_override.mstone before
       // needHomepageOverride updates it, so that we can later add it to the
       // URL if we do end up showing an overridePage. This makes it possible
       // to have the overridePage's content vary depending on the version we're
       // upgrading from.
       let old_mstone = "unknown";
       try {
@@ -563,21 +563,25 @@ nsBrowserContentHandler.prototype = {
       let override = needHomepageOverride(prefb);
       if (override != OVERRIDE_NONE) {
         switch (override) {
           case OVERRIDE_NEW_PROFILE:
             // New profile.
             overridePage = Services.urlFormatter.formatURLPref("startup.homepage_welcome_url");
             break;
           case OVERRIDE_NEW_MSTONE:
-            // Check whether we have a session to restore. If we do, we assume
-            // that this is an "update" session.
+            // Check whether we will restore a session. If we will, we assume
+            // that this is an "update" session. This does not take crashes
+            // into account because that requires waiting for the session file
+            // to be read. If a crash occurs after updating, before restarting,
+            // we may open the startPage in addition to restoring the session.
             var ss = Components.classes["@mozilla.org/browser/sessionstartup;1"]
                                .getService(Components.interfaces.nsISessionStartup);
-            haveUpdateSession = ss.doRestore();
+            willRestoreSession = ss.isAutomaticRestoreEnabled();
+
             overridePage = Services.urlFormatter.formatURLPref("startup.homepage_override_url");
             if (prefb.prefHasUserValue("app.update.postupdate"))
               overridePage = getPostUpdateOverridePage(overridePage);
 
             overridePage = overridePage.replace("%OLD_VERSION%", old_mstone);
             break;
         }
       }
@@ -595,17 +599,17 @@ nsBrowserContentHandler.prototype = {
     } catch (e) {
       Components.utils.reportError(e);
     }
 
     if (startPage == "about:blank")
       startPage = "";
 
     // Only show the startPage if we're not restoring an update session.
-    if (overridePage && startPage && !haveUpdateSession)
+    if (overridePage && startPage && !willRestoreSession)
       return overridePage + "|" + startPage;
 
     return overridePage || startPage || "about:blank";
   },
 
   get startPage() {
     var uri = Services.prefs.getComplexValue("browser.startup.homepage",
                                              nsIPrefLocalizedString).data;
--- a/browser/components/sessionstore/nsISessionStartup.idl
+++ b/browser/components/sessionstore/nsISessionStartup.idl
@@ -5,36 +5,42 @@
 #include "nsISupports.idl"
 
 /**
  * nsISessionStore keeps track of the current browsing state - i.e.
  * tab history, cookies, scroll state, form data, POSTDATA and window features
  * - and allows to restore everything into one window.
  */
 
-[scriptable, uuid(51f4b9f0-f3d2-11e2-bb62-2c24dd830245)]
+[scriptable, uuid(6c79d4c1-f071-4c5c-a7fb-676adb144584)]
 interface nsISessionStartup: nsISupports
 {
   /**
    * Return a promise that is resolved once initialization
    * is complete.
    */
   readonly attribute jsval onceInitialized;
 
   // Get session state
   readonly attribute jsval state;
 
   /**
-   * Determines whether there is a pending session restore and makes sure that
-   * we're initialized before returning. If we're not yet this will read the
-   * session file synchronously.
+   * Determines whether there is a pending session restore. Should only be
+   * called after initialization has completed.
    */
   boolean doRestore();
 
   /**
+   * Determines whether automatic session restoration is enabled for this
+   * launch of the browser. This does not include crash restoration, and will
+   * return false if restoration will only be caused by a crash.
+   */
+  boolean isAutomaticRestoreEnabled();
+
+  /**
    * Returns whether we will restore a session that ends up replacing the
    * homepage. The browser uses this to not start loading the homepage if
    * we're going to stop its load anyway shortly after.
    *
    * This is meant to be an optimization for the average case that loading the
    * session file finishes before we may want to start loading the default
    * homepage. Should this be called before the session file has been read it
    * will just return false.
--- a/browser/components/sessionstore/src/SessionFile.jsm
+++ b/browser/components/sessionstore/src/SessionFile.jsm
@@ -33,44 +33,29 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/osfile/_PromiseWorker.jsm", this);
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/AsyncShutdown.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
   "resource://gre/modules/TelemetryStopwatch.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-  "resource://gre/modules/NetUtil.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
-  "resource://gre/modules/FileUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "Telemetry",
   "@mozilla.org/base/telemetry;1", "nsITelemetry");
-XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
-  "resource://gre/modules/Deprecated.jsm");
 
 this.SessionFile = {
   /**
    * Read the contents of the session file, asynchronously.
    */
   read: function () {
     return SessionFileInternal.read();
   },
   /**
-   * Read the contents of the session file, synchronously.
-   */
-  syncRead: function () {
-    Deprecated.warning(
-      "syncRead is deprecated and will be removed in a future version",
-      "https://bugzilla.mozilla.org/show_bug.cgi?id=532150")
-    return SessionFileInternal.syncRead();
-  },
-  /**
    * Write the contents of the session file, asynchronously.
    */
   write: function (aData) {
     return SessionFileInternal.write(aData);
   },
   /**
    * Writes the initial state to disk again only to change the session's load
    * state. This must only be called once, it will throw an error otherwise.
@@ -156,70 +141,16 @@ let SessionFileInternal = {
    */
   _latestWrite: null,
 
   /**
    * |true| once we have decided to stop receiving write instructiosn
    */
   _isClosed: false,
 
-  /**
-   * Utility function to safely read a file synchronously.
-   * @param aPath
-   *        A path to read the file from.
-   * @returns string if successful, undefined otherwise.
-   */
-  readAuxSync: function (aPath) {
-    let text;
-    try {
-      let file = new FileUtils.File(aPath);
-      let chan = NetUtil.newChannel(file);
-      let stream = chan.open();
-      text = NetUtil.readInputStreamToString(stream, stream.available(),
-        {charset: "utf-8"});
-    } catch (e if e.result == Components.results.NS_ERROR_FILE_NOT_FOUND) {
-      // Ignore exceptions about non-existent files.
-    } catch (ex) {
-      // Any other error.
-      Cu.reportError(ex);
-    } finally {
-      return text;
-    }
-  },
-
-  /**
-   * Read the sessionstore file synchronously.
-   *
-   * This function is meant to serve as a fallback in case of race
-   * between a synchronous usage of the API and asynchronous
-   * initialization.
-   *
-   * In case if sessionstore.js file does not exist or is corrupted (something
-   * happened between backup and write), attempt to read the sessionstore.bak
-   * instead.
-   */
-  syncRead: function () {
-    // Start measuring the duration of the synchronous read.
-    TelemetryStopwatch.start("FX_SESSION_RESTORE_SYNC_READ_FILE_MS");
-    // First read the sessionstore.js.
-    let text = this.readAuxSync(this.path);
-    if (typeof text === "undefined") {
-      // If sessionstore.js does not exist or is corrupted, read sessionstore.bak.
-      text = this.readAuxSync(this.backupPath);
-    }
-    // Finish the telemetry probe and return an empty string.
-    TelemetryStopwatch.finish("FX_SESSION_RESTORE_SYNC_READ_FILE_MS");
-    text = text || "";
-
-    // The worker needs to know the initial state read from
-    // disk so that writeLoadStateOnceAfterStartup() works.
-    SessionWorker.post("setInitialState", [text]);
-    return text;
-  },
-
   read: function () {
     return SessionWorker.post("read").then(msg => {
       this._recordTelemetry(msg.telemetry);
       return msg.ok;
     });
   },
 
   write: function (aData) {
--- a/browser/components/sessionstore/src/SessionWorker.js
+++ b/browser/components/sessionstore/src/SessionWorker.js
@@ -69,40 +69,16 @@ let Agent = {
 
   // The path to sessionstore.js
   path: OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.js"),
 
   // The path to sessionstore.bak
   backupPath: OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.bak"),
 
   /**
-   * This method is only intended to be called by SessionFile.syncRead() and
-   * can be removed when we're not supporting synchronous SessionStore
-   * initialization anymore. When sessionstore.js is read from disk
-   * synchronously the state string must be supplied to the worker manually by
-   * calling this method.
-   */
-  setInitialState: function (aState) {
-    // SessionFile.syncRead() should not be called after startup has finished.
-    // Thus we also don't support any setInitialState() calls after we already
-    // wrote the loadState to disk.
-    if (this.hasWrittenLoadStateOnce) {
-      throw new Error("writeLoadStateOnceAfterStartup() must only be called once.");
-    }
-
-    // Initial state might have been filled by read() already but yet we might
-    // be called by SessionFile.syncRead() before SessionStore.jsm had a chance
-    // to call writeLoadStateOnceAfterStartup(). It's safe to ignore
-    // setInitialState() calls if this happens.
-    if (!this.initialState) {
-      this.initialState = aState;
-    }
-  },
-
-  /**
    * Read the session from disk.
    * In case sessionstore.js does not exist, attempt to read sessionstore.bak.
    */
   read: function () {
     for (let path of [this.path, this.backupPath]) {
       try {
         let durationMs = Date.now();
         let bytes = File.read(path);
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -43,16 +43,19 @@ Cu.import("resource://gre/modules/Teleme
 Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SessionFile",
   "resource:///modules/sessionstore/SessionFile.jsm");
 
 const STATE_RUNNING_STR = "running";
 
+// 'browser.startup.page' preference value to resume the previous session.
+const BROWSER_STARTUP_RESUME_SESSION = 3;
+
 function debug(aMsg) {
   aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
   Services.console.logStringMessage(aMsg);
 }
 
 let gOnceInitializedDeferred = Promise.defer();
 
 /* :::::::: The Service ::::::::::::::: */
@@ -133,17 +136,17 @@ SessionStartup.prototype = {
           debug("The session file contained un-eval-able JSON: " + ex);
           corruptFile = true;
         }
       }
       Services.telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").add(corruptFile);
 
       let doResumeSessionOnce = Services.prefs.getBoolPref("browser.sessionstore.resume_session_once");
       let doResumeSession = doResumeSessionOnce ||
-            Services.prefs.getIntPref("browser.startup.page") == 3;
+            Services.prefs.getIntPref("browser.startup.page") == BROWSER_STARTUP_RESUME_SESSION;
 
       // If this is a normal restore then throw away any previous session
       if (!doResumeSessionOnce)
         delete this._initialState.lastSessionState;
 
       let resumeFromCrash = Services.prefs.getBoolPref("browser.sessionstore.resume_from_crash");
       let lastSessionCrashed =
         this._initialState && this._initialState.session &&
@@ -221,27 +224,39 @@ SessionStartup.prototype = {
    * Get the session state as a jsval
    */
   get state() {
     this._ensureInitialized();
     return this._initialState;
   },
 
   /**
-   * Determines whether there is a pending session restore and makes sure that
-   * we're initialized before returning. If we're not yet this will read the
-   * session file synchronously.
+   * Determines whether there is a pending session restore. Should only be
+   * called after initialization has completed.
+   * @throws Error if initialization is not complete yet.
    * @returns bool
    */
   doRestore: function sss_doRestore() {
     this._ensureInitialized();
     return this._willRestore();
   },
 
   /**
+   * Determines whether automatic session restoration is enabled for this
+   * launch of the browser. This does not include crash restoration. In
+   * particular, if session restore is configured to restore only in case of
+   * crash, this method returns false.
+   * @returns bool
+   */
+  isAutomaticRestoreEnabled: function () {
+    return Services.prefs.getBoolPref("browser.sessionstore.resume_session_once") ||
+           Services.prefs.getIntPref("browser.startup.page") == BROWSER_STARTUP_RESUME_SESSION;
+  },
+
+  /**
    * Determines whether there is a pending session restore.
    * @returns bool
    */
   _willRestore: function () {
     return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
            this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
   },
 
@@ -270,30 +285,22 @@ SessionStartup.prototype = {
   /**
    * Get the type of pending session store, if any.
    */
   get sessionType() {
     this._ensureInitialized();
     return this._sessionType;
   },
 
-  // Ensure that initialization is complete.
-  // If initialization is not complete yet, fall back to a synchronous
-  // initialization and kill ongoing asynchronous initialization
+  // Ensure that initialization is complete. If initialization is not complete
+  // yet, something is attempting to use the old synchronous initialization,
+  // throw an error.
   _ensureInitialized: function sss__ensureInitialized() {
-    try {
-      if (this._initialized) {
-        // Initialization is complete, nothing else to do
-        return;
-      }
-      let contents = SessionFile.syncRead();
-      this._onSessionFileRead(contents);
-    } catch(ex) {
-      debug("ensureInitialized: could not read session " + ex + ", " + ex.stack);
-      throw ex;
+    if (!this._initialized) {
+      throw new Error("Session Store is not initialized.");
     }
   },
 
   /* ........ QueryInterface .............. */
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference,
                                           Ci.nsISessionStartup]),
   classID:          Components.ID("{ec7a6c20-e081-11da-8ad9-0800200c9a66}")
--- a/browser/components/sessionstore/test/browser_833286_atomic_backup.js
+++ b/browser/components/sessionstore/test/browser_833286_atomic_backup.js
@@ -99,36 +99,26 @@ function testReadBackup() {
   // Read latest sessionstore.js.
   array = yield OS.File.read(path);
   gSSData = gDecoder.decode(array);
 
   // Read sessionstore.js with SessionFile.read.
   let ssDataRead = yield SessionFile.read();
   is(ssDataRead, gSSData, "SessionFile.read read sessionstore.js correctly.");
 
-  // Read sessionstore.js with SessionFile.syncRead.
-  ssDataRead = SessionFile.syncRead();
-  is(ssDataRead, gSSData,
-    "SessionFile.syncRead read sessionstore.js correctly.");
-
   // Remove sessionstore.js to test fallback onto sessionstore.bak.
   yield OS.File.remove(path);
   ssExists = yield OS.File.exists(path);
   ok(!ssExists, "sessionstore.js should be removed now.");
 
   // Read sessionstore.bak with SessionFile.read.
   ssDataRead = yield SessionFile.read();
   is(ssDataRead, gSSBakData,
     "SessionFile.read read sessionstore.bak correctly.");
 
-  // Read sessionstore.bak with SessionFile.syncRead.
-  ssDataRead = SessionFile.syncRead();
-  is(ssDataRead, gSSBakData,
-    "SessionFile.syncRead read sessionstore.bak correctly.");
-
   nextTest(testBackupUnchanged);
 }
 
 function testBackupUnchanged() {
   // Ensure sessionstore.bak is backed up only once.
 
   // Read sessionstore.bak data.
   let array = yield OS.File.read(backupPath);
deleted file mode 100644
--- a/browser/components/sessionstore/test/unit/test_startup_nosession_sync.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-
-// Test nsISessionStartup.sessionType in the following scenario:
-// - no sessionstore.js;
-// - the session store has not been loaded yet, so we have to trigger
-//    synchronous fallback
-
-function run_test() {
-  do_get_profile();
-  let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
-    getService(Ci.nsISessionStartup);
-  do_check_eq(startup.sessionType, Ci.nsISessionStartup.NO_SESSION);
-}
\ No newline at end of file
deleted file mode 100644
--- a/browser/components/sessionstore/test/unit/test_startup_session_sync.js
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-
-// Test nsISessionStartup.sessionType in the following scenario:
-// - valid sessionstore.js;
-// - the session store has not been loaded yet, so we have to trigger
-//    synchronous fallback
-
-function run_test() {
-  let profd = do_get_profile();
-  let source = do_get_file("data/sessionstore_valid.js");
-  source.copyTo(profd, "sessionstore.js");
-  let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
-    getService(Ci.nsISessionStartup);
-  do_check_eq(startup.sessionType, Ci.nsISessionStartup.DEFER_SESSION);
-}
\ No newline at end of file
--- a/browser/components/sessionstore/test/unit/xpcshell.ini
+++ b/browser/components/sessionstore/test/unit/xpcshell.ini
@@ -1,12 +1,10 @@
 [DEFAULT]
 head = head.js
 tail =
 firefox-appdir = browser
 support-files = data/sessionstore_valid.js
 
 [test_backup.js]
 [test_backup_once.js]
-[test_startup_nosession_sync.js]
 [test_startup_nosession_async.js]
-[test_startup_session_sync.js]
 [test_startup_session_async.js]
--- a/browser/components/test/browser_bug538331.js
+++ b/browser/components/test/browser_bug538331.js
@@ -113,16 +113,20 @@ this.__defineGetter__("gBG", function() 
                     getService(Ci.nsIBrowserGlue).
                     QueryInterface(Ci.nsIObserver);
 });
 
 function test()
 {
   waitForExplicitFinish();
 
+  // Reset the startup page pref since it may have been set by other tests
+  // and we will assume it is default.
+  Services.prefs.clearUserPref('browser.startup.page');
+
   if (gPrefService.prefHasUserValue(PREF_MSTONE)) {
     gOriginalMStone = gPrefService.getCharPref(PREF_MSTONE);
   }
 
   if (gPrefService.prefHasUserValue(PREF_OVERRIDE_URL)) {
     gOriginalOverrideURL = gPrefService.getCharPref(PREF_OVERRIDE_URL);
   }
 
--- a/browser/devtools/debugger/debugger-panes.js
+++ b/browser/devtools/debugger/debugger-panes.js
@@ -1511,16 +1511,17 @@ WatchExpressionsView.prototype = Heritag
   /**
    * The keypress listener for a watch expression's textbox.
    */
   _onKeyPress: function(e) {
     switch(e.keyCode) {
       case e.DOM_VK_RETURN:
       case e.DOM_VK_ENTER:
       case e.DOM_VK_ESCAPE:
+        e.stopPropagation();
         DebuggerView.editor.focus();
         return;
     }
   }
 });
 
 /**
  * Functions handling the event listeners UI.
--- a/browser/devtools/framework/toolbox.js
+++ b/browser/devtools/framework/toolbox.js
@@ -62,16 +62,17 @@ loader.lazyGetter(this, "Requisition", (
 function Toolbox(target, selectedTool, hostType, hostOptions) {
   this._target = target;
   this._toolPanels = new Map();
   this._telemetry = new Telemetry();
 
   this._toolRegistered = this._toolRegistered.bind(this);
   this._toolUnregistered = this._toolUnregistered.bind(this);
   this._refreshHostTitle = this._refreshHostTitle.bind(this);
+  this._splitConsoleOnKeypress = this._splitConsoleOnKeypress.bind(this)
   this.destroy = this.destroy.bind(this);
 
   this._target.on("close", this.destroy);
 
   if (!hostType) {
     hostType = Services.prefs.getCharPref(this._prefs.LAST_HOST);
   }
   if (!selectedTool) {
@@ -224,21 +225,65 @@ Toolbox.prototype = {
 
   _buildOptions: function() {
     let key = this.doc.getElementById("toolbox-options-key");
     key.addEventListener("command", () => {
       this.selectTool("options");
     }, true);
   },
 
+  _splitConsoleOnKeypress: function(e) {
+    if (e.keyCode === e.DOM_VK_ESCAPE) {
+      this.toggleSplitConsole();
+    }
+  },
+
   _addToolSwitchingKeys: function() {
     let nextKey = this.doc.getElementById("toolbox-next-tool-key");
     nextKey.addEventListener("command", this.selectNextTool.bind(this), true);
     let prevKey = this.doc.getElementById("toolbox-previous-tool-key");
     prevKey.addEventListener("command", this.selectPreviousTool.bind(this), true);
+
+    // Split console uses keypress instead of command so the event can be
+    // cancelled with stopPropagation on the keypress, and not preventDefault.
+    this.doc.addEventListener("keypress", this._splitConsoleOnKeypress, false);
+  },
+
+  /**
+   * Make sure that the console is showing up properly based on all the
+   * possible conditions.
+   *   1) If the console tab is selected, then regardless of split state
+   *      it should take up the full height of the deck, and we should
+   *      hide the deck and splitter.
+   *   2) If the console tab is not selected and it is split, then we should
+   *      show the splitter, deck, and console.
+   *   3) If the console tab is not selected and it is *not* split,
+   *      then we should hide the console and splitter, and show the deck
+   *      at full height.
+   */
+  _refreshConsoleDisplay: function() {
+    let deck = this.doc.getElementById("toolbox-deck");
+    let webconsolePanel = this.doc.getElementById("toolbox-panel-webconsole");
+    let splitter = this.doc.getElementById("toolbox-console-splitter");
+    let openedConsolePanel = this.currentToolId === "webconsole";
+
+    if (openedConsolePanel) {
+      deck.setAttribute("collapsed", "true");
+      splitter.setAttribute("hidden", "true");
+      webconsolePanel.removeAttribute("collapsed");
+    } else {
+      deck.removeAttribute("collapsed");
+      if (this._splitConsole) {
+        webconsolePanel.removeAttribute("collapsed");
+        splitter.removeAttribute("hidden");
+      } else {
+        webconsolePanel.setAttribute("collapsed", "true");
+        splitter.setAttribute("hidden", "true");
+      }
+    }
   },
 
   /**
    * Wire up the listeners for the zoom keys.
    */
   _addZoomKeys: function() {
     let inKey = this.doc.getElementById("toolbox-zoom-in-key");
     inKey.addEventListener("command", this.zoomIn.bind(this), true);
@@ -497,18 +542,21 @@ Toolbox.prototype = {
       radio.setAttribute("flex", "1");
     }
 
     if (!toolDefinition.bgTheme) {
       toolDefinition.bgTheme = "theme-toolbar";
     }
     let vbox = this.doc.createElement("vbox");
     vbox.className = "toolbox-panel " + toolDefinition.bgTheme;
-    vbox.id = "toolbox-panel-" + id;
 
+    // There is already a container for the webconsole frame.
+    if (!this.doc.getElementById("toolbox-panel-" + id)) {
+      vbox.id = "toolbox-panel-" + id;
+    }
 
     // If there is no tab yet, or the ordinal to be added is the largest one.
     if (tabs.childNodes.length == 0 ||
         +tabs.lastChild.getAttribute("ordinal") <= toolDefinition.ordinal) {
       tabs.appendChild(radio);
       deck.appendChild(vbox);
     } else {
       // else, iterate over all the tabs to get the correct location.
@@ -608,17 +656,16 @@ Toolbox.prototype = {
     let selected = this.doc.querySelector(".devtools-tab[selected]");
     if (selected) {
       selected.removeAttribute("selected");
     }
 
     let tab = this.doc.getElementById("toolbox-tab-" + id);
     tab.setAttribute("selected", "true");
 
-
     if (this.currentToolId == id) {
       // re-focus tool to get key events again
       this.focusTool(id);
 
       // Return the existing panel in order to have a consistent return value.
       return promise.resolve(this._toolPanels.get(id));
     }
 
@@ -651,16 +698,17 @@ Toolbox.prototype = {
     }
     tabstrip.selectedItem = tab;
 
     // and select the right iframe
     let deck = this.doc.getElementById("toolbox-deck");
     deck.selectedIndex = index;
 
     this.currentToolId = id;
+    this._refreshConsoleDisplay();
     if (id != "options") {
       Services.prefs.setCharPref(this._prefs.LAST_TOOL, id);
     }
 
     return this.loadTool(id).then(panel => {
       // focus the tool's frame to start receiving key events
       this.focusTool(id);
 
@@ -676,16 +724,37 @@ Toolbox.prototype = {
    *         The id of tool to focus
    */
   focusTool: function(id) {
     let iframe = this.doc.getElementById("toolbox-panel-iframe-" + id);
     iframe.focus();
   },
 
   /**
+   * Toggles the split state of the webconsole.  If the webconsole panel
+   * is already selected, then this command is ignored.
+   */
+  toggleSplitConsole: function() {
+    let openedConsolePanel = this.currentToolId === "webconsole";
+
+    // Don't allow changes when console is open, since it could be confusing
+    if (!openedConsolePanel) {
+      this._splitConsole = !this._splitConsole;
+      this._refreshConsoleDisplay();
+      this.emit("split-console");
+
+      if (this._splitConsole) {
+        this.loadTool("webconsole").then(() => {
+          this.focusTool("webconsole");
+        });
+      }
+    }
+  },
+
+  /**
    * Loads the tool next to the currently selected tool.
    */
   selectNextTool: function() {
     let selected = this.doc.querySelector(".devtools-tab[selected]");
     let next = selected.nextSibling || selected.parentNode.firstChild;
     let tool = next.getAttribute("toolid");
     return this.selectTool(tool);
   },
@@ -784,17 +853,17 @@ Toolbox.prototype = {
 
     let newHost = this._createHost(hostType);
     return newHost.create().then(iframe => {
       // change toolbox document's parent to the new host
       iframe.QueryInterface(Ci.nsIFrameLoaderOwner);
       iframe.swapFrameLoaders(this.frame);
 
       this._host.off("window-closed", this.destroy);
-      this._host.destroy();
+      this.destroyHost();
 
       this._host = newHost;
 
       if (this.hostType != Toolbox.HostType.CUSTOM) {
         Services.prefs.setCharPref(this._prefs.LAST_HOST, this._host.type);
       }
 
       this._buildDockButtons();
@@ -872,16 +941,27 @@ Toolbox.prototype = {
    *
    * @return The notification box element.
    */
   getNotificationBox: function() {
     return this.doc.getElementById("toolbox-notificationbox");
   },
 
   /**
+   * Destroy the current host, and remove event listeners from its frame.
+   *
+   * @return {promise} to be resolved when the host is destroyed.
+   */
+  destroyHost: function() {
+    this.doc.removeEventListener("keypress",
+      this._splitConsoleOnKeypress, false);
+    return this._host.destroy();
+  },
+
+  /**
    * Remove all UI elements, detach from target and clear up
    */
   destroy: function() {
     // If several things call destroy then we give them all the same
     // destruction promise so we're sure to destroy only once
     if (this._destroyer) {
       return this._destroyer;
     }
@@ -912,17 +992,17 @@ Toolbox.prototype = {
       }
     }
 
     let container = this.doc.getElementById("toolbox-buttons");
     while (container.firstChild) {
       container.removeChild(container.firstChild);
     }
 
-    outstanding.push(this._host.destroy());
+    outstanding.push(this.destroyHost());
 
     this._telemetry.destroy();
 
     return this._destroyer = promise.all(outstanding).then(() => {
       // Targets need to be notified that the toolbox is being torn down.
       // This is done after other destruction tasks since it may tear down
       // fronts and the debugger transport which earlier destroy methods may
       // require to complete.
--- a/browser/devtools/framework/toolbox.xul
+++ b/browser/devtools/framework/toolbox.xul
@@ -69,12 +69,15 @@
       <hbox id="toolbox-controls">
         <hbox id="toolbox-dock-buttons"/>
         <toolbarbutton id="toolbox-close"
                        class="devtools-closebutton"
                        tooltiptext="&toolboxCloseButton.tooltip;"/>
       </hbox>
 #endif
     </toolbar>
-    <deck id="toolbox-deck" flex="1">
-    </deck>
+    <vbox flex="1">
+      <deck id="toolbox-deck" flex="1" minheight="75" />
+      <splitter id="toolbox-console-splitter" class="devtools-horizontal-splitter" hidden="true" />
+      <box minheight="75" flex="1" id="toolbox-panel-webconsole" collapsed="true" />
+    </vbox>
   </notificationbox>
 </window>
--- a/browser/devtools/shared/widgets/Tooltip.js
+++ b/browser/devtools/shared/widgets/Tooltip.js
@@ -167,16 +167,19 @@ function Tooltip(doc, options) {
       this["_onPopup" + event], false);
   }
 
   // Listen to keypress events to close the tooltip if configured to do so
   let win = this.doc.querySelector("window");
   this._onKeyPress = event => {
     this.emit("keypress", event.keyCode);
     if (this.options.get("closeOnKeys").indexOf(event.keyCode) !== -1) {
+      if (!this.panel.hidden) {
+        event.stopPropagation();
+      }
       this.hide();
     }
   };
   win.addEventListener("keypress", this._onKeyPress, false);
 }
 
 module.exports.Tooltip = Tooltip;
 
--- a/browser/devtools/sourceeditor/test/browser.ini
+++ b/browser/devtools/sourceeditor/test/browser.ini
@@ -25,10 +25,9 @@ support-files =
 [browser_bug725392_mouse_coords_char_offset.js]
 [browser_bug725430_comment_uncomment.js]
 [browser_bug725618_moveLines_shortcut.js]
 [browser_bug729480_line_vertical_align.js]
 [browser_bug729960_block_bracket_jump.js]
 [browser_bug731721_debugger_stepping.js]
 [browser_bug744021_next_prev_bracket_jump.js]
 [browser_codemirror.js]
-skip-if = os == "linux"
-[browser_sourceeditor_initialization.js]
+[browser_sourceeditor_initialization.js]
\ No newline at end of file
--- a/browser/devtools/sourceeditor/test/browser_codemirror.js
+++ b/browser/devtools/sourceeditor/test/browser_codemirror.js
@@ -3,16 +3,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const HOST = 'mochi.test:8888';
 const URI  = "http://" + HOST + "/browser/browser/devtools/sourceeditor/test/codemirror.html";
 
 function test() {
+  requestLongerTimeout(2);
   waitForExplicitFinish();
 
   let tab = gBrowser.addTab();
   gBrowser.selectedTab = tab;
 
   let browser = gBrowser.getBrowserForTab(tab);
   browser.loadURI(URI);
 
--- a/browser/devtools/webconsole/test/browser.ini
+++ b/browser/devtools/webconsole/test/browser.ini
@@ -231,12 +231,13 @@ skip-if = os == "linux"
 [browser_webconsole_message_node_id.js]
 [browser_webconsole_netlogging.js]
 [browser_webconsole_network_panel.js]
 [browser_webconsole_notifications.js]
 [browser_webconsole_output_copy_newlines.js]
 [browser_webconsole_output_order.js]
 [browser_webconsole_property_provider.js]
 [browser_webconsole_scratchpad_panel_link.js]
+[browser_webconsole_split.js]
 [browser_webconsole_view_source.js]
 [browser_webconsole_reflow.js]
 [browser_webconsole_log_file_filter.js]
 [browser_webconsole_expandable_timestamps.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/webconsole/test/browser_webconsole_split.js
@@ -0,0 +1,238 @@
+/* vim:set ts=2 sw=2 sts=2 et: */
+/* 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/. */
+
+function test()
+{
+  let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
+  let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
+  let Toolbox = devtools.Toolbox;
+  let toolbox;
+
+  addTab("data:text/html;charset=utf-8,Web Console test for splitting");
+  browser.addEventListener("load", function onLoad() {
+    browser.removeEventListener("load", onLoad, true);
+    testConsoleLoadOnDifferentPanel()
+  }, true);
+
+  function testConsoleLoadOnDifferentPanel()
+  {
+    info("About to check console loads even when non-webconsole panel is open");
+
+    openPanel("inspector").then(() => {
+      toolbox.on("webconsole-ready", () => {
+        ok(true, "Webconsole has been triggered as loaded while another tool is active");
+        testKeyboardShortcuts();
+      });
+
+      // Opens split console.
+      toolbox.toggleSplitConsole();
+    });
+  }
+
+  function testKeyboardShortcuts()
+  {
+    info("About to check that panel responds to ESCAPE keyboard shortcut");
+
+    toolbox.once("split-console", () => {
+      ok(true, "Split console has been triggered via ESCAPE keypress");
+      checkAllTools();
+    });
+
+    // Closes split console.
+    EventUtils.sendKey("ESCAPE", toolbox.frame.contentWindow);
+  }
+
+  function checkAllTools()
+  {
+    info("About to check split console with each panel individually.");
+
+    Task.spawn(function() {
+      yield openAndCheckPanel("jsdebugger");
+      yield openAndCheckPanel("inspector");
+      yield openAndCheckPanel("styleeditor");
+      yield openAndCheckPanel("jsprofiler");
+      yield openAndCheckPanel("netmonitor");
+
+      yield checkWebconsolePanelOpened();
+      testBottomHost();
+    });
+  }
+
+  function getCurrentUIState()
+  {
+    let win = toolbox.doc.defaultView;
+    let deck = toolbox.doc.getElementById("toolbox-deck");
+    let webconsolePanel = toolbox.doc.getElementById("toolbox-panel-webconsole");
+    let splitter = toolbox.doc.getElementById("toolbox-console-splitter");
+
+    let containerHeight = parseFloat(win.getComputedStyle(deck.parentNode).getPropertyValue("height"));
+    let deckHeight = parseFloat(win.getComputedStyle(deck).getPropertyValue("height"));
+    let webconsoleHeight = parseFloat(win.getComputedStyle(webconsolePanel).getPropertyValue("height"));
+    let splitterVisibility = !splitter.getAttribute("hidden");
+    let openedConsolePanel = toolbox.currentToolId === "webconsole";
+
+    return {
+      deckHeight: deckHeight,
+      containerHeight: containerHeight,
+      webconsoleHeight: webconsoleHeight,
+      splitterVisibility: splitterVisibility,
+      openedConsolePanel: openedConsolePanel
+    };
+  }
+
+  function checkWebconsolePanelOpened()
+  {
+    info("About to check special cases when webconsole panel is open.");
+
+    let deferred = promise.defer();
+
+    // Start with console split, so we can test for transition to main panel.
+    toolbox.toggleSplitConsole();
+
+    let currentUIState = getCurrentUIState();
+
+    ok (currentUIState.splitterVisibility, "Splitter is visible when console is split");
+    ok (currentUIState.deckHeight > 0, "Deck has a height > 0 when console is split");
+    ok (currentUIState.webconsoleHeight > 0, "Web console has a height > 0 when console is split");
+    ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
+
+    openPanel("webconsole").then(() => {
+
+      let currentUIState = getCurrentUIState();
+
+      ok (!currentUIState.splitterVisibility, "Splitter is hidden when console is opened.");
+      is (currentUIState.deckHeight, 0, "Deck has a height == 0 when console is opened.");
+      is (currentUIState.webconsoleHeight, currentUIState.containerHeight, "Web console is full height.");
+      ok (currentUIState.openedConsolePanel, "The console panel is the current tool");
+
+      // Make sure splitting console does nothing while webconsole is opened
+      toolbox.toggleSplitConsole();
+
+      let currentUIState = getCurrentUIState();
+
+      ok (!currentUIState.splitterVisibility, "Splitter is hidden when console is opened.");
+      is (currentUIState.deckHeight, 0, "Deck has a height == 0 when console is opened.");
+      is (currentUIState.webconsoleHeight, currentUIState.containerHeight, "Web console is full height.");
+      ok (currentUIState.openedConsolePanel, "The console panel is the current tool");
+
+      // Make sure that split state is saved after opening another panel
+      openPanel("inspector").then(() => {
+        let currentUIState = getCurrentUIState();
+        ok (currentUIState.splitterVisibility, "Splitter is visible when console is split");
+        ok (currentUIState.deckHeight > 0, "Deck has a height > 0 when console is split");
+        ok (currentUIState.webconsoleHeight > 0, "Web console has a height > 0 when console is split");
+        ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
+
+        toolbox.toggleSplitConsole();
+        deferred.resolve();
+
+      });
+    });
+    return deferred.promise;
+  }
+
+  function openPanel(toolId, callback)
+  {
+    let deferred = promise.defer();
+    let target = TargetFactory.forTab(gBrowser.selectedTab);
+    gDevTools.showToolbox(target, toolId).then(function(box) {
+      toolbox = box;
+      deferred.resolve();
+    }).then(null, console.error);
+    return deferred.promise;
+  }
+
+  function openAndCheckPanel(toolId)
+  {
+    let deferred = promise.defer();
+    openPanel(toolId).then(() => {
+      info ("Checking toolbox for " + toolId);
+      checkToolboxUI(toolbox.getCurrentPanel());
+      deferred.resolve();
+    });
+    return deferred.promise;
+  }
+
+  function checkToolboxUI()
+  {
+    let currentUIState = getCurrentUIState();
+
+    ok (!currentUIState.splitterVisibility, "Splitter is hidden by default");
+    is (currentUIState.deckHeight, currentUIState.containerHeight, "Deck has a height > 0 by default");
+    is (currentUIState.webconsoleHeight, 0, "Web console is collapsed by default");
+    ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
+
+    toolbox.toggleSplitConsole();
+
+    let currentUIState = getCurrentUIState();
+
+    ok (currentUIState.splitterVisibility, "Splitter is visible when console is split");
+    ok (currentUIState.deckHeight > 0, "Deck has a height > 0 when console is split");
+    ok (currentUIState.webconsoleHeight > 0, "Web console has a height > 0 when console is split");
+    is (currentUIState.deckHeight + currentUIState.webconsoleHeight,
+          currentUIState.containerHeight,
+        "Everything adds up to container height");
+    ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
+
+    toolbox.toggleSplitConsole();
+
+    let currentUIState = getCurrentUIState();
+
+    ok (!currentUIState.splitterVisibility, "Splitter is hidden after toggling");
+    is (currentUIState.deckHeight, currentUIState.containerHeight, "Deck has a height > 0 after toggling");
+    is (currentUIState.webconsoleHeight, 0, "Web console is collapsed after toggling");
+    ok (!currentUIState.openedConsolePanel, "The console panel is not the current tool");
+  }
+
+
+  function testBottomHost()
+  {
+    checkHostType(Toolbox.HostType.BOTTOM);
+
+    checkToolboxUI();
+
+    toolbox.switchHost(Toolbox.HostType.SIDE).then(testSidebarHost);
+  }
+
+  function testSidebarHost()
+  {
+    checkHostType(Toolbox.HostType.SIDE);
+
+    checkToolboxUI();
+
+    toolbox.switchHost(Toolbox.HostType.WINDOW).then(testWindowHost);
+  }
+
+  function testWindowHost()
+  {
+    checkHostType(Toolbox.HostType.WINDOW);
+
+    checkToolboxUI();
+
+    testDestroy();
+  }
+
+  function checkHostType(hostType)
+  {
+    is(toolbox.hostType, hostType, "host type is " + hostType);
+
+    let pref = Services.prefs.getCharPref("devtools.toolbox.host");
+    is(pref, hostType, "host pref is " + hostType);
+  }
+
+  function testDestroy()
+  {
+    toolbox.destroy().then(function() {
+      let target = TargetFactory.forTab(gBrowser.selectedTab);
+      gDevTools.showToolbox(target).then(finish);
+    });
+  }
+
+  function finish()
+  {
+    toolbox = null;
+    finishTest();
+  }
+}
--- a/browser/metro/base/content/bindings/bindings.xml
+++ b/browser/metro/base/content/bindings/bindings.xml
@@ -301,9 +301,59 @@
               // binding for browser content (e.g. about:config)
               Services.obs.notifyObservers(event, "attach_edit_session_to_content", "");
             }
           }
         ]]>
       </handler>
     </handlers>
   </binding>
+
+  <binding id="line-wrap-label" extends="chrome://global/content/bindings/text.xml#text-label">
+    <implementation>
+      <constructor>
+        <![CDATA[
+          if (this.hasAttribute("value")) {
+            this.textContent = this.getAttribute("value");
+            this.removeAttribute("value");
+          }
+        ]]>
+      </constructor>
+      <property name="value">
+        <getter>
+          <![CDATA[
+            return this.textContent;
+          ]]>
+        </getter>
+        <setter>
+          <![CDATA[
+            return (this.textContent = val);
+          ]]>
+        </setter>
+      </property>
+    </implementation>
+  </binding>
+  <binding id="line-wrap-text-link" extends="chrome://global/content/bindings/text.xml#text-link">
+    <implementation>
+      <constructor>
+        <![CDATA[
+          if (this.hasAttribute("value")) {
+            this.textContent = this.getAttribute("value");
+            this.removeAttribute("value");
+          }
+        ]]>
+      </constructor>
+      <property name="value">
+        <getter>
+          <![CDATA[
+            return this.textContent;
+          ]]>
+        </getter>
+        <setter>
+          <![CDATA[
+            return (this.textContent = val);
+          ]]>
+        </setter>
+      </property>
+    </implementation>
+  </binding>
+
 </bindings>
--- a/browser/metro/base/content/bindings/urlbar.xml
+++ b/browser/metro/base/content/bindings/urlbar.xml
@@ -535,16 +535,18 @@
       <!-- nsIAutocompleteInput -->
 
       <field name="_input">null</field>
 
       <property name="input" readonly="true" onget="return this._input;"/>
       <property name="matchCount" readonly="true" onget="return this.input.controller.matchCount;"/>
       <property name="popupOpen" readonly="true" onget="return !this.hidden"/>
       <property name="overrideValue" readonly="true" onget="return null;"/>
+      <!-- Alias of popupOpen, for compatibility with global/content/bindings/autocomplete.xml -->
+      <property name="mPopupOpen" readonly="true" onget="return this.popupOpen"/>
 
       <property name="selectedItem">
         <getter>
           <![CDATA[
             return this._isGridBound(this._results) ? this._results.selectedItem : null;
           ]]>
         </getter>
         <setter>
--- a/browser/metro/base/content/browser.css
+++ b/browser/metro/base/content/browser.css
@@ -24,29 +24,32 @@ documenttab {
 
 appbar {
   -moz-binding: url('chrome://browser/content/bindings/appbar.xml#appbarBinding');
 }
 
 flyoutpanel {
   -moz-binding: url('chrome://browser/content/bindings/flyoutpanel.xml#flyoutpanelBinding');
 }
-
 cssthrobber {
   -moz-binding: url('chrome://browser/content/bindings/cssthrobber.xml#cssthrobberBinding');
 }
+label[linewrap] {
+  -moz-binding: url("chrome://browser/content/bindings/bindings.xml#line-wrap-label");
+}
+label[linewrap].text-link, label[onclick][linewrap] {
+  -moz-binding: url("chrome://browser/content/bindings/bindings.xml#line-wrap-text-link");
+}
 
 settings {
   -moz-binding: url("chrome://mozapps/content/extensions/setting.xml#settings");
 }
-
 setting {
   display: none;
 }
-
 autoscroller {
   -moz-binding: url('chrome://browser/content/bindings/popup.xml#element-popup');
 }
 
 notificationbox {
   -moz-binding: url('chrome://browser/content/bindings/notification.xml#notificationbox');
 }
 
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -234,16 +234,17 @@
               <image id="identity-icon"/>
             </box>
 
             <textbox id="urlbar-edit" type="url" flex="1"
                      autocompletesearch="history"
                      autocompletepopup="urlbar-autocomplete"
                      completeselectedindex="true"
                      placeholder="&urlbar.emptytext;"
+                     tabscrolling="true"
                      onclick="SelectionHelperUI.urlbarClick();"/>
 
             <toolbarbutton id="go-button" class="urlbar-button"
                            command="cmd_go"/>
             <toolbarbutton id="reload-button" class="urlbar-button"
                            oncommand="CommandUpdater.doCommand(
                                         event.shiftKey ? 'cmd_forceReload'
                                                        : 'cmd_reload');"/>
@@ -366,22 +367,20 @@
         <toolbarbutton id="restore-selected-button" class="appbar-secondary"
                        hidden="true" fade="true"
                        oncommand="Appbar.dispatchContextualAction('restore')"/>
         <toolbarbutton id="clear-selected-button" class="appbar-secondary"
                        hidden="true" fade="true"
                        oncommand="Appbar.dispatchContextualAction('clear')"/>
       </toolbar>
     </appbar>
-
     <autoscroller class="autoscroller" id="autoscrollerid"/>
-
     <flyoutpanel id="about-flyoutpanel" class="flyout-narrow" headertext="&aboutHeader.title;">
-      <label id="about-product-label" value="&aboutHeader.product.label;"/>
-      <label value="&aboutHeader.company.label;"/>
+      <label id="about-product-label" linewrap="true" value="&aboutHeader.product.label;"/>
+      <label value="&aboutHeader.company.label;" linewrap="true"/>
 #expand <label id="about-version-label">__MOZ_APP_VERSION__</label>
       <vbox id="updateBox">
 #ifdef MOZ_UPDATER
         <deck id="updateDeck" orient="vertical">
           <hbox id="updateButtonBox" align="center">
             <button id="updateButton" align="start"
                     oncommand="FlyoutPanelsUI.AboutFlyoutPanel.appUpdater.buttonOnCommand();"/>
             <spacer flex="1"/>
@@ -406,50 +405,48 @@
           </hbox>
           <hbox id="noUpdatesFound" align="center">
             <label>&update.noUpdatesFound;</label>
           </hbox>
           <hbox id="otherInstanceHandlingUpdates" align="center">
             <label>&update.otherInstanceHandlingUpdates;</label>
           </hbox>
           <hbox id="manualUpdate" align="center">
-            <label>&update.manual.start;</label><label id="manualLink" class="text-link"/><label>&update.manual.end;</label>
+            <label>&update.manual.start;</label><label id="manualLink" linewrap="true" class="text-link"/><label>&update.manual.end;</label>
           </hbox>
         </deck>
 #endif
       </vbox>
-
 #if MOZ_UPDATE_CHANNEL != release
 #ifdef MOZ_UPDATER
-      <description class="text-blurb" id="currentChannelText">&channel.description.start;<label id="currentChannel"/>&channel.description.end;</description>
+      <description class="text-blurb" id="currentChannelText">&channel.description.start;<label id="currentChannel" linewrap="true"/>&channel.description.end;</description>
 #endif
 #endif
       <label id="about-policy-label"
+            linewrap="true"
             onclick="FlyoutPanelsUI.AboutFlyoutPanel.onPolicyClick(event);"
             class="text-link" value="&aboutHeader.policy.label;"/>
       <spacer class="flyoutpanel-hack"/>
     </flyoutpanel>
-
 #ifdef MOZ_SERVICES_SYNC
     <flyoutpanel id="sync-flyoutpanel" class="flyout-narrow" headertext="&sync.flyout.title;">
-
       <vbox id="sync-presetup-container" collapsed="true">
         <description>&sync.flyout.presetup.description1;</description>
         <separator />
         <hbox onclick="FlyoutPanelsUI.SyncFlyoutPanel.startEasySetup();"
               align="center"
               class="text-link">
           <image src="chrome://browser/skin/images/plus-34.png" />
           <separator />
           <label value="&sync.flyout.presetup.setup.label;"
+                 linewrap="true"
                  class="text-link" />
           <spacer flex="1" />
         </hbox>
       </vbox>
-
       <vbox id="sync-setup-container" collapsed="true">
         <description>&sync.flyout.setup.description1;</description>
         <description>&sync.flyout.setup.description2;</description>
         <separator />
         <vbox flex="1" pack="center" align="start">
           <textbox id="sync-setup-code1"
                    class="syncJPAKECode"
                    placeholder="...."
--- a/browser/metro/base/tests/mochitest/browser_urlbar.js
+++ b/browser/metro/base/tests/mochitest/browser_urlbar.js
@@ -112,28 +112,29 @@ gTests.push({
   setUp: setUp,
   tearDown: tearDown,
   run: function testSearchEngine() {
     // If the XBL hasn't initialized yet, open the popup so that it will.
     if (gEdit.popup._searches == undefined) {
       gEdit.openPopup();
       gEdit.closePopup();
     }
+    yield waitForCondition(() => gEdit.popup._searches.itemCount);
 
     let numSearches = gEdit.popup._searches.itemCount;
     function getEngineItem() {
       return gEdit.popup._searches.querySelector("richgriditem[value="+kSearchEngineName+"]");
     }
 
     yield addMockSearchDefault();
-    ok(gEdit.popup._searches.itemCount == numSearches + 1, "added search engine count");
+    is(gEdit.popup._searches.itemCount, numSearches + 1, "added search engine count");
     ok(getEngineItem(), "added search engine item");
 
     yield removeMockSearchDefault();
-    ok(gEdit.popup._searches.itemCount == numSearches, "normal search engine count");
+    is(gEdit.popup._searches.itemCount, numSearches, "normal search engine count");
     ok(!getEngineItem(), "added search engine item");
   }
 });
 
 gTests.push({
   desc: "display autocomplete while typing, handle enter",
   setUp: setUp,
   tearDown: tearDown,
@@ -332,16 +333,22 @@ gTests.push({
 
     yield waitForCondition(() => gEdit.popup._resultsContainer.hidden);
 
     ok(gEdit.popup._resultsContainer.hidden, "'Your results' are hidden");
     ok(gEdit.popup._results.itemCount === 0, "'Your results' are empty");
 
     EventUtils.synthesizeKey("VK_DOWN", {}, window);
     is(gEdit.popup._searches.selectedIndex, 0, "key select search: first search selected");
+
+    EventUtils.synthesizeKey("VK_TAB", {}, window);
+    is(gEdit.popup._searches.selectedIndex, 1, "tab key: second search selected");
+
+    EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, window);
+    is(gEdit.popup._searches.selectedIndex, 0, "shift-tab: first search selected");
   }
 });
 
 gTests.push({
   desc: "Bug 891667 - Use up arrow too",
   tearDown: tearDown,
   run: function testBug891667() {
     yield addTab("about:start");
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -466,17 +466,17 @@ class Automation(object):
       if ext == ".client":
         self.Process([pk12util, "-i", os.path.join(certPath, item), "-w",
                     pwfilePath, "-d", profileDir], 
                     env = env).wait()
 
     os.unlink(pwfilePath)
     return 0
 
-  def environment(self, env = None, xrePath = None, crashreporter = True):
+  def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False):
     if xrePath == None:
       xrePath = self.DIST_BIN
     if env == None:
       env = dict(os.environ)
 
     ldLibraryPath = os.path.abspath(os.path.join(SCRIPT_DIR, xrePath))
     if self.UNIXISH or self.IS_MAC:
       envVar = "LD_LIBRARY_PATH"
@@ -485,17 +485,17 @@ class Automation(object):
       else: # unixish
         env['MOZILLA_FIVE_HOME'] = xrePath
       if envVar in env:
         ldLibraryPath = ldLibraryPath + ":" + env[envVar]
       env[envVar] = ldLibraryPath
     elif self.IS_WIN32:
       env["PATH"] = env["PATH"] + ";" + str(ldLibraryPath)
 
-    if crashreporter:
+    if crashreporter and not debugger:
       env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
       env['MOZ_CRASHREPORTER'] = '1'
     else:
       env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
     env['GNOME_DISABLE_CRASH_DIALOG'] = '1'
     env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1'
     env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -397,17 +397,17 @@ def parseKeyValue(strings, separator='='
 
 def systemMemory():
   """
   Returns total system memory in kilobytes.
   Works only on unix-like platforms where `free` is in the path.
   """
   return int(os.popen("free").readlines()[1].split()[1])
 
-def environment(xrePath, env=None, crashreporter=True):
+def environment(xrePath, env=None, crashreporter=True, debugger=False):
   """populate OS environment variables for mochitest"""
 
   env = os.environ.copy() if env is None else env
 
   assert os.path.isabs(xrePath)
 
   ldLibraryPath = xrePath
 
@@ -425,17 +425,17 @@ def environment(xrePath, env=None, crash
                 else (ldLibraryPath, env.get(envVar)))
     env[envVar] = os.path.pathsep.join([path for path in envValue if path])
 
   # crashreporter
   env['GNOME_DISABLE_CRASH_DIALOG'] = '1'
   env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1'
   env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
 
-  if crashreporter:
+  if crashreporter and not debugger:
     env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
     env['MOZ_CRASHREPORTER'] = '1'
   else:
     env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
   # Additional temporary logging while we try to debug some intermittent
   # WebRTC conditions. This is necessary to troubleshoot bugs 841496,
   # 841150, and 839677 (at least)
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -30,16 +30,18 @@ SEARCH_PATHS = [
     'python/mozbuild',
     'python/mozversioncontrol',
     'python/blessings',
     'python/configobj',
     'python/psutil',
     'python/which',
     'build/pymake',
     'config',
+    'dom/bindings',
+    'dom/bindings/parser',
     'other-licenses/ply',
     'xpcom/idl-parser',
     'testing',
     'testing/xpcshell',
     'testing/marionette/client',
     'testing/marionette/client/marionette',
     'testing/mozbase/mozcrash',
     'testing/mozbase/mozdevice',
@@ -55,16 +57,17 @@ SEARCH_PATHS = [
     'testing/mozbase/moztest',
     'testing/mozbase/manifestdestiny',
     'xpcom/idl-parser',
 ]
 
 # Individual files providing mach commands.
 MACH_MODULES = [
     'addon-sdk/mach_commands.py',
+    'dom/bindings/mach_commands.py',
     'layout/tools/reftest/mach_commands.py',
     'python/mach_commands.py',
     'python/mach/mach/commands/commandinfo.py',
     'python/mozboot/mozboot/mach_commands.py',
     'python/mozbuild/mozbuild/config.py',
     'python/mozbuild/mozbuild/mach_commands.py',
     'python/mozbuild/mozbuild/frontend/mach_commands.py',
     'testing/mach_commands.py',
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -43,29 +43,29 @@ class RemoteAutomation(Automation):
 
     def setProduct(self, product):
         self._product = product
 
     def setRemoteLog(self, logfile):
         self._remoteLog = logfile
 
     # Set up what we need for the remote environment
-    def environment(self, env = None, xrePath = None, crashreporter = True):
+    def environment(self, env=None, xrePath=None, crashreporter=True, debugger=False):
         # Because we are running remote, we don't want to mimic the local env
         # so no copying of os.environ
         if env is None:
             env = {}
 
         # Except for the mochitest results table hiding option, which isn't
         # passed to runtestsremote.py as an actual option, but through the
-        # MOZ_CRASHREPORTER_DISABLE environment variable.
+        # MOZ_HIDE_RESULTS_TABLE environment variable.
         if 'MOZ_HIDE_RESULTS_TABLE' in os.environ:
             env['MOZ_HIDE_RESULTS_TABLE'] = os.environ['MOZ_HIDE_RESULTS_TABLE']
 
-        if crashreporter:
+        if crashreporter and not debugger:
             env['MOZ_CRASHREPORTER_NO_REPORT'] = '1'
             env['MOZ_CRASHREPORTER'] = '1'
         else:
             env['MOZ_CRASHREPORTER_DISABLE'] = '1'
 
         return env
 
     def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath):
--- a/build/mobile/robocop/moz.build
+++ b/build/mobile/robocop/moz.build
@@ -1,9 +1,5 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
-
-ANDROID_RESFILES = [
-    'res/values/strings.xml',
-]
--- a/build/mobile/sutagent/android/fencp/moz.build
+++ b/build/mobile/sutagent/android/fencp/moz.build
@@ -1,13 +1,5 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
-
-ANDROID_RESFILES = [
-    'res/drawable-hdpi/icon.png',
-    'res/drawable-ldpi/icon.png',
-    'res/drawable-mdpi/icon.png',
-    'res/layout/main.xml',
-    'res/values/strings.xml',
-]
--- a/build/mobile/sutagent/android/ffxcp/moz.build
+++ b/build/mobile/sutagent/android/ffxcp/moz.build
@@ -1,13 +1,5 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
-
-ANDROID_RESFILES = [
-    'res/drawable-hdpi/icon.png',
-    'res/drawable-ldpi/icon.png',
-    'res/drawable-mdpi/icon.png',
-    'res/layout/main.xml',
-    'res/values/strings.xml',
-]
--- a/build/mobile/sutagent/android/moz.build
+++ b/build/mobile/sutagent/android/moz.build
@@ -1,15 +1,5 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
-
-ANDROID_RESFILES = [
-    'res/drawable/ateamlogo.png',
-    'res/drawable/ic_stat_first.png',
-    'res/drawable/ic_stat_neterror.png',
-    'res/drawable/ic_stat_warning.png',
-    'res/drawable/icon.png',
-    'res/layout/main.xml',
-    'res/values/strings.xml',
-]
--- a/build/mobile/sutagent/android/watcher/moz.build
+++ b/build/mobile/sutagent/android/watcher/moz.build
@@ -1,16 +1,5 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
-
-ANDROID_RESFILES = [
-    'res/drawable-hdpi/ateamlogo.png',
-    'res/drawable-hdpi/icon.png',
-    'res/drawable-ldpi/ateamlogo.png',
-    'res/drawable-ldpi/icon.png',
-    'res/drawable-mdpi/ateamlogo.png',
-    'res/drawable-mdpi/icon.png',
-    'res/layout/main.xml',
-    'res/values/strings.xml',
-]
--- a/config/config.mk
+++ b/config/config.mk
@@ -30,17 +30,17 @@ endif
 -include $(DEPTH)/.mozconfig.mk
 
 # Integrate with mozbuild-generated make files. We first verify that no
 # variables provided by the automatically generated .mk files are
 # present. If they are, this is a violation of the separation of
 # responsibility between Makefile.in and mozbuild files.
 _MOZBUILD_EXTERNAL_VARIABLES := \
   ANDROID_GENERATED_RESFILES \
-  ANDROID_RESFILES \
+  ANDROID_RES_DIRS \
   CMSRCS \
   CMMSRCS \
   CPP_UNIT_TESTS \
   DIRS \
   EXTRA_PP_COMPONENTS \
   EXTRA_PP_JS_MODULES \
   FORCE_SHARED_LIB \
   FORCE_STATIC_LIB \
@@ -68,16 +68,17 @@ endif
   TEST_DIRS \
   TIERS \
   TOOL_DIRS \
   XPCSHELL_TESTS \
   XPIDL_MODULE \
   $(NULL)
 
 _DEPRECATED_VARIABLES := \
+  ANDROID_RESFILES \
   MOCHITEST_FILES_PARTS \
   MOCHITEST_BROWSER_FILES_PARTS \
   SHORT_LIBNAME \
   $(NULL)
 
 ifndef EXTERNALLY_MANAGED_MAKE_FILE
 # Using $(firstword) may not be perfect. But it should be good enough for most
 # scenarios.
@@ -472,19 +473,19 @@ JAVA_GEN_DIR  = _javagen
 JAVA_DIST_DIR = $(DEPTH)/$(JAVA_GEN_DIR)
 JAVA_IFACES_PKG_NAME = org/mozilla/interfaces
 
 OS_INCLUDES += $(MOZ_JPEG_CFLAGS) $(MOZ_PNG_CFLAGS) $(MOZ_ZLIB_CFLAGS)
 
 # NSPR_CFLAGS and NSS_CFLAGS must appear ahead of OS_INCLUDES to avoid Linux
 # builds wrongly picking up system NSPR/NSS header files.
 INCLUDES = \
-  $(LOCAL_INCLUDES) \
   -I$(srcdir) \
   -I. \
+  $(LOCAL_INCLUDES) \
   -I$(DIST)/include \
   $(if $(LIBXUL_SDK),-I$(LIBXUL_SDK)/include) \
   $(NSPR_CFLAGS) $(NSS_CFLAGS) \
   $(OS_INCLUDES) \
   $(NULL)
 
 include $(topsrcdir)/config/static-checking-config.mk
 
--- a/config/makefiles/java-build.mk
+++ b/config/makefiles/java-build.mk
@@ -2,49 +2,27 @@
 # vim:set ts=8 sw=8 sts=8 noet:
 #
 # 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/.
 
 ifndef INCLUDED_JAVA_BUILD_MK #{
 
-ifdef ANDROID_RESFILES #{
-ifndef IGNORE_ANDROID_RESFILES #{
-res-dep := .deps-copy-java-res
-
-GENERATED_DIRS += res
-GARBAGE        += $(res-dep)
-
-export:: $(res-dep)
-
-res-dep-preqs := \
-  $(addprefix $(srcdir)/,$(ANDROID_RESFILES)) \
-  $(call mkdir_deps,res) \
-  $(if $(IS_LANGUAGE_REPACK),FORCE) \
-  $(NULL)
-
-# nop-build: only copy res/ files when needed
-$(res-dep): $(res-dep-preqs)
-	$(call copy_dir,$(srcdir)/res,$(CURDIR)/res)
-	@$(TOUCH) $@
-endif #} IGNORE_ANDROID_RESFILES
-endif #} ANDROID_RESFILES
-
-
 ifdef JAVAFILES #{
 GENERATED_DIRS += classes
 
 export:: classes
 classes: $(call mkdir_deps,classes)
 endif #} JAVAFILES
 
 
 ifdef ANDROID_APK_NAME #{
-_ANDROID_RES_FLAG := -S $(or $(ANDROID_RES_DIR),res)
+android_res_dirs := $(addprefix $(srcdir)/,$(or $(ANDROID_RES_DIRS),res))
+_ANDROID_RES_FLAG := $(addprefix -S ,$(android_res_dirs))
 _ANDROID_ASSETS_FLAG := $(addprefix -A ,$(ANDROID_ASSETS_DIR))
 
 GENERATED_DIRS += classes
 
 classes.dex: $(call mkdir_deps,classes)
 classes.dex: R.java
 classes.dex: $(ANDROID_APK_NAME).ap_
 classes.dex: $(JAVAFILES)
@@ -52,17 +30,21 @@ classes.dex: $(JAVAFILES)
 	$(DX) --dex --output=$@ classes $(ANDROID_EXTRA_JARS)
 
 # R.java and $(ANDROID_APK_NAME).ap_ are both produced by aapt.  To
 # save an aapt invocation, we produce them both at the same time.
 
 R.java: .aapt.deps
 $(ANDROID_APK_NAME).ap_: .aapt.deps
 
-.aapt.deps: AndroidManifest.xml $(wildcard $(ANDROID_RES_DIR)) $(wildcard $(ANDROID_ASSETS_DIR))
+# This uses the fact that Android resource directories list all
+# resource files one subdirectory below the parent resource directory.
+android_res_files := $(wildcard $(addsuffix /*,$(wildcard $(addsuffix /*,$(android_res_dirs)))))
+
+.aapt.deps: AndroidManifest.xml $(android_res_files) $(wildcard $(ANDROID_ASSETS_DIR))
 	$(AAPT) package -f -M $< -I $(ANDROID_SDK)/android.jar $(_ANDROID_RES_FLAG) $(_ANDROID_ASSETS_FLAG) \
 		-J ${@D} \
 		-F $(ANDROID_APK_NAME).ap_
 	@$(TOUCH) $@
 
 $(ANDROID_APK_NAME)-unsigned-unaligned.apk: $(ANDROID_APK_NAME).ap_ classes.dex
 	cp $< $@
 	$(ZIP) -0 $@ classes.dex
--- a/config/mozunit.py
+++ b/config/mozunit.py
@@ -124,16 +124,29 @@ class MockedOpen(object):
             file = self.open(name, mode)
         if 'a' in mode:
             file.seek(0, os.SEEK_END)
         return file
 
     def __enter__(self):
         import __builtin__
         self.open = __builtin__.open
+        self._orig_path_exists = os.path.exists
         __builtin__.open = self
+        os.path.exists = self._wrapped_exists
 
     def __exit__(self, type, value, traceback):
         import __builtin__
         __builtin__.open = self.open
+        os.path.exists = self._orig_path_exists
+
+    def _wrapped_exists(self, p):
+        if p in self.files:
+            return True
+
+        abspath = os.path.abspath(p)
+        if abspath in self.files:
+            return True
+
+        return self._orig_path_exists(p)
 
 def main(*args):
     unittest.main(testRunner=MozTestRunner(),*args)
--- a/config/tests/unit-mozunit.py
+++ b/config/tests/unit-mozunit.py
@@ -10,46 +10,58 @@ from tempfile import mkstemp
 
 class TestMozUnit(unittest.TestCase):
     def test_mocked_open(self):
         # Create a temporary file on the file system.
         (fd, path) = mkstemp()
         with os.fdopen(fd, 'w') as file:
             file.write('foobar');
 
+        self.assertFalse(os.path.exists('file1'))
+        self.assertFalse(os.path.exists('file2'))
+
         with MockedOpen({'file1': 'content1',
                          'file2': 'content2'}):
+            self.assertTrue(os.path.exists('file1'))
+            self.assertTrue(os.path.exists('file2'))
+            self.assertFalse(os.path.exists('foo/file1'))
+
             # Check the contents of the files given at MockedOpen creation.
             self.assertEqual(open('file1', 'r').read(), 'content1')
             self.assertEqual(open('file2', 'r').read(), 'content2')
 
             # Check that overwriting these files alters their content.
             with open('file1', 'w') as file:
                 file.write('foo')
+            self.assertTrue(os.path.exists('file1'))
             self.assertEqual(open('file1', 'r').read(), 'foo')
 
             # ... but not until the file is closed.
             file = open('file2', 'w')
             file.write('bar')
             self.assertEqual(open('file2', 'r').read(), 'content2')
             file.close()
             self.assertEqual(open('file2', 'r').read(), 'bar')
 
             # Check that appending to a file does append
             with open('file1', 'a') as file:
                 file.write('bar')
             self.assertEqual(open('file1', 'r').read(), 'foobar')
 
+            self.assertFalse(os.path.exists('file3'))
+
             # Opening a non-existing file ought to fail.
             self.assertRaises(IOError, open, 'file3', 'r')
+            self.assertFalse(os.path.exists('file3'))
 
             # Check that writing a new file does create the file.
             with open('file3', 'w') as file:
                 file.write('baz')
             self.assertEqual(open('file3', 'r').read(), 'baz')
+            self.assertTrue(os.path.exists('file3'))
 
             # Check the content of the file created outside MockedOpen.
             self.assertEqual(open(path, 'r').read(), 'foobar')
 
             # Check that overwriting a file existing on the file system
             # does modify its content.
             with open(path, 'w') as file:
                 file.write('bazqux')
--- a/content/base/src/DirectionalityUtils.cpp
+++ b/content/base/src/DirectionalityUtils.cpp
@@ -215,17 +215,17 @@
 #include "nsUnicodeProperties.h"
 #include "nsTextFragment.h"
 #include "nsAttrValue.h"
 #include "nsTextNode.h"
 #include "nsCheapSets.h"
 
 namespace mozilla {
 
-typedef mozilla::dom::Element Element;
+using mozilla::dom::Element;
 
 /**
  * Returns true if aElement is one of the elements whose text content should not
  * affect its own direction, nor the direction of ancestors with dir=auto.
  *
  * Note that this does not include <bdi>, whose content does affect its own
  * direction when it has dir=auto (which it has by default), so one needs to
  * test for it separately, e.g. with DoesNotAffectDirectionOfAncestors.
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -62,17 +62,17 @@ EXPORTS.mozilla.dom += [
     'DOMRect.h',
     'EventSource.h',
     'Link.h',
     'NodeIterator.h',
     'Text.h',
     'TreeWalker.h',
 ]
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'Attr.cpp',
     'ChildIterator.cpp',
     'Comment.cpp',
     'DirectionalityUtils.cpp',
     'DocumentFragment.cpp',
     'DocumentType.cpp',
     'DOMImplementation.cpp',
     'DOMParser.cpp',
@@ -89,22 +89,20 @@ SOURCES += [
     'nsAttrValueOrString.cpp',
     'nsCCUncollectableMarker.cpp',
     'nsChannelPolicy.cpp',
     'nsContentAreaDragDrop.cpp',
     'nsContentIterator.cpp',
     'nsContentList.cpp',
     'nsContentPolicy.cpp',
     'nsContentSink.cpp',
-    'nsContentUtils.cpp',
     'nsCopySupport.cpp',
     'nsCrossSiteListenerProxy.cpp',
     'nsCSPService.cpp',
     'nsDataDocumentContentPolicy.cpp',
-    'nsDocument.cpp',
     'nsDocumentEncoder.cpp',
     'nsDOMAttributeMap.cpp',
     'nsDOMBlobBuilder.cpp',
     'nsDOMCaretPosition.cpp',
     'nsDOMFile.cpp',
     'nsDOMFileReader.cpp',
     'nsDOMLists.cpp',
     'nsDOMMutationObserver.cpp',
@@ -125,19 +123,17 @@ SOURCES += [
     'nsInProcessTabChildGlobal.cpp',
     'nsLineBreaker.cpp',
     'nsMappedAttributeElement.cpp',
     'nsMappedAttributes.cpp',
     'nsMixedContentBlocker.cpp',
     'nsNameSpaceManager.cpp',
     'nsNoDataProtocolContentPolicy.cpp',
     'nsNodeInfo.cpp',
-    'nsNodeInfoManager.cpp',
     'nsNodeUtils.cpp',
-    'nsObjectLoadingContent.cpp',
     'nsPlainTextSerializer.cpp',
     'nsPropertyTable.cpp',
     'nsRange.cpp',
     'nsReferencedElement.cpp',
     'nsScriptElement.cpp',
     'nsScriptLoader.cpp',
     'nsStubDocumentObserver.cpp',
     'nsStubMutationObserver.cpp',
@@ -154,16 +150,28 @@ SOURCES += [
     'nsXMLHttpRequest.cpp',
     'nsXMLNameSpaceMap.cpp',
     'Text.cpp',
     'ThirdPartyUtil.cpp',
     'TreeWalker.cpp',
     'WebSocket.cpp',
 ]
 
+# These files cannot be built in unified mode because they use FORCE_PR_LOG
+SOURCES += [
+    'nsDocument.cpp',
+    'nsNodeInfoManager.cpp',
+]
+
+# These files cannot be built in unified mode because of OS X headers.
+SOURCES += [
+    'nsContentUtils.cpp',
+    'nsObjectLoadingContent.cpp',
+]
+
 EXTRA_COMPONENTS += [
     'contentAreaDropListener.js',
     'contentAreaDropListener.manifest',
     'contentSecurityPolicy.manifest',
     'messageWakeupService.js',
     'messageWakeupService.manifest',
 ]
 
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -17,17 +17,17 @@
 #include "mozilla/css/StyleRule.h"
 #include "nsCSSParser.h"
 #include "mozilla/css/Loader.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsXULElement.h"
 #include "nsContentUtils.h"
 #include "nsStyleUtil.h"
 
-namespace css = mozilla::css;
+using namespace mozilla;
 using namespace mozilla::dom;
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 nsIAtom*
 nsStyledElementNotElementCSSInlineStyle::GetClassAttributeName() const
 {
--- a/content/html/content/public/HTMLVideoElement.h
+++ b/content/html/content/public/HTMLVideoElement.h
@@ -111,14 +111,18 @@ protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   virtual void WakeLockCreate();
   virtual void WakeLockRelease();
   void WakeLockUpdate();
 
   nsCOMPtr<nsIDOMMozWakeLock> mScreenWakeLock;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLVideoElement_h
--- a/content/html/content/src/HTMLBRElement.cpp
+++ b/content/html/content/src/HTMLBRElement.cpp
@@ -52,19 +52,19 @@ HTMLBRElement::ParseAttribute(int32_t aN
   if (aAttribute == nsGkAtoms::clear && aNamespaceID == kNameSpaceID_None) {
     return aResult.ParseEnumValue(aValue, kClearTable, false);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLBRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                     nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
     nsCSSValue* clear = aData->ValueForClear();
     if (clear->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::clear);
       if (value && value->Type() == nsAttrValue::eEnum)
         clear->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
     }
--- a/content/html/content/src/HTMLBRElement.h
+++ b/content/html/content/src/HTMLBRElement.h
@@ -41,15 +41,19 @@ public:
   }
   void SetClear(const nsAString& aClear, ErrorResult& aError)
   {
     return SetHTMLAttr(nsGkAtoms::clear, aClear, aError);
   }
 
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
 
--- a/content/html/content/src/HTMLBodyElement.cpp
+++ b/content/html/content/src/HTMLBodyElement.cpp
@@ -343,18 +343,19 @@ HTMLBodyElement::UnbindFromTree(bool aDe
   if (mContentStyleRule) {
     mContentStyleRule->mPart = nullptr;
     mContentStyleRule = nullptr;
   }
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);  
 }
 
-static 
-void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                       nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
     // When display if first asked for, go ahead and get our colors set up.
     nsIPresShell *presShell = aData->mPresContext->GetPresShell();
     if (presShell) {
       nsIDocument *doc = presShell->GetDocument();
       if (doc) {
         nsHTMLStyleSheet* styleSheet = doc->GetAttributeStyleSheet();
--- a/content/html/content/src/HTMLBodyElement.h
+++ b/content/html/content/src/HTMLBodyElement.h
@@ -131,14 +131,18 @@ public:
 
   virtual bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsRefPtr<BodyRule> mContentStyleRule;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLBodyElement_h___ */
--- a/content/html/content/src/HTMLDivElement.cpp
+++ b/content/html/content/src/HTMLDivElement.cpp
@@ -57,18 +57,19 @@ HTMLDivElement::ParseAttribute(int32_t a
       return ParseDivAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLDivElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                      nsRuleData* aData)
 {
   nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 static void
 MapMarqueeAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
 {
--- a/content/html/content/src/HTMLDivElement.h
+++ b/content/html/content/src/HTMLDivElement.h
@@ -55,14 +55,18 @@ public:
                               nsAttrValue& aResult) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLDivElement_h___ */
--- a/content/html/content/src/HTMLFontElement.cpp
+++ b/content/html/content/src/HTMLFontElement.cpp
@@ -48,19 +48,19 @@ HTMLFontElement::ParseAttribute(int32_t 
       return aResult.ParseColor(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLFontElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                       nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Font)) {
     // face: string list
     nsCSSValue* family = aData->ValueForFontFamily();
     if (family->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::face);
       if (value && value->Type() == nsAttrValue::eString &&
           !value->IsEmptyString()) {
--- a/content/html/content/src/HTMLFontElement.h
+++ b/content/html/content/src/HTMLFontElement.h
@@ -51,14 +51,18 @@ public:
                                 nsAttrValue& aResult) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* HTMLFontElement_h___ */
--- a/content/html/content/src/HTMLFrameElement.cpp
+++ b/content/html/content/src/HTMLFrameElement.cpp
@@ -76,19 +76,19 @@ HTMLFrameElement::ParseAttribute(int32_t
       return ParseScrollingValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
                                                    aValue, aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLFrameElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                        nsRuleData* aData)
 {
   nsGenericHTMLElement::MapScrollingAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLFrameElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
--- a/content/html/content/src/HTMLFrameElement.h
+++ b/content/html/content/src/HTMLFrameElement.h
@@ -94,14 +94,18 @@ public:
   }
 
   using nsGenericHTMLFrameElement::GetContentDocument;
   using nsGenericHTMLFrameElement::GetContentWindow;
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLFrameElement_h
--- a/content/html/content/src/HTMLHRElement.cpp
+++ b/content/html/content/src/HTMLHRElement.cpp
@@ -27,29 +27,29 @@ NS_IMPL_ELEMENT_CLONE(HTMLHRElement)
 
 
 NS_IMPL_STRING_ATTR(HTMLHRElement, Align, align)
 NS_IMPL_BOOL_ATTR(HTMLHRElement, NoShade, noshade)
 NS_IMPL_STRING_ATTR(HTMLHRElement, Size, size)
 NS_IMPL_STRING_ATTR(HTMLHRElement, Width, width)
 NS_IMPL_STRING_ATTR(HTMLHRElement, Color, color)
 
-static const nsAttrValue::EnumTable kAlignTable[] = {
-  { "left", NS_STYLE_TEXT_ALIGN_LEFT },
-  { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
-  { "center", NS_STYLE_TEXT_ALIGN_CENTER },
-  { 0 }
-};
-
 bool
 HTMLHRElement::ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
                               nsAttrValue& aResult)
 {
+  static const nsAttrValue::EnumTable kAlignTable[] = {
+    { "left", NS_STYLE_TEXT_ALIGN_LEFT },
+    { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
+    { "center", NS_STYLE_TEXT_ALIGN_CENTER },
+    { 0 }
+  };
+
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::width) {
       return aResult.ParseSpecialIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::size) {
       return aResult.ParseIntWithBounds(aValue, 1, 1000);
     }
     if (aAttribute == nsGkAtoms::align) {
@@ -59,19 +59,19 @@ HTMLHRElement::ParseAttribute(int32_t aN
       return aResult.ParseColor(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                     nsRuleData* aData)
 {
   bool noshade = false;
 
   const nsAttrValue* colorValue = aAttributes->GetAttr(nsGkAtoms::color);
   nscolor color;
   bool colorIsSet = colorValue && colorValue->GetColorValue(color);
 
   if (aData->mSIDs & (NS_STYLE_INHERIT_BIT(Position) |
--- a/content/html/content/src/HTMLHRElement.h
+++ b/content/html/content/src/HTMLHRElement.h
@@ -68,14 +68,18 @@ public:
   void SetWidth(const nsAString& aWidth, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::width, aWidth, aError);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLHRElement_h
--- a/content/html/content/src/HTMLHeadingElement.cpp
+++ b/content/html/content/src/HTMLHeadingElement.cpp
@@ -45,18 +45,19 @@ HTMLHeadingElement::ParseAttribute(int32
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return ParseDivAlignValue(aValue, aResult);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLHeadingElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                          nsRuleData* aData)
 {
   nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLHeadingElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
--- a/content/html/content/src/HTMLHeadingElement.h
+++ b/content/html/content/src/HTMLHeadingElement.h
@@ -38,14 +38,18 @@ public:
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   // The XPCOM versions of GetAlign and SetAlign are fine for us for
   // use from WebIDL.
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace mozilla
 } // namespace dom
 
 #endif // mozilla_dom_HTMLHeadingElement_h
--- a/content/html/content/src/HTMLIFrameElement.cpp
+++ b/content/html/content/src/HTMLIFrameElement.cpp
@@ -101,19 +101,19 @@ HTMLIFrameElement::ParseAttribute(int32_
       return ParseAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
                                                    aValue, aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLIFrameElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                         nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Border)) {
     // frameborder: 0 | 1 (| NO | YES in quirks mode)
     // If frameborder is 0 or No, set border to 0
     // else leave it as the value set in html.css
     const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::frameborder);
     if (value && value->Type() == nsAttrValue::eEnum) {
       int32_t frameborder = value->GetEnumValue();
--- a/content/html/content/src/HTMLIFrameElement.h
+++ b/content/html/content/src/HTMLIFrameElement.h
@@ -169,14 +169,18 @@ public:
   // nsGenericHTMLFrameElement::GetAppManifestURL is fine
 
 protected:
   virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
   virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
 
   virtual JSObject* WrapNode(JSContext* aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
--- a/content/html/content/src/HTMLImageElement.cpp
+++ b/content/html/content/src/HTMLImageElement.cpp
@@ -227,19 +227,19 @@ HTMLImageElement::ParseAttribute(int32_t
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLImageElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                        nsRuleData* aData)
 {
   nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
--- a/content/html/content/src/HTMLImageElement.h
+++ b/content/html/content/src/HTMLImageElement.h
@@ -185,14 +185,18 @@ protected:
                                  bool aNotify) MOZ_OVERRIDE;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue, bool aNotify) MOZ_OVERRIDE;
 
   // This is a weak reference that this element and the HTMLFormElement
   // cooperate in maintaining.
   HTMLFormElement* mForm;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLImageElement_h */
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -4451,19 +4451,19 @@ HTMLInputElement::ParseAttribute(int32_t
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLInputElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                        nsRuleData* aData)
 {
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
   if (value && value->Type() == nsAttrValue::eEnum &&
       value->GetEnumValue() == NS_FORM_INPUT_IMAGE) {
     nsGenericHTMLFormElementWithState::MapImageBorderAttributeInto(aAttributes, aData);
     nsGenericHTMLFormElementWithState::MapImageMarginAttributeInto(aAttributes, aData);
     nsGenericHTMLFormElementWithState::MapImageSizeAttributesInto(aAttributes, aData);
     // Images treat align as "float"
@@ -6817,8 +6817,10 @@ HTMLInputElement::UpdateHasRange()
 JSObject*
 HTMLInputElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLInputElementBinding::Wrap(aCx, aScope, this);
 }
 
 } // namespace dom
 } // namespace mozilla
+
+#undef NS_ORIGINAL_CHECKED_VALUE
--- a/content/html/content/src/HTMLInputElement.h
+++ b/content/html/content/src/HTMLInputElement.h
@@ -1214,16 +1214,18 @@ protected:
   bool                     mInhibitRestoration  : 1;
   bool                     mCanShowValidUI      : 1;
   bool                     mCanShowInvalidUI    : 1;
   bool                     mHasRange            : 1;
   bool                     mIsDraggingRange     : 1;
   bool                     mProgressTimerIsActive : 1;
 
 private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 
   /**
    * Returns true if this input's type will fire a DOM "change" event when it
    * loses focus if its value has changed since it gained focus.
    */
   bool MayFireChangeOnBlur() const {
     return MayFireChangeOnBlur(mType);
   }
--- a/content/html/content/src/HTMLLIElement.cpp
+++ b/content/html/content/src/HTMLLIElement.cpp
@@ -64,19 +64,19 @@ HTMLLIElement::ParseAttribute(int32_t aN
       return aResult.ParseIntValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLLIElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                     nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(List)) {
     nsCSSValue* listStyleType = aData->ValueForListStyleType();
     if (listStyleType->GetUnit() == eCSSUnit_Null) {
       // type: enum
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
       if (value && value->Type() == nsAttrValue::eEnum)
         listStyleType->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
--- a/content/html/content/src/HTMLLIElement.h
+++ b/content/html/content/src/HTMLLIElement.h
@@ -54,14 +54,18 @@ public:
   void SetValue(int32_t aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLIntAttr(nsGkAtoms::value, aValue, rv);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLLIElement_h
--- a/content/html/content/src/HTMLLegendElement.cpp
+++ b/content/html/content/src/HTMLLegendElement.cpp
@@ -16,26 +16,16 @@ namespace dom {
 
 
 HTMLLegendElement::~HTMLLegendElement()
 {
 }
 
 NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
 
-// this contains center, because IE4 does
-static const nsAttrValue::EnumTable kAlignTable[] = {
-  { "left", NS_STYLE_TEXT_ALIGN_LEFT },
-  { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
-  { "center", NS_STYLE_TEXT_ALIGN_CENTER },
-  { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
-  { "top", NS_STYLE_VERTICAL_ALIGN_TOP },
-  { 0 }
-};
-
 nsIContent*
 HTMLLegendElement::GetFieldSet()
 {
   nsIContent* parent = GetParent();
 
   if (parent && parent->IsHTML(nsGkAtoms::fieldset)) {
     return parent;
   }
@@ -44,16 +34,26 @@ HTMLLegendElement::GetFieldSet()
 }
 
 bool
 HTMLLegendElement::ParseAttribute(int32_t aNamespaceID,
                                   nsIAtom* aAttribute,
                                   const nsAString& aValue,
                                   nsAttrValue& aResult)
 {
+  // this contains center, because IE4 does
+  static const nsAttrValue::EnumTable kAlignTable[] = {
+    { "left", NS_STYLE_TEXT_ALIGN_LEFT },
+    { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
+    { "center", NS_STYLE_TEXT_ALIGN_CENTER },
+    { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
+    { "top", NS_STYLE_VERTICAL_ALIGN_TOP },
+    { 0 }
+  };
+
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return aResult.ParseEnumValue(aValue, kAlignTable, false);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
--- a/content/html/content/src/HTMLMenuItemElement.cpp
+++ b/content/html/content/src/HTMLMenuItemElement.cpp
@@ -485,8 +485,10 @@ HTMLMenuItemElement::InitChecked()
 JSObject*
 HTMLMenuItemElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return HTMLMenuItemElementBinding::Wrap(aCx, aScope, this);
 }
 
 } // namespace dom
 } // namespace mozilla
+
+#undef NS_ORIGINAL_CHECKED_VALUE
--- a/content/html/content/src/HTMLObjectElement.cpp
+++ b/content/html/content/src/HTMLObjectElement.cpp
@@ -361,19 +361,19 @@ HTMLObjectElement::ParseAttribute(int32_
       return true;
     }
   }
 
   return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
                                                   aValue, aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
-                      nsRuleData *aData)
+void
+HTMLObjectElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
+                                         nsRuleData *aData)
 {
   nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
   nsGenericHTMLFormElement::MapImageMarginAttributeInto(aAttributes, aData);
   nsGenericHTMLFormElement::MapImageSizeAttributesInto(aAttributes, aData);
   nsGenericHTMLFormElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
--- a/content/html/content/src/HTMLObjectElement.h
+++ b/content/html/content/src/HTMLObjectElement.h
@@ -234,15 +234,18 @@ private:
   bool IsFocusableForTabIndex();
   
   virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
   virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
 
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
+
   bool mIsDoneAddingChildren;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLObjectElement_h
--- a/content/html/content/src/HTMLParagraphElement.cpp
+++ b/content/html/content/src/HTMLParagraphElement.cpp
@@ -36,18 +36,19 @@ HTMLParagraphElement::ParseAttribute(int
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return ParseDivAlignValue(aValue, aResult);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLParagraphElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                            nsRuleData* aData)
 {
   nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLParagraphElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
--- a/content/html/content/src/HTMLParagraphElement.h
+++ b/content/html/content/src/HTMLParagraphElement.h
@@ -45,14 +45,18 @@ public:
   void SetAlign(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::align, aValue, rv);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLParagraphElement_h
--- a/content/html/content/src/HTMLPreElement.cpp
+++ b/content/html/content/src/HTMLPreElement.cpp
@@ -42,19 +42,19 @@ HTMLPreElement::ParseAttribute(int32_t a
       return aResult.ParseIntWithBounds(aValue, 0);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLPreElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                      nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     nsCSSValue* width = aData->ValueForWidth();
     if (width->GetUnit() == eCSSUnit_Null) {
       // width: int (html4 attribute == nav4 cols)
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
       if (!value || value->Type() != nsAttrValue::eInteger) {
         // cols: int (nav4 attribute)
--- a/content/html/content/src/HTMLPreElement.h
+++ b/content/html/content/src/HTMLPreElement.h
@@ -49,14 +49,18 @@ public:
   void SetWidth(int32_t aWidth, mozilla::ErrorResult& rv)
   {
     rv = SetIntAttr(nsGkAtoms::width, aWidth);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLPreElement_h
--- a/content/html/content/src/HTMLSelectElement.cpp
+++ b/content/html/content/src/HTMLSelectElement.cpp
@@ -1421,19 +1421,19 @@ HTMLSelectElement::ParseAttribute(int32_
 {
   if (aAttribute == nsGkAtoms::size && kNameSpaceID_None == aNamespaceID) {
     return aResult.ParsePositiveIntValue(aValue);
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLSelectElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                         nsRuleData* aData)
 {
   nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
 }
 
 nsChangeHint
 HTMLSelectElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                           int32_t aModType) const
--- a/content/html/content/src/HTMLSelectElement.h
+++ b/content/html/content/src/HTMLSelectElement.h
@@ -642,14 +642,18 @@ protected:
    * done adding options
    */
   nsCOMPtr<SelectState> mRestoreState;
 
   /**
    * The live list of selected options.
   */
   nsRefPtr<nsContentList> mSelectedOptions;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSelectElement_h
--- a/content/html/content/src/HTMLSharedListElement.cpp
+++ b/content/html/content/src/HTMLSharedListElement.cpp
@@ -84,18 +84,19 @@ HTMLSharedListElement::ParseAttribute(in
       }
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLSharedListElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                             nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(List)) {
     nsCSSValue* listStyleType = aData->ValueForListStyleType();
     if (listStyleType->GetUnit() == eCSSUnit_Null) {
       // type: enum
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
       if (value) {
         if (value->Type() == nsAttrValue::eEnum)
--- a/content/html/content/src/HTMLSharedListElement.h
+++ b/content/html/content/src/HTMLSharedListElement.h
@@ -74,14 +74,18 @@ public:
   void SetCompact(bool aCompact, mozilla::ErrorResult& rv)
   {
     SetHTMLBoolAttr(nsGkAtoms::compact, aCompact, rv);
   }
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSharedListElement_h
--- a/content/html/content/src/HTMLSharedObjectElement.cpp
+++ b/content/html/content/src/HTMLSharedObjectElement.cpp
@@ -255,19 +255,19 @@ MapAttributesIntoRuleBase(const nsMapped
 static void
 MapAttributesIntoRuleExceptHidden(const nsMappedAttributes *aAttributes,
                                   nsRuleData *aData)
 {
   MapAttributesIntoRuleBase(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesIntoExceptHidden(aAttributes, aData);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
-                      nsRuleData *aData)
+void
+HTMLSharedObjectElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
+                                               nsRuleData *aData)
 {
   MapAttributesIntoRuleBase(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLSharedObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
 {
--- a/content/html/content/src/HTMLSharedObjectElement.h
+++ b/content/html/content/src/HTMLSharedObjectElement.h
@@ -218,14 +218,17 @@ private:
   // always true for <embed>, per the documentation in nsIContent.h.
   bool mIsDoneAddingChildren;
 
   virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
   virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
 
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSharedObjectElement_h
--- a/content/html/content/src/HTMLTableCaptionElement.cpp
+++ b/content/html/content/src/HTMLTableCaptionElement.cpp
@@ -50,18 +50,19 @@ HTMLTableCaptionElement::ParseAttribute(
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return aResult.ParseEnumValue(aValue, kCaptionAlignTable, false);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static 
-void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLTableCaptionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                               nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(TableBorder)) {
     nsCSSValue* captionSide = aData->ValueForCaptionSide();
     if (captionSide->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::align);
       if (value && value->Type() == nsAttrValue::eEnum)
         captionSide->SetIntValue(value->GetEnumValue(), eCSSUnit_Enumerated);
     }
--- a/content/html/content/src/HTMLTableCaptionElement.h
+++ b/content/html/content/src/HTMLTableCaptionElement.h
@@ -44,14 +44,18 @@ public:
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableCaptionElement_h */
--- a/content/html/content/src/HTMLTableCellElement.cpp
+++ b/content/html/content/src/HTMLTableCellElement.cpp
@@ -430,19 +430,19 @@ HTMLTableCellElement::ParseAttribute(int
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static 
-void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                           nsRuleData* aData)
+void
+HTMLTableCellElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                            nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // width: value
     nsCSSValue* width = aData->ValueForWidth();
     if (width->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
       if (value && value->Type() == nsAttrValue::eInteger) {
         if (value->GetIntegerValue() > 0)
--- a/content/html/content/src/HTMLTableCellElement.h
+++ b/content/html/content/src/HTMLTableCellElement.h
@@ -157,14 +157,18 @@ public:
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   HTMLTableElement* GetTable() const;
 
   HTMLTableRowElement* GetRow() const;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableCellElement_h */
--- a/content/html/content/src/HTMLTableColElement.cpp
+++ b/content/html/content/src/HTMLTableColElement.cpp
@@ -57,18 +57,19 @@ HTMLTableColElement::ParseAttribute(int3
       return ParseTableVAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static 
-void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLTableColElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                           nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Table)) {
     nsCSSValue *span = aData->ValueForSpan();
     if (span->GetUnit() == eCSSUnit_Null) {
       // span: int
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::span);
       if (value && value->Type() == nsAttrValue::eInteger) {
         int32_t val = value->GetIntegerValue();
--- a/content/html/content/src/HTMLTableColElement.h
+++ b/content/html/content/src/HTMLTableColElement.h
@@ -77,14 +77,18 @@ public:
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const MOZ_OVERRIDE;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableColElement_h */
--- a/content/html/content/src/HTMLTableElement.cpp
+++ b/content/html/content/src/HTMLTableElement.cpp
@@ -696,19 +696,19 @@ HTMLTableElement::ParseAttribute(int32_t
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLTableElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                        nsRuleData* aData)
 {
   // XXX Bug 211636:  This function is used by a single style rule
   // that's used to match two different type of elements -- tables, and
   // table cells.  (nsHTMLTableCellElement overrides
   // WalkContentStyleRules so that this happens.)  This violates the
   // nsIStyleRule contract, since it's the same style rule object doing
   // the mapping in two different ways.  It's also incorrect since it's
   // testing the display type of the style context rather than checking
--- a/content/html/content/src/HTMLTableElement.h
+++ b/content/html/content/src/HTMLTableElement.h
@@ -217,14 +217,18 @@ protected:
 
   nsRefPtr<nsContentList> mTBodies;
   nsRefPtr<TableRowsCollection> mRows;
   // Sentinel value of TABLE_ATTRS_DIRTY indicates that this is dirty and needs
   // to be recalculated.
   nsMappedAttributes *mTableInheritedAttributes;
   void BuildInheritedAttributes();
   void ReleaseInheritedAttributes();
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableElement_h */
--- a/content/html/content/src/HTMLTableRowElement.cpp
+++ b/content/html/content/src/HTMLTableRowElement.cpp
@@ -256,18 +256,19 @@ HTMLTableRowElement::ParseAttribute(int3
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static 
-void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLTableRowElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                           nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // height: value
     nsCSSValue* height = aData->ValueForHeight();
     if (height->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger)
         height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
--- a/content/html/content/src/HTMLTableRowElement.h
+++ b/content/html/content/src/HTMLTableRowElement.h
@@ -91,14 +91,18 @@ public:
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   HTMLTableSectionElement* GetSection() const;
   HTMLTableElement* GetTable() const;
   nsRefPtr<nsContentList> mCells;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableRowElement_h */
--- a/content/html/content/src/HTMLTableSectionElement.cpp
+++ b/content/html/content/src/HTMLTableSectionElement.cpp
@@ -156,18 +156,19 @@ HTMLTableSectionElement::ParseAttribute(
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static
-void MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
+void
+HTMLTableSectionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                               nsRuleData* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)) {
     // height: value
     nsCSSValue* height = aData->ValueForHeight();
     if (height->GetUnit() == eCSSUnit_Null) {
       const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
       if (value && value->Type() == nsAttrValue::eInteger)
         height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
--- a/content/html/content/src/HTMLTableSectionElement.h
+++ b/content/html/content/src/HTMLTableSectionElement.h
@@ -72,14 +72,18 @@ public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableSectionElement,
                                                      nsGenericHTMLElement)
 protected:
   virtual JSObject* WrapNode(JSContext *aCx,
                              JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsRefPtr<nsContentList> mRows;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLTableSectionElement_h */
--- a/content/html/content/src/HTMLTextAreaElement.cpp
+++ b/content/html/content/src/HTMLTextAreaElement.cpp
@@ -395,19 +395,19 @@ HTMLTextAreaElement::ParseAttribute(int3
                aAttribute == nsGkAtoms::rows) {
       return aResult.ParsePositiveIntValue(aValue);
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLTextAreaElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                           nsRuleData* aData)
 {
   nsGenericHTMLFormElementWithState::MapDivAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
 }
 
 nsChangeHint
 HTMLTextAreaElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
                                             int32_t aModType) const
--- a/content/html/content/src/HTMLTextAreaElement.h
+++ b/content/html/content/src/HTMLTextAreaElement.h
@@ -351,15 +351,19 @@ protected:
   bool IsMutable() const;
 
   /**
    * Returns whether the current value is the empty string.
    *
    * @return whether the current value is the empty string.
    */
   bool IsValueEmpty() const;
+
+private:
+  static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                    nsRuleData* aData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif
 
--- a/content/html/content/src/HTMLVideoElement.cpp
+++ b/content/html/content/src/HTMLVideoElement.cpp
@@ -97,19 +97,19 @@ HTMLVideoElement::ParseAttribute(int32_t
    if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) {
      return aResult.ParseSpecialIntValue(aValue);
    }
 
    return HTMLMediaElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                            aResult);
 }
 
-static void
-MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
-                      nsRuleData* aData)
+void
+HTMLVideoElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
+                                        nsRuleData* aData)
 {
   nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
 }
 
 NS_IMETHODIMP_(bool)
 HTMLVideoElement::IsAttributeMapped(const nsIAtom* aAttribute) const
 {
--- a/content/html/content/src/moz.build
+++ b/content/html/content/src/moz.build
@@ -70,17 +70,17 @@ EXPORTS.mozilla.dom += [
     'HTMLUnknownElement.h',
     'MediaError.h',
     'TextTrackManager.h',
     'TimeRanges.h',
     'UndoManager.h',
     'ValidityState.h',
 ]
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'HTMLAnchorElement.cpp',
     'HTMLAreaElement.cpp',
     'HTMLAudioElement.cpp',
     'HTMLBodyElement.cpp',
     'HTMLBRElement.cpp',
     'HTMLButtonElement.cpp',
     'HTMLCanvasElement.cpp',
     'HTMLDataElement.cpp',
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1177,34 +1177,16 @@ nsGenericHTMLElement::GetPresContext()
     if (presShell) {
       return presShell->GetPresContext();
     }
   }
 
   return nullptr;
 }
 
-static const nsAttrValue::EnumTable kAlignTable[] = {
-  { "left",      NS_STYLE_TEXT_ALIGN_LEFT },
-  { "right",     NS_STYLE_TEXT_ALIGN_RIGHT },
-
-  { "top",       NS_STYLE_VERTICAL_ALIGN_TOP },
-  { "middle",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
-  { "bottom",    NS_STYLE_VERTICAL_ALIGN_BASELINE },
-
-  { "center",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
-  { "baseline",  NS_STYLE_VERTICAL_ALIGN_BASELINE },
-
-  { "texttop",   NS_STYLE_VERTICAL_ALIGN_TEXT_TOP },
-  { "absmiddle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
-  { "abscenter", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
-  { "absbottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
-  { 0 }
-};
-
 static const nsAttrValue::EnumTable kDivAlignTable[] = {
   { "left", NS_STYLE_TEXT_ALIGN_MOZ_LEFT },
   { "right", NS_STYLE_TEXT_ALIGN_MOZ_RIGHT },
   { "center", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
   { "middle", NS_STYLE_TEXT_ALIGN_MOZ_CENTER },
   { "justify", NS_STYLE_TEXT_ALIGN_JUSTIFY },
   { 0 }
 };
@@ -1235,16 +1217,34 @@ static const nsAttrValue::EnumTable kTab
   { "baseline",NS_STYLE_VERTICAL_ALIGN_BASELINE },
   { 0 }
 };
 
 bool
 nsGenericHTMLElement::ParseAlignValue(const nsAString& aString,
                                       nsAttrValue& aResult)
 {
+  static const nsAttrValue::EnumTable kAlignTable[] = {
+    { "left",      NS_STYLE_TEXT_ALIGN_LEFT },
+    { "right",     NS_STYLE_TEXT_ALIGN_RIGHT },
+
+    { "top",       NS_STYLE_VERTICAL_ALIGN_TOP },
+    { "middle",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
+    { "bottom",    NS_STYLE_VERTICAL_ALIGN_BASELINE },
+
+    { "center",    NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
+    { "baseline",  NS_STYLE_VERTICAL_ALIGN_BASELINE },
+
+    { "texttop",   NS_STYLE_VERTICAL_ALIGN_TEXT_TOP },
+    { "absmiddle", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
+    { "abscenter", NS_STYLE_VERTICAL_ALIGN_MIDDLE },
+    { "absbottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
+    { 0 }
+  };
+
   return aResult.ParseEnumValue(aString, kAlignTable, false);
 }
 
 //----------------------------------------
 
 static const nsAttrValue::EnumTable kTableHAlignTable[] = {
   { "left",   NS_STYLE_TEXT_ALIGN_LEFT },
   { "right",  NS_STYLE_TEXT_ALIGN_RIGHT },
--- a/content/html/document/src/moz.build
+++ b/content/html/document/src/moz.build
@@ -8,17 +8,17 @@ EXPORTS += [
     'nsIHTMLDocument.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'HTMLAllCollection.h',
     'ImageDocument.h',
 ]
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'HTMLAllCollection.cpp',
     'ImageDocument.cpp',
     'MediaDocument.cpp',
     'nsHTMLContentSink.cpp',
     'nsHTMLDocument.cpp',
     'PluginDocument.cpp',
     'VideoDocument.cpp',
 ]
--- a/content/media/DecoderTraits.cpp
+++ b/content/media/DecoderTraits.cpp
@@ -471,17 +471,17 @@ DecoderTraits::CreateDecoder(const nsACS
     decoder = new WaveDecoder();
   }
 #endif
 #ifdef MOZ_OMX_DECODER
   if (IsOmxSupportedType(aType)) {
     // AMR audio is enabled for MMS, but we are discouraging Web and App
     // developers from using AMR, thus we only allow AMR to be played on WebApps.
     if (aType.EqualsASCII("audio/amr")) {
-      HTMLMediaElement* element = aOwner->GetMediaElement();
+      dom::HTMLMediaElement* element = aOwner->GetMediaElement();
       if (!element) {
         return nullptr;
       }
       nsIPrincipal* principal = element->NodePrincipal();
       if (!principal) {
         return nullptr;
       }
       if (principal->GetAppStatus() < nsIPrincipal::APP_STATUS_PRIVILEGED) {
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -565,17 +565,17 @@ nsresult MediaDecoder::Play()
 /**
  * Returns true if aValue is inside a range of aRanges, and put the range
  * index in aIntervalIndex if it is not null.
  * If aValue is not inside a range, false is returned, and aIntervalIndex, if
  * not null, is set to the index of the range which ends immediately before aValue
  * (and can be -1 if aValue is before aRanges.Start(0)).
  */
 static bool
-IsInRanges(TimeRanges& aRanges, double aValue, int32_t& aIntervalIndex)
+IsInRanges(dom::TimeRanges& aRanges, double aValue, int32_t& aIntervalIndex)
 {
   uint32_t length;
   aRanges.GetLength(&length);
   for (uint32_t i = 0; i < length; i++) {
     double start, end;
     aRanges.Start(i, &start);
     if (start > aValue) {
       aIntervalIndex = i - 1;
@@ -593,17 +593,17 @@ IsInRanges(TimeRanges& aRanges, double a
 
 nsresult MediaDecoder::Seek(double aTime)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
 
   NS_ABORT_IF_FALSE(aTime >= 0.0, "Cannot seek to a negative value.");
 
-  TimeRanges seekable;
+  dom::TimeRanges seekable;
   nsresult res;
   uint32_t length = 0;
   res = GetSeekable(&seekable);
   NS_ENSURE_SUCCESS(res, NS_OK);
 
   seekable.GetLength(&length);
   if (!length) {
     return NS_OK;
@@ -1321,17 +1321,17 @@ bool MediaDecoder::IsTransportSeekable()
 bool MediaDecoder::IsMediaSeekable()
 {
   NS_ENSURE_TRUE(GetStateMachine(), false);
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   MOZ_ASSERT(OnDecodeThread() || NS_IsMainThread());
   return mMediaSeekable;
 }
 
-nsresult MediaDecoder::GetSeekable(TimeRanges* aSeekable)
+nsresult MediaDecoder::GetSeekable(dom::TimeRanges* aSeekable)
 {
   double initialTime = 0.0;
 
   // We can seek in buffered range if the media is seekable. Also, we can seek
   // in unbuffered ranges if the transport level is seekable (local file or the
   // server supports range requests, etc.)
   if (!IsMediaSeekable()) {
     return NS_OK;
@@ -1487,17 +1487,17 @@ void MediaDecoder::Invalidate()
 {
   if (mVideoFrameContainer) {
     mVideoFrameContainer->Invalidate();
   }
 }
 
 // Constructs the time ranges representing what segments of the media
 // are buffered and playable.
-nsresult MediaDecoder::GetBuffered(TimeRanges* aBuffered) {
+nsresult MediaDecoder::GetBuffered(dom::TimeRanges* aBuffered) {
   if (mDecoderStateMachine) {
     return mDecoderStateMachine->GetBuffered(aBuffered);
   }
   return NS_ERROR_FAILURE;
 }
 
 int64_t MediaDecoder::VideoQueueMemoryInUse() {
   if (mDecoderStateMachine) {
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -196,18 +196,16 @@ class nsIPrincipal;
 class nsITimer;
 
 namespace mozilla {
 namespace dom {
 class TimeRanges;
 }
 }
 
-using namespace mozilla::dom;
-
 namespace mozilla {
 namespace layers {
 class Image;
 } //namespace layers
 
 class VideoFrameContainer;
 class MediaDecoderStateMachine;
 class MediaDecoderOwner;
@@ -227,18 +225,16 @@ static const uint32_t FRAMEBUFFER_LENGTH
 #ifdef GetCurrentTime
 #undef GetCurrentTime
 #endif
 
 class MediaDecoder : public nsIObserver,
                      public AbstractMediaDecoder
 {
 public:
-  typedef mozilla::layers::Image Image;
-
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   // Enumeration for the valid play states (see mPlayState)
   enum PlayState {
     PLAY_STATE_START,
     PLAY_STATE_LOADING,
     PLAY_STATE_PAUSED,
@@ -366,17 +362,17 @@ public:
     int64_t mInitialTime; // microseconds
     // mNextVideoTime is the end timestamp for the last packet sent to the stream.
     // Therefore video packets starting at or after this time need to be copied
     // to the output stream.
     int64_t mNextVideoTime; // microseconds
     MediaDecoder* mDecoder;
     // The last video image sent to the stream. Useful if we need to replicate
     // the image.
-    nsRefPtr<Image> mLastVideoImage;
+    nsRefPtr<layers::Image> mLastVideoImage;
     gfxIntSize mLastVideoImageDisplaySize;
     // This is set to true when the stream is initialized (audio and
     // video tracks added).
     bool mStreamInitialized;
     bool mHaveSentFinish;
     bool mHaveSentFinishAudio;
     bool mHaveSentFinishVideo;
 
@@ -518,17 +514,17 @@ public:
   // Returns true if this media supports seeking. False for example for WebM
   // files without an index and chained ogg files.
   virtual bool IsMediaSeekable() MOZ_FINAL MOZ_OVERRIDE;
   // Returns true if seeking is supported on a transport level (e.g. the server
   // supports range requests, we are playing a file, etc.).
   virtual bool IsTransportSeekable();
 
   // Return the time ranges that can be seeked into.
-  virtual nsresult GetSeekable(TimeRanges* aSeekable);
+  virtual nsresult GetSeekable(dom::TimeRanges* aSeekable);
 
   // Set the end time of the media resource. When playback reaches
   // this point the media pauses. aTime is in seconds.
   virtual void SetFragmentEndTime(double aTime);
 
   // Set the end time of the media. aTime is in microseconds.
   void SetMediaEndTime(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
 
@@ -554,17 +550,17 @@ public:
   // Moves any existing channel loads into the background, so that they don't
   // block the load event. This is called when we stop delaying the load
   // event. Any new loads initiated (for example to seek) will also be in the
   // background. Implementations of this must call MoveLoadsToBackground() on
   // their MediaResource.
   virtual void MoveLoadsToBackground();
 
   // Returns a weak reference to the media decoder owner.
-  mozilla::MediaDecoderOwner* GetMediaOwner() const;
+  MediaDecoderOwner* GetMediaOwner() const;
 
   // Returns the current size of the framebuffer used in
   // MozAudioAvailable events.
   uint32_t GetFrameBufferLength() { return mFrameBufferLength; }
 
   void AudioAvailable(float* aFrameBuffer, uint32_t aFrameBufferLength, float aTime);
 
   // Called by the state machine to notify the decoder that the duration
@@ -579,28 +575,28 @@ public:
   // state.
   ReentrantMonitor& GetReentrantMonitor() MOZ_OVERRIDE;
 
   // Returns true if the decoder is shut down
   bool IsShutdown() const MOZ_FINAL MOZ_OVERRIDE;
 
   // Constructs the time ranges representing what segments of the media
   // are buffered and playable.
-  virtual nsresult GetBuffered(TimeRanges* aBuffered);
+  virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
 
   // Returns the size, in bytes, of the heap memory used by the currently
   // queued decoded video and audio data.
   virtual int64_t VideoQueueMemoryInUse();
   virtual int64_t AudioQueueMemoryInUse();
 
   VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE
   {
     return mVideoFrameContainer;
   }
-  mozilla::layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
+  layers::ImageContainer* GetImageContainer() MOZ_OVERRIDE;
 
   // Sets the length of the framebuffer used in MozAudioAvailable events.
   // The new size must be between 512 and 16384.
   virtual nsresult RequestFrameBufferLength(uint32_t aLength);
 
   // Return the current state. Can be called on any thread. If called from
   // a non-main thread, the decoder monitor must be held.
   PlayState GetState() {
@@ -656,18 +652,18 @@ public:
   bool CanPlayThrough();
 
   // Make the decoder state machine update the playback position. Called by
   // the reader on the decoder thread (Assertions for this checked by
   // mDecoderStateMachine). This must be called with the decode monitor
   // held.
   void UpdatePlaybackPosition(int64_t aTime) MOZ_FINAL MOZ_OVERRIDE;
 
-  void SetAudioChannelType(AudioChannelType aType) { mAudioChannelType = aType; }
-  AudioChannelType GetAudioChannelType() { return mAudioChannelType; }
+  void SetAudioChannelType(dom::AudioChannelType aType) { mAudioChannelType = aType; }
+  dom::AudioChannelType GetAudioChannelType() { return mAudioChannelType; }
 
   // Send a new set of metadata to the state machine, to be dispatched to the
   // main thread to be presented when the |currentTime| of the media is greater
   // or equal to aPublishTime.
   void QueueMetadata(int64_t aPublishTime,
                      int aChannels,
                      int aRate,
                      bool aHasAudio,
@@ -922,16 +918,17 @@ public:
 
   // Increments the parsed and decoded frame counters by the passed in counts.
   // Can be called on any thread.
   virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE
   {
     GetFrameStatistics().NotifyDecodedFrames(aParsed, aDecoded);
   }
 
+protected:
   /******
    * The following members should be accessed with the decoder lock held.
    ******/
 
   // Current decoding position in the stream. This is where the decoder
   // is up to consuming the stream. This is not adjusted during decoder
   // seek operations, but it's updated at the end when we start playing
   // back again.
@@ -1020,17 +1017,17 @@ private:
     }
   private:
     ReentrantMonitor mReentrantMonitor;
   };
 
   // The |RestrictedAccessMonitor| member object.
   RestrictedAccessMonitor mReentrantMonitor;
 
-public:
+protected:
   // Data about MediaStreams that are being fed by this decoder.
   nsTArray<OutputStreamData> mOutputStreams;
   // The SourceMediaStream we are using to feed the mOutputStreams. This stream
   // is never exposed outside the decoder.
   // Only written on the main thread while holding the monitor. Therefore it
   // can be read on any thread while holding the monitor, or on the main thread
   // without holding the monitor.
   nsAutoPtr<DecodedStreamData> mDecodedStream;
@@ -1082,18 +1079,16 @@ public:
 
   // True if the stream is infinite (e.g. a webradio).
   bool mInfiniteStream;
 
   // True if NotifyDecodedStreamMainThreadStateChanged should retrigger
   // PlaybackEnded when mDecodedStream->mStream finishes.
   bool mTriggerPlaybackEndedWhenSourceStreamFinishes;
 
-protected:
-
   // Start timer to update download progress information.
   nsresult StartProgress();
 
   // Stop progress information timer.
   nsresult StopProgress();
 
   // Ensures our media stream has been pinned.
   void PinForSeek();
@@ -1143,14 +1138,14 @@ protected:
   // Read/Write from the main thread only.
   bool mShuttingDown;
 
   // True if the playback is paused because the playback rate member is 0.0.
   bool mPausedForPlaybackRateNull;
 
   // Be assigned from media element during the initialization and pass to
   // AudioStream Class.
-  AudioChannelType mAudioChannelType;
+  dom::AudioChannelType mAudioChannelType;
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1600,17 +1600,17 @@ void MediaDecoderStateMachine::NotifyDat
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
 
   // While playing an unseekable stream of unknown duration, mEndTime is
   // updated (in AdvanceFrame()) as we play. But if data is being downloaded
   // faster than played, mEndTime won't reflect the end of playable data
   // since we haven't played the frame at the end of buffered data. So update
   // mEndTime here as new data is downloaded to prevent such a lag.
-  TimeRanges buffered;
+  dom::TimeRanges buffered;
   if (mDecoder->IsInfinite() &&
       NS_SUCCEEDED(mDecoder->GetBuffered(&buffered)))
   {
     uint32_t length = 0;
     buffered.GetLength(&length);
     if (length) {
       double end = 0;
       buffered.End(length - 1, &end);
@@ -2699,17 +2699,17 @@ void MediaDecoderStateMachine::StartBuff
   MediaDecoder::Statistics stats = mDecoder->GetStatistics();
 #endif
   LOG(PR_LOG_DEBUG, ("%p Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
     mDecoder.get(),
     stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
     stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)"));
 }
 
-nsresult MediaDecoderStateMachine::GetBuffered(TimeRanges* aBuffered) {
+nsresult MediaDecoderStateMachine::GetBuffered(dom::TimeRanges* aBuffered) {
   MediaResource* resource = mDecoder->GetResource();
   NS_ENSURE_TRUE(resource, NS_ERROR_FAILURE);
   resource->Pin();
   nsresult res = mReader->GetBuffered(aBuffered, mStartTime);
   resource->Unpin();
   return res;
 }
 
--- a/content/media/MediaDecoderStateMachine.h
+++ b/content/media/MediaDecoderStateMachine.h
@@ -250,17 +250,17 @@ public:
 
   // Must be called with the decode monitor held.
   bool IsSeeking() const {
     AssertCurrentThreadInMonitor();
 
     return mState == DECODER_STATE_SEEKING;
   }
 
-  nsresult GetBuffered(TimeRanges* aBuffered);
+  nsresult GetBuffered(dom::TimeRanges* aBuffered);
 
   void SetPlaybackRate(double aPlaybackRate);
   void SetPreservesPitch(bool aPreservesPitch);
 
   int64_t VideoQueueMemoryInUse() {
     if (mReader) {
       return mReader->VideoQueueMemoryInUse();
     }
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -142,17 +142,17 @@ ChannelMediaResource::Listener::GetInter
 
 nsresult
 ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
 {
   NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
   nsresult status;
   nsresult rv = aRequest->GetStatus(&status);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (element->ShouldCheckAllowOrigin()) {
     // If the request was cancelled by nsCORSListenerProxy due to failing
     // the CORS security check, send an error through to the media element.
@@ -578,17 +578,17 @@ nsresult ChannelMediaResource::OpenChann
     mChannel->SetNotificationCallbacks(mListener.get());
 
     nsCOMPtr<nsIStreamListener> listener = mListener.get();
 
     // Ensure that if we're loading cross domain, that the server is sending
     // an authorizing Access-Control header.
     MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
     NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
-    HTMLMediaElement* element = owner->GetMediaElement();
+    dom::HTMLMediaElement* element = owner->GetMediaElement();
     NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
     if (element->ShouldCheckAllowOrigin()) {
       nsRefPtr<nsCORSListenerProxy> crossSiteListener =
         new nsCORSListenerProxy(mListener,
                                 element->NodePrincipal(),
                                 false);
       nsresult rv = crossSiteListener->Init(mChannel);
       listener = crossSiteListener;
@@ -637,17 +637,17 @@ void ChannelMediaResource::SetupChannelH
     hc->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false);
 
     // Send Accept header for video and audio types only (Bug 489071)
     NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
     MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
     if (!owner) {
       return;
     }
-    HTMLMediaElement* element = owner->GetMediaElement();
+    dom::HTMLMediaElement* element = owner->GetMediaElement();
     if (!element) {
       return;
     }
     element->SetRequestHeaders(hc);
   } else {
     NS_ASSERTION(mOffset == 0, "Don't know how to seek on this channel type");
   }
 }
@@ -800,17 +800,17 @@ void ChannelMediaResource::Suspend(bool 
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   if (!owner) {
     // Shutting down; do nothing.
     return;
   }
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
     // Shutting down; do nothing.
     return;
   }
 
   if (mChannel) {
     if (aCloseImmediately && mCacheStream.IsTransportSeekable()) {
       // Kill off our channel right now, but don't tell anyone about it.
@@ -835,17 +835,17 @@ void ChannelMediaResource::Resume()
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
   NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   if (!owner) {
     // Shutting down; do nothing.
     return;
   }
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
     // Shutting down; do nothing.
     return;
   }
 
   NS_ASSERTION(mSuspendCount > 0, "Resume without previous Suspend!");
   --mSuspendCount;
   if (mSuspendCount == 0) {
@@ -884,17 +884,17 @@ ChannelMediaResource::RecreateChannel()
     nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
     (mLoadInBackground ? nsIRequest::LOAD_BACKGROUND : 0);
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   if (!owner) {
     // The decoder is being shut down, so don't bother opening a new channel
     return NS_OK;
   }
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
     // The decoder is being shut down, so don't bother opening a new channel
     return NS_OK;
   }
   nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup();
   NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER);
 
   nsresult rv = NS_NewChannel(getter_AddRefs(mChannel),
@@ -1304,17 +1304,17 @@ nsresult FileMediaResource::Open(nsIStre
     } else if (IsBlobURI(mURI)) {
       rv = NS_GetStreamForBlobURI(mURI, getter_AddRefs(mInput));
     }
   } else {
     // Ensure that we never load a local file from some page on a
     // web server.
     MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
     NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
-    HTMLMediaElement* element = owner->GetMediaElement();
+    dom::HTMLMediaElement* element = owner->GetMediaElement();
     NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
 
     rv = nsContentUtils::GetSecurityManager()->
            CheckLoadURIWithPrincipal(element->NodePrincipal(),
                                      mURI,
                                      nsIScriptSecurityManager::STANDARD);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1369,17 +1369,17 @@ already_AddRefed<MediaResource> FileMedi
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   if (!owner) {
     // The decoder is being shut down, so we can't clone
     return nullptr;
   }
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
     // The decoder is being shut down, so we can't clone
     return nullptr;
   }
   nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup();
   NS_ENSURE_TRUE(loadGroup, nullptr);
 
   nsCOMPtr<nsIChannel> channel;
@@ -1528,17 +1528,17 @@ void BaseMediaResource::MoveLoadsToBackg
     return;
   }
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   if (!owner) {
     NS_WARNING("Null owner in MediaResource::MoveLoadsToBackground()");
     return;
   }
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
     NS_WARNING("Null element in MediaResource::MoveLoadsToBackground()");
     return;
   }
 
   bool isPending = false;
   if (NS_SUCCEEDED(mChannel->IsPending(&isPending)) &&
       isPending) {
--- a/content/media/RtspMediaResource.cpp
+++ b/content/media/RtspMediaResource.cpp
@@ -499,17 +499,17 @@ RtspMediaResource::OnConnected(uint8_t a
     }
   }
   // Fires an initial progress event and sets up the stall counter so stall events
   // fire if no download occurs within the required time frame.
   mDecoder->Progress(false);
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
 
   element->FinishDecoderSetup(mDecoder, this);
   mIsConnected = true;
 
   return NS_OK;
 }
 
@@ -530,30 +530,30 @@ RtspMediaResource::OnDisconnected(uint8_
 }
 
 void RtspMediaResource::Suspend(bool aCloseImmediately)
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   NS_ENSURE_TRUE_VOID(owner);
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   NS_ENSURE_TRUE_VOID(element);
 
   mMediaStreamController->Suspend();
   element->DownloadSuspended();
 }
 
 void RtspMediaResource::Resume()
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   NS_ENSURE_TRUE_VOID(owner);
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   NS_ENSURE_TRUE_VOID(element);
 
   if (mChannel) {
     element->DownloadResumed();
   }
   mMediaStreamController->Resume();
 }
 
--- a/content/media/gstreamer/GStreamerReader.cpp
+++ b/content/media/gstreamer/GStreamerReader.cpp
@@ -649,17 +649,17 @@ nsresult GStreamerReader::Seek(int64_t a
     LOG(PR_LOG_ERROR, ("seek failed"));
     return NS_ERROR_FAILURE;
   }
   LOG(PR_LOG_DEBUG, ("seek succeeded"));
 
   return DecodeToTarget(aTarget);
 }
 
-nsresult GStreamerReader::GetBuffered(TimeRanges* aBuffered,
+nsresult GStreamerReader::GetBuffered(dom::TimeRanges* aBuffered,
                                       int64_t aStartTime)
 {
   if (!mInfo.HasValidMedia()) {
     return NS_OK;
   }
 
   GstFormat format = GST_FORMAT_TIME;
   MediaResource* resource = mDecoder->GetResource();
--- a/content/media/mediasource/MediaSource.h
+++ b/content/media/mediasource/MediaSource.h
@@ -30,17 +30,16 @@ namespace mozilla {
 class ErrorResult;
 template <typename T> class AsyncEventRunner;
 
 namespace dom {
 
 class GlobalObject;
 class SourceBuffer;
 class SourceBufferList;
-class TimeRanges;
 template <typename T> class Optional;
 
 #define MOZILLA_DOM_MEDIASOURCE_IMPLEMENTATION_IID \
   { 0x3839d699, 0x22c5, 0x439f, \
   { 0x94, 0xca, 0x0e, 0x0b, 0x26, 0xf9, 0xca, 0xbf } }
 
 class MediaSource MOZ_FINAL : public nsDOMEventTargetHelper
 {
--- a/content/media/mediasource/MediaSourceDecoder.cpp
+++ b/content/media/mediasource/MediaSourceDecoder.cpp
@@ -115,17 +115,17 @@ private:
 
   MediaDecoderReader* GetAudioReader()
   {
     MediaSourceDecoder* decoder = static_cast<MediaSourceDecoder*>(mDecoder);
     return decoder->GetAudioReader();
   }
 };
 
-MediaSourceDecoder::MediaSourceDecoder(HTMLMediaElement* aElement)
+MediaSourceDecoder::MediaSourceDecoder(dom::HTMLMediaElement* aElement)
   : mMediaSource(nullptr)
   , mVideoReader(nullptr),
     mAudioReader(nullptr)
 {
   Init(aElement);
 }
 
 MediaDecoder*
@@ -143,33 +143,33 @@ MediaSourceDecoder::CreateStateMachine()
 
 nsresult
 MediaSourceDecoder::Load(nsIStreamListener**, MediaDecoder*)
 {
   return NS_OK;
 }
 
 nsresult
-MediaSourceDecoder::GetSeekable(TimeRanges* aSeekable)
+MediaSourceDecoder::GetSeekable(dom::TimeRanges* aSeekable)
 {
   double duration = mMediaSource->Duration();
   if (IsNaN(duration)) {
     // Return empty range.
   } else if (duration > 0 && mozilla::IsInfinite(duration)) {
-    nsRefPtr<TimeRanges> bufferedRanges = new TimeRanges();
+    nsRefPtr<dom::TimeRanges> bufferedRanges = new dom::TimeRanges();
     GetBuffered(bufferedRanges);
     aSeekable->Add(0, bufferedRanges->GetFinalEndTime());
   } else {
     aSeekable->Add(0, duration);
   }
   return NS_OK;
 }
 
 void
-MediaSourceDecoder::AttachMediaSource(MediaSource* aMediaSource)
+MediaSourceDecoder::AttachMediaSource(dom::MediaSource* aMediaSource)
 {
   MOZ_ASSERT(!mMediaSource && !mDecoderStateMachine);
   mMediaSource = aMediaSource;
   mDecoderStateMachine = CreateStateMachine();
 }
 
 void
 MediaSourceDecoder::DetachMediaSource()
--- a/content/media/mediasource/MediaSourceDecoder.h
+++ b/content/media/mediasource/MediaSourceDecoder.h
@@ -31,24 +31,24 @@ namespace dom {
 class HTMLMediaElement;
 class MediaSource;
 
 } // namespace dom
 
 class MediaSourceDecoder : public MediaDecoder
 {
 public:
-  MediaSourceDecoder(HTMLMediaElement* aElement);
+  MediaSourceDecoder(dom::HTMLMediaElement* aElement);
 
   virtual MediaDecoder* Clone() MOZ_OVERRIDE;
   virtual MediaDecoderStateMachine* CreateStateMachine() MOZ_OVERRIDE;
   virtual nsresult Load(nsIStreamListener**, MediaDecoder*) MOZ_OVERRIDE;
-  virtual nsresult GetSeekable(TimeRanges* aSeekable) MOZ_OVERRIDE;
+  virtual nsresult GetSeekable(dom::TimeRanges* aSeekable) MOZ_OVERRIDE;
 
-  void AttachMediaSource(MediaSource* aMediaSource);
+  void AttachMediaSource(dom::MediaSource* aMediaSource);
   void DetachMediaSource();
 
   SubBufferDecoder* CreateSubDecoder(const nsACString& aType);
 
   const nsTArray<MediaDecoderReader*>& GetReaders()
   {
     ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
     while (mReaders.Length() == 0) {
@@ -75,17 +75,17 @@ public:
   }
 
   MediaDecoderReader* GetAudioReader()
   {
     return mAudioReader;
   }
 
 private:
-  MediaSource* mMediaSource;
+  dom::MediaSource* mMediaSource;
 
   nsTArray<nsRefPtr<SubBufferDecoder> > mDecoders;
   nsTArray<MediaDecoderReader*> mReaders; // Readers owned by Decoders.
 
   MediaDecoderReader* mVideoReader;
   MediaDecoderReader* mAudioReader;
 };
 
--- a/content/media/mediasource/SubBufferDecoder.h
+++ b/content/media/mediasource/SubBufferDecoder.h
@@ -43,17 +43,17 @@ public:
   void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
   {
     mReader->NotifyDataArrived(aBuffer, aLength, aOffset);
 
     // XXX: aOffset makes no sense here, need view of "data timeline".
     mParentDecoder->NotifyDataArrived(aBuffer, aLength, aOffset);
   }
 
-  nsresult GetBuffered(TimeRanges* aBuffered)
+  nsresult GetBuffered(dom::TimeRanges* aBuffered)
   {
     // XXX: Need mStartTime (from StateMachine) instead of passing 0.
     return mReader->GetBuffered(aBuffered, 0);
   }
 
 private:
   MediaSourceDecoder* mParentDecoder;
   nsAutoPtr<MediaDecoderReader> mReader;
--- a/content/media/ogg/OggReader.cpp
+++ b/content/media/ogg/OggReader.cpp
@@ -1767,17 +1767,17 @@ nsresult OggReader::SeekBisection(int64_
     NS_ASSERTION(endTime >= seekTarget, "End must be after seek target");
   }
 
   SEEK_LOG(PR_LOG_DEBUG, ("Seek complete in %d bisections.", hops));
 
   return NS_OK;
 }
 
-nsresult OggReader::GetBuffered(TimeRanges* aBuffered, int64_t aStartTime)
+nsresult OggReader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
 {
   {
     mozilla::ReentrantMonitorAutoEnter mon(mMonitor);
     if (mIsChained)
       return NS_ERROR_FAILURE;
   }
 #ifdef OGG_ESTIMATE_BUFFERED
   return MediaDecoderReader::GetBuffered(aBuffered, aStartTime);
--- a/content/media/webaudio/blink/moz.build
+++ b/content/media/webaudio/blink/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'Biquad.cpp',
     'DirectConvolver.cpp',
     'DynamicsCompressor.cpp',
     'DynamicsCompressorKernel.cpp',
     'FFTConvolver.cpp',
     'HRTFDatabase.cpp',
     'HRTFDatabaseLoader.cpp',
     'HRTFElevation.cpp',
--- a/content/media/webaudio/moz.build
+++ b/content/media/webaudio/moz.build
@@ -43,17 +43,17 @@ EXPORTS.mozilla.dom += [
     'OfflineAudioCompletionEvent.h',
     'OscillatorNode.h',
     'PannerNode.h',
     'PeriodicWave.h',
     'ScriptProcessorNode.h',
     'WaveShaperNode.h',
 ]
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'AnalyserNode.cpp',
     'AudioBuffer.cpp',
     'AudioBufferSourceNode.cpp',
     'AudioContext.cpp',
     'AudioDestinationNode.cpp',
     'AudioListener.cpp',
     'AudioNode.cpp',
     'AudioParam.cpp',
--- a/content/media/wmf/WMFReader.cpp
+++ b/content/media/wmf/WMFReader.cpp
@@ -109,17 +109,17 @@ WMFReader::InitializeDXVA()
   // Extract the layer manager backend type so that we can determine
   // whether it's worthwhile using DXVA. If we're not running with a D3D
   // layer manager then the readback of decoded video frames from GPU to
   // CPU memory grinds painting to a halt, and makes playback performance
   // *worse*.
   MediaDecoderOwner* owner = mDecoder->GetOwner();
   NS_ENSURE_TRUE(owner, false);
 
-  HTMLMediaElement* element = owner->GetMediaElement();
+  dom::HTMLMediaElement* element = owner->GetMediaElement();
   NS_ENSURE_TRUE(element, false);
 
   nsRefPtr<LayerManager> layerManager =
     nsContentUtils::LayerManagerForDocument(element->OwnerDoc());
   NS_ENSURE_TRUE(layerManager, false);
 
   if (layerManager->GetBackendType() != LayersBackend::LAYERS_D3D9 &&
       layerManager->GetBackendType() != LayersBackend::LAYERS_D3D10) {
--- a/content/xslt/src/base/moz.build
+++ b/content/xslt/src/base/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'txDouble.cpp',
     'txExpandedNameMap.cpp',
     'txList.cpp',
     'txNamespaceMap.cpp',
     'txURIUtils.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
--- a/content/xslt/src/base/txLog.h
+++ b/content/xslt/src/base/txLog.h
@@ -2,17 +2,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/. */
 
 #ifndef txLog_h__
 #define txLog_h__
 
 #include "prlog.h"
-#endif
 
 #ifdef PR_LOGGING
 class txLog
 {
 public:
     static PRLogModuleInfo *xpath;
     static PRLogModuleInfo *xslt;
 };
@@ -26,8 +25,9 @@ public:
     txLog::xslt  = PR_NewLogModule("xslt")
 
 #else
 
 #define TX_LG_IMPL
 #define TX_LG_CREATE
 
 #endif
+#endif
--- a/content/xslt/src/xml/moz.build
+++ b/content/xslt/src/xml/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'txXMLParser.cpp',
     'txXMLUtils.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
     '../base',
--- a/content/xslt/src/xpath/moz.build
+++ b/content/xslt/src/xpath/moz.build
@@ -3,17 +3,17 @@
 # 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/.
 
 EXPORTS.mozilla.dom += [
     'XPathEvaluator.h',
 ]
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'nsXPathExpression.cpp',
     'nsXPathNSResolver.cpp',
     'nsXPathResult.cpp',
     'txBooleanExpr.cpp',
     'txBooleanResult.cpp',
     'txCoreFunctionCall.cpp',
     'txErrorExpr.cpp',
     'txExpr.cpp',
--- a/content/xslt/src/xslt/moz.build
+++ b/content/xslt/src/xslt/moz.build
@@ -1,15 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'txBufferingHandler.cpp',
     'txCurrentFunctionCall.cpp',
     'txDocumentFunctionCall.cpp',
     'txExecutionState.cpp',
     'txEXSLTFunctions.cpp',
     'txFormatNumberFunctionCall.cpp',
     'txGenerateIdFunctionCall.cpp',
     'txInstructions.cpp',
--- a/dom/audiochannel/moz.build
+++ b/dom/audiochannel/moz.build
@@ -14,17 +14,17 @@ XPIDL_MODULE = 'dom_audiochannel'
 
 EXPORTS += [
     'AudioChannelAgent.h',
     'AudioChannelCommon.h',
     'AudioChannelService.h',
     'AudioChannelServiceChild.h',
 ]
 
-SOURCES += [
+UNIFIED_SOURCES += [
     'AudioChannelAgent.cpp',
     'AudioChannelService.cpp',
     'AudioChannelServiceChild.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/base/IndexedDBHelper.jsm
+++ b/dom/base/IndexedDBHelper.jsm
@@ -15,16 +15,17 @@ if (DEBUG) {
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 this.EXPORTED_SYMBOLS = ["IndexedDBHelper"];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.importGlobalProperties(["indexedDB"]);
 
 this.IndexedDBHelper = function IndexedDBHelper() {}
 
 IndexedDBHelper.prototype = {
 
   // Cache the database
   _db: null,
 
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -52,16 +52,17 @@ EXPORTS.mozilla.dom += [
     'BarProps.h',
     'DOMCursor.h',
     'DOMError.h',
     'DOMException.h',
     'DOMRequest.h',
     'MessageChannel.h',
     'MessagePort.h',
     'MessagePortList.h',
+    'Navigator.h',
     'ScreenOrientation.h',
     'StructuredCloneTags.h',
     'URL.h',
 ]
 
 SOURCES += [
     'BarProps.cpp',
     'CompositionStringSynthesizer.cpp',
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1884,17 +1884,17 @@ class CGCreateInterfaceObjectsMethod(CGA
                 (pref, ptr) in prefCacheData]
             prefCache = CGWrapper(CGIndenter(CGList(prefCacheData, "\n")),
                                   pre=("static bool sPrefCachesInited = false;\n"
                                        "if (!sPrefCachesInited) {\n"
                                        "  sPrefCachesInited = true;\n"),
                                   post="\n}")
         else:
             prefCache = None
-            
+
         if UseHolderForUnforgeable(self.descriptor):
             createUnforgeableHolder = CGGeneric("""JS::Rooted<JSObject*> unforgeableHolder(aCx,
   JS_NewObjectWithGivenProto(aCx, nullptr, nullptr, nullptr));
 if (!unforgeableHolder) {
   return;
 }""")
             defineUnforgeables = InitUnforgeablePropertiesOnObject(self.descriptor,
                                                                    "unforgeableHolder",
@@ -2012,17 +2012,17 @@ class CGGetPerInterfaceObject(CGAbstract
     return JS::NullPtr();
   }
   /* Check to see whether the interface objects are already installed */
   JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
   if (!protoAndIfaceArray[%s]) {
     CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray, aDefineOnGlobal);
   }
 
-  /* 
+  /*
    * The object might _still_ be null, but that's OK.
    *
    * Calling fromMarkedLocation() is safe because protoAndIfaceArray is
    * traced by TraceProtoAndIfaceCache() and its contents are never
    * changed after they have been set.
    */
   return JS::Handle<JSObject*>::fromMarkedLocation(protoAndIfaceArray[%s].address());""" %
                 (self.id, self.id))
@@ -3536,17 +3536,17 @@ for (uint32_t i = 0; i < length; ++i) {
             # have a non-default exceptionCode here unless attribute "arg
             # conversion" code starts passing in an exceptionCode.  At which
             # point we'll need to figure out what that even means.
             assert exceptionCode == "return false;"
             handleInvalidEnumValueCode = (
                 "  if (index < 0) {\n"
                 "    return true;\n"
                 "  }\n")
-            
+
         template = (
             "{\n"
             "  bool ok;\n"
             '  int index = FindEnumStringIndex<%(invalidEnumValueFatal)s>(cx, ${val}, %(values)s, "%(enumtype)s", "%(sourceDescription)s", &ok);\n'
             "  if (!ok) {\n"
             "%(exceptionCode)s\n"
             "  }\n"
             "%(handleInvalidEnumValueCode)s"
@@ -4103,17 +4103,17 @@ def getWrapTemplateForType(type, descrip
                     "}\n" +
                     successCode)
         return ("${jsvalRef}.set(%s);\n" +
                 tail) % (value)
 
     def wrapAndSetPtr(wrapCall, failureCode=None):
         """
         Returns the code to set the jsval by calling "wrapCall". "failureCode"
-        is the code to run if calling "wrapCall" fails 
+        is the code to run if calling "wrapCall" fails
         """
         if failureCode is None:
             failureCode = exceptionCode
         str = ("if (!%s) {\n" +
                CGIndenter(CGGeneric(failureCode)).define() + "\n" +
                "}\n" +
                successCode) % (wrapCall)
         return str
@@ -5031,17 +5031,17 @@ class CGSwitch(CGList):
                 CGIndenter(
                     CGWrapper(
                         CGIndenter(default),
                         pre="default: {\n",
                         post="\n  break;\n}"
                         )
                     )
                 )
-                        
+
         self.append(CGGeneric("}"))
 
 class CGCase(CGList):
     """
     A class to generate code for a case statement.
 
     Takes three constructor arguments: an expression, a CGThing for
     the body (allowed to be None if there is no body), and an optional
@@ -5080,17 +5080,17 @@ class CGMethodCall(CGThing):
             return requiredArgs
 
         def getPerSignatureCall(signature, argConversionStartsAt=0):
             return CGPerSignatureCall(signature[0], signature[1],
                                       nativeMethodName, static, descriptor,
                                       method,
                                       argConversionStartsAt=argConversionStartsAt,
                                       isConstructor=isConstructor)
-            
+
 
         signatures = method.signatures()
         if len(signatures) == 1:
             # Special case: we can just do a per-signature method call
             # here for our one signature and not worry about switching
             # on anything.
             signature = signatures[0]
             self.cgRoot = CGList([ CGIndenter(getPerSignatureCall(signature)) ])
@@ -6783,20 +6783,20 @@ class ClassUsingDeclaration(ClassItem):
                   'name': self.name })
 
     def define(self, cgClass):
         return ''
 
 class ClassConstructor(ClassItem):
     """
     Used for adding a constructor to a CGClass.
-    
+
     args is a list of Argument objects that are the arguments taken by the
     constructor.
-    
+
     inline should be True if the constructor should be marked inline.
 
     bodyInHeader should be True if the body should be placed in the class
     declaration in the header.
 
     visibility determines the visibility of the constructor (public,
     protected, private), defaults to private.
 
@@ -6830,17 +6830,17 @@ class ClassConstructor(ClassItem):
 
     def getInitializationList(self, cgClass):
         items = [str(c) for c in self.baseConstructors]
         for m in cgClass.members:
             if not m.static:
                 initialize = m.body
                 if initialize:
                     items.append(m.name + "(" + initialize + ")")
-            
+
         if len(items) > 0:
             return '\n  : ' + ',\n    '.join(items)
         return ''
 
     def getBody(self):
         return self.body
 
     def declare(self, cgClass):
@@ -7841,17 +7841,17 @@ class CGDOMJSProxyHandler_hasOwn(ClassMe
         args = [Argument('JSContext*', 'cx'),
                 Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<jsid>', 'id'),
                 Argument('bool*', 'bp')]
         ClassMethod.__init__(self, "hasOwn", "bool", args)
         self.descriptor = descriptor
     def getBody(self):
         if self.descriptor.supportsIndexedProperties():
-            indexed = ("int32_t index = GetArrayIndexFromId(cx, id);\n" + 
+            indexed = ("int32_t index = GetArrayIndexFromId(cx, id);\n" +
                        "if (IsArrayIndex(index)) {\n" +
                        CGIndenter(CGProxyIndexedPresenceChecker(self.descriptor)).define() + "\n" +
                        "  *bp = found;\n" +
                        "  return true;\n" +
                        "}\n\n") % (self.descriptor.nativeType)
         else:
             indexed = ""
 
@@ -8737,17 +8737,17 @@ if (""",
         else:
             conversion += (
                 "if (!isNull && !temp.ref().isUndefined()) {\n"
                 "  ${prop}.Construct();\n"
                 "${convert}\n"
                 "}")
             conversionReplacements["convert"] = CGIndenter(
                 CGGeneric(conversionReplacements["convert"])).define()
-        
+
         return CGGeneric(
             string.Template(conversion).substitute(conversionReplacements)
             )
 
     def getMemberDefinition(self, memberInfo):
         member = memberInfo[0]
         declType = memberInfo[1].declType
         memberLoc = self.makeMemberName(member.identifier.name)
@@ -11344,9 +11344,8 @@ class CGEventRoot(CGThing):
 
 """)
 
     def declare(self):
         return self.root.declare()
 
     def define(self):
         return self.root.define()
-
new file mode 100644
--- /dev/null
+++ b/dom/bindings/mach_commands.py
@@ -0,0 +1,30 @@
+# 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/.
+
+from __future__ import unicode_literals
+
+import os
+import sys
+
+from mach.decorators import (
+    CommandArgument,
+    CommandProvider,
+    Command,
+)
+
+from mozbuild.base import MachCommandBase
+
+
+@CommandProvider
+class WebIDLProvider(MachCommandBase):
+    @Command('webidl-parser-test', category='testing',
+        description='Run WebIDL tests.')
+    @CommandArgument('--verbose', '-v', action='store_true',
+        help='Run tests in verbose mode.')
+    def webidl_test(self, verbose=False):
+        sys.path.insert(0, os.path.join(self.topsrcdir, 'other-licenses',
+            'ply'))
+
+        from runtests import run_tests
+        return run_tests(None, verbose=verbose)
--- a/dom/bindings/test/Makefile.in
+++ b/dom/bindings/test/Makefile.in
@@ -60,20 +60,16 @@ include $(topsrcdir)/config/rules.mk
 	# $(CPPSRCS) in dom/bindings/Makefile.in.
 	$(MAKE) -C .. export TestExampleInterface-example TestExampleProxyInterface-example
 	@$(TOUCH) $@
 
 check::
 	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	  $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py
 
-check-interactive:
-	PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $(topsrcdir)/config/pythonpath.py \
-	  $(PLY_INCLUDE) $(srcdir)/../parser/runtests.py -q
-
 # Since we define MOCHITEST_FILES, config/makefiles/mochitest.mk goes ahead and
 # sets up a rule with libs:: in itm which makes our .DEFAULT_TARGET be "libs".
 # Then ruls.mk does |.DEFAULT_TARGET ?= default| which leaves it as "libs".  So
 # if we make without an explicit target in this directory, we try to make
 # "libs", but with a $(MAKECMDGOALS) of empty string.  And then rules.mk
 # helpfully does not include our *.o.pp files, since it includes them only if
 # filtering some stuff out from $(MAKECMDGOALS) leaves it nonempty.  The upshot
 # is that if some headers change and we run make in this dir without an explicit
--- a/dom/browser-element/BrowserElementPanning.js
+++ b/dom/browser-element/BrowserElementPanning.js
@@ -449,17 +449,17 @@ const ContentPanning = {
 
   get _activeDurationMs() {
     let duration = Services.prefs.getIntPref('ui.touch_activation.duration_ms');
     delete this._activeDurationMs;
     return this._activeDurationMs = duration;
   },
 
   _resetActive: function cp_resetActive() {
-    let elt = this.target || this.pointerDownTarget;
+    let elt = this.pointerDownTarget || this.target;
     let root = elt.ownerDocument || elt.document;
     this._setActive(root.documentElement);
   },
 
   _resetHover: function cp_resetHover() {
     const kStateHover = 0x00000004;
     let element = content.document.createElement('foo');
     this._domUtils.setContentState(element, kStateHover);
--- a/dom/contacts/fallback/ContactDB.jsm
+++ b/dom/contacts/fallback/ContactDB.jsm
@@ -13,16 +13,17 @@ function debug(s) { dump("-*- ContactDB 
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
+Cu.importGlobalProperties(["indexedDB"]);
 
 const DB_NAME = "contacts";
 const DB_VERSION = 18;
 const STORE_NAME = "contacts";
 const SAVED_GETALL_STORE_NAME = "getallcache";
 const CHUNK_SIZE = 20;
 const REVISION_STORE = "revision";
 const REVISION_KEY = "revision";
--- a/dom/contacts/tests/chrome.ini
+++ b/dom/contacts/tests/chrome.ini
@@ -1,3 +1,3 @@
 [DEFAULT]
 
-[test_contacts_upgrade.html]
+[test_contacts_upgrade.xul]
rename from dom/contacts/tests/test_contacts_upgrade.html
rename to dom/contacts/tests/test_contacts_upgrade.xul
--- a/dom/contacts/tests/test_contacts_upgrade.html
+++ b/dom/contacts/tests/test_contacts_upgrade.xul
@@ -1,278 +1,279 @@
-<!DOCTYPE html>
-<html>
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=889239
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
 -->
-<head>
-  <title>Test for Bug 889239</title>
-  <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-</head>
-<body>
 
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=889239">Mozilla Bug 889239</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-</div>
-<pre id="test">
-<script class="testbody" type="application/javascript;version=1.7">
-"use strict";
-
-var isAndroid = (navigator.userAgent.indexOf("Android") !== -1);
+<window title="Mozilla Bug 889239"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
 
-function checkStr(str1, str2, msg) {
-  if (str1 ^ str2) {
-    ok(false, "Expected both strings to be either present or absent");
-    return;
-  }
-  is(str1, str2, msg);
-}
+  <script type="application/javascript;version=1.7">
+  <![CDATA[
+  "use strict";
+
+  var isAndroid = (navigator.userAgent.indexOf("Android") !== -1);
 
-function checkStrArray(str1, str2, msg) {
-  // comparing /[null(,null)+]/ and undefined should pass
-  function nonNull(e) {
-    return e != null;
-  }
-  if ((Array.isArray(str1) && str1.filter(nonNull).length == 0 && str2 == undefined)
-     ||(Array.isArray(str2) && str2.filter(nonNull).length == 0 && str1 == undefined)) {
-    ok(true, msg);
-  } else if (str1) {
-    is(JSON.stringify(typeof str1 == "string" ? [str1] : str1), JSON.stringify(typeof str2 == "string" ? [str2] : str2), msg);
-  }
-}
-
-function checkAddress(adr1, adr2) {
-  if (adr1 ^ adr2) {
-    ok(false, "Expected both adrs to be either present or absent");
-    return;
+  function checkStr(str1, str2, msg) {
+    if (str1 ^ str2) {
+      ok(false, "Expected both strings to be either present or absent");
+      return;
+    }
+    is(str1, str2, msg);
   }
-  checkStrArray(adr1.type, adr2.type, "Same type");
-  checkStrArray(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
-  checkStrArray(adr1.locality, adr2.locality, "Same locality");
-  checkStrArray(adr1.region, adr2.region, "Same region");
-  checkStrArray(adr1.postalCode, adr2.postalCode, "Same postalCode");
-  checkStrArray(adr1.countryName, adr2.countryName, "Same countryName");
-  is(adr1.pref, adr2.pref, "Same pref");
-}
 
-function checkTel(tel1, tel2) {
-  if (tel1 ^ tel2) {
-    ok(false, "Expected both tels to be either present or absent");
-    return;
-  }
-  checkStrArray(tel1.type, tel2.type, "Same type");
-  checkStrArray(tel1.value, tel2.value, "Same value");
-  checkStrArray(tel1.carrier, tel2.carrier, "Same carrier");
-  is(tel1.pref, tel2.pref, "Same pref");
-}
-
-function checkField(field1, field2) {
-  if (field1 ^ field2) {
-    ok(false, "Expected both fields to be either present or absent");
-    return;
+  function checkStrArray(str1, str2, msg) {
+    // comparing /[null(,null)+]/ and undefined should pass
+    function nonNull(e) {
+      return e != null;
+    }
+    if ((Array.isArray(str1) && str1.filter(nonNull).length == 0 && str2 == undefined)
+       ||(Array.isArray(str2) && str2.filter(nonNull).length == 0 && str1 == undefined)) {
+      ok(true, msg);
+    } else if (str1) {
+      is(JSON.stringify(typeof str1 == "string" ? [str1] : str1), JSON.stringify(typeof str2 == "string" ? [str2] : str2), msg);
+    }
   }
-  checkStrArray(field1.type, field2.type, "Same type");
-  checkStrArray(field1.value, field2.value, "Same value");
-  is(field1.pref, field2.pref, "Same pref");
-}
-
-function checkDBContacts(dbContact1, dbContact2) {
-  let contact1 = dbContact1.properties;
-  let contact2 = dbContact2.properties;
 
-  checkStrArray(contact1.name, contact2.name, "Same name");
-  checkStrArray(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
-  checkStrArray(contact1.givenName, contact2.givenName, "Same givenName");
-  checkStrArray(contact1.additionalName, contact2.additionalName, "Same additionalName");
-  checkStrArray(contact1.familyName, contact2.familyName, "Same familyName");
-  checkStrArray(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
-  checkStrArray(contact1.nickname, contact2.nickname, "Same nickname");
-  checkStrArray(contact1.category, contact2.category, "Same category");
-  checkStrArray(contact1.org, contact2.org, "Same org");
-  checkStrArray(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
-  is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
-  checkStrArray(contact1.note, contact2.note, "Same note");
-  is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
-  checkStr(contact1.sex, contact2.sex, "Same sex");
-  checkStr(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
-  checkStrArray(contact1.key, contact2.key, "Same key");
+  function checkAddress(adr1, adr2) {
+    if (adr1 ^ adr2) {
+      ok(false, "Expected both adrs to be either present or absent");
+      return;
+    }
+    checkStrArray(adr1.type, adr2.type, "Same type");
+    checkStrArray(adr1.streetAddress, adr2.streetAddress, "Same streetAddress");
+    checkStrArray(adr1.locality, adr2.locality, "Same locality");
+    checkStrArray(adr1.region, adr2.region, "Same region");
+    checkStrArray(adr1.postalCode, adr2.postalCode, "Same postalCode");
+    checkStrArray(adr1.countryName, adr2.countryName, "Same countryName");
+    is(adr1.pref, adr2.pref, "Same pref");
+  }
 
-  is(contact1.email.length, contact2.email.length, "Same number of emails");
-  for (let i = 0; i < contact1.email.length; ++i) {
-    checkField(contact1.email[i], contact2.email[i]);
+  function checkTel(tel1, tel2) {
+    if (tel1 ^ tel2) {
+      ok(false, "Expected both tels to be either present or absent");
+      return;
+    }
+    checkStrArray(tel1.type, tel2.type, "Same type");
+    checkStrArray(tel1.value, tel2.value, "Same value");
+    checkStrArray(tel1.carrier, tel2.carrier, "Same carrier");
+    is(tel1.pref, tel2.pref, "Same pref");
   }
 
-  is(contact1.adr.length, contact2.adr.length, "Same number of adrs");
-  for (var i in contact1.adr) {
-    checkAddress(contact1.adr[i], contact2.adr[i]);
+  function checkField(field1, field2) {
+    if (field1 ^ field2) {
+      ok(false, "Expected both fields to be either present or absent");
+      return;
+    }
+    checkStrArray(field1.type, field2.type, "Same type");
+    checkStrArray(field1.value, field2.value, "Same value");
+    is(field1.pref, field2.pref, "Same pref");
   }
 
-  is(contact1.tel.length, contact2.tel.length, "Same number of tels");
-  for (var i in contact1.tel) {
-    checkTel(contact1.tel[i], contact2.tel[i]);
-  }
+  function checkDBContacts(dbContact1, dbContact2) {
+    let contact1 = dbContact1.properties;
+    let contact2 = dbContact2.properties;
+
+    checkStrArray(contact1.name, contact2.name, "Same name");
+    checkStrArray(contact1.honorificPrefix, contact2.honorificPrefix, "Same honorificPrefix");
+    checkStrArray(contact1.givenName, contact2.givenName, "Same givenName");
+    checkStrArray(contact1.additionalName, contact2.additionalName, "Same additionalName");
+    checkStrArray(contact1.familyName, contact2.familyName, "Same familyName");
+    checkStrArray(contact1.honorificSuffix, contact2.honorificSuffix, "Same honorificSuffix");
+    checkStrArray(contact1.nickname, contact2.nickname, "Same nickname");
+    checkStrArray(contact1.category, contact2.category, "Same category");
+    checkStrArray(contact1.org, contact2.org, "Same org");
+    checkStrArray(contact1.jobTitle, contact2.jobTitle, "Same jobTitle");
+    is(contact1.bday ? contact1.bday.valueOf() : null, contact2.bday ? contact2.bday.valueOf() : null, "Same birthday");
+    checkStrArray(contact1.note, contact2.note, "Same note");
+    is(contact1.anniversary ? contact1.anniversary.valueOf() : null , contact2.anniversary ? contact2.anniversary.valueOf() : null, "Same anniversary");
+    checkStr(contact1.sex, contact2.sex, "Same sex");
+    checkStr(contact1.genderIdentity, contact2.genderIdentity, "Same genderIdentity");
+    checkStrArray(contact1.key, contact2.key, "Same key");
+
+    is(contact1.email.length, contact2.email.length, "Same number of emails");
+    for (let i = 0; i < contact1.email.length; ++i) {
+      checkField(contact1.email[i], contact2.email[i]);
+    }
 
-  is(contact1.url.length, contact2.url.length, "Same number of urls");
-  for (var i in contact1.url) {
-    checkField(contact1.url[i], contact2.url[i]);
-  }
+    is(contact1.adr.length, contact2.adr.length, "Same number of adrs");
+    for (var i in contact1.adr) {
+      checkAddress(contact1.adr[i], contact2.adr[i]);
+    }
+
+    is(contact1.tel.length, contact2.tel.length, "Same number of tels");
+    for (var i in contact1.tel) {
+      checkTel(contact1.tel[i], contact2.tel[i]);
+    }
+
+    is(contact1.url.length, contact2.url.length, "Same number of urls");
+    for (var i in contact1.url) {
+      checkField(contact1.url[i], contact2.url[i]);
+    }
 
-  is(contact1.impp.length, contact2.impp.length, "Same number of impps");
-  for (var i in contact1.impp) {
-    checkField(contact1.impp[i], contact2.impp[i]);
+    is(contact1.impp.length, contact2.impp.length, "Same number of impps");
+    for (var i in contact1.impp) {
+      checkField(contact1.impp[i], contact2.impp[i]);
+    }
+
+    // test search indexes
+    contact1 = dbContact1.search;
+    contact2 = dbContact2.search;
+    checkStrArray(contact1.category, contact2.category, "Same cateogry index");
+    checkStrArray(contact1.email, contact2.email, "Same email index");
+    checkStrArray(contact1.emailLowerCase, contact2.emailLowerCase, "Same emailLowerCase index");
+    checkStrArray(contact1.familyName, contact2.familyName, "Same familyName index");
+    checkStrArray(contact1.familyNameLowerCase, contact2.familyNameLowerCase, "Same familyNameLowerCase index");
+    checkStrArray(contact1.givenName, contact2.givenName, "Same givenName index");
+    checkStrArray(contact1.givenNameLowerCase, contact2.givenNameLowerCase, "Same givenNameLowerCase index");
+    checkStrArray(contact1.name, contact2.name, "Same name index");
+    checkStrArray(contact1.tel, contact2.tel, "Same tel index");
+    checkStrArray(contact1.telLowerCase, contact2.telLowerCase, "Same telLowerCase index");
+    checkStrArray(contact1.telMatch, contact2.telMatch, "Same telMatch index");
   }
 
-  // test search indexes
-  contact1 = dbContact1.search;
-  contact2 = dbContact2.search;
-  checkStrArray(contact1.category, contact2.category, "Same cateogry index");
-  checkStrArray(contact1.email, contact2.email, "Same email index");
-  checkStrArray(contact1.emailLowerCase, contact2.emailLowerCase, "Same emailLowerCase index");
-  checkStrArray(contact1.familyName, contact2.familyName, "Same familyName index");
-  checkStrArray(contact1.familyNameLowerCase, contact2.familyNameLowerCase, "Same familyNameLowerCase index");
-  checkStrArray(contact1.givenName, contact2.givenName, "Same givenName index");
-  checkStrArray(contact1.givenNameLowerCase, contact2.givenNameLowerCase, "Same givenNameLowerCase index");
-  checkStrArray(contact1.name, contact2.name, "Same name index");
-  checkStrArray(contact1.tel, contact2.tel, "Same tel index");
-  checkStrArray(contact1.telLowerCase, contact2.telLowerCase, "Same telLowerCase index");
-  checkStrArray(contact1.telMatch, contact2.telMatch, "Same telMatch index");
-}
-
-function makeFailure(reason) {
-  return function() {
-    ok(false, reason);
-    SimpleTest.finish();
-  };
-};
-
-const {Cc, Ci, Cu} = SpecialPowers;
-Cu.import("resource://gre/modules/ContactDB.jsm", window);
-
-let cdb = new ContactDB();
-cdb.init();
-
-let CONTACT_PROPS = {
-  id: "ab74671e36be41b680f8f030e7e24ea2",
-  properties: {
-    name: ["Magnificentest foo bar the third"],
-    givenName: ["foo"],
-    familyName: ["bar"],
-    honorificPrefix: ["magnificentest"],
-    honorificSuffix: ["the third"],
-    additionalName: ["addl"],
-    nickname: ["foo"],
-    tel: [
-      {type: ["mobile"], value: "+12345678901", carrier: "ACME Telecommunications", pref: true},
-      {type: ["home", "custom"], value: "7932012346", pref: false},
-    ],
-    email: [{type: ["work"], value: "a@b.c"}, {value: "b@c.d", pref: true}],
-    adr: [
-      {
-        type: ["home"],
-        streetAddress: "street 1",
-        locality: "locality 1",
-        region: "region 1",
-        postalCode: "postal code 1",
-        countryName: "country 1",
-      }
-    ],
-    impp: [{type: ["aim"], value:"im1", pref: true}, {value: "im2"}],
-    org: ["org1", "org2"],
-    jobTitle: ["boss", "superboss"],
-    bday: new Date("1980, 12, 01"),
-    note: ["bla bla bla"],
-    category: ["cat1", "cat2"],
-    url: [{type: ["work", "work2"], value: "www.1.com", pref: true}, {value: "www2.com"}],
-    anniversary: new Date("2000, 12, 01"),
-    sex: "male",
-    genderIdentity: "trisexual",
-    key: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAC4jAAAuIwF4pT92AAACrElEQVQozwXBTW8bRRgA4Hfemf1er7/iJI4Tq7VFlEZN1VZIlapy4MQBTkXcuSH+G/APKnGAAyCVCqmtCHETp64db5zdtdf7NbMzw/OQH378HkCZpmmapqYMy8yrNnadS6026HC/Z7k+SCkEBwKEEKaUQtQAmlDqrucH23nH4BRkJVRcwmod5gcn6LehFgCaEIIalFZaEcLCq73w355RdvY7nfGQGVTlmRXfqMlrUaSUMUQkhCISJIggKj3/YBHt7PRbpy+cwbF7dN/0vEqTMoo3s0tmGAAAoJAgImMq3xZ5WTPbHj4Mho8Nf+QcPtZBLxEkqeQ2WmklkRCtNdNaI1KpVCnqOC3j5ZK++4vnm6xSWZpzwQtRV2mOiBoRpEKtNQAQggjQcCwqinRxJeKlWW93dlqEsa2QRZbF85nWBAAZY4YUgl9fRJWKVuWgmhwHhpD1+ZrfVjAN867rMCne//rq7OuXjWaLCVHnOWHgFDwMw+Tvi09PdhtJXoVC7bWDIi8Lg8qyMk3rYjLzvJh2O30hwK6TpiG7zWDcck9GR17D9wxDcH7/oNtElRa1aZuLDJN4S7/87tssLVg0/eZs/3h0D5R89vR0v+1AVT0YHX31ZDy9uv7IeJrryeyu2+nS50/PqOXM5qt8Nf/jv08UwTfN27vkchldLpPf/nx/nqSz5sbzhkTYzLRppzNYre/ycrMIZwqsHdf96fd/Xr354AYBr/jESWhgGb6zVSuGrrQS1j4Zk8nc2Hs7frFb3Phc6+fOKDGLKOJTHvlj2u85N4t6vbw7OM4YRVquboPdsPNZ9eb8pvfAOf2iN4dN3EzWadnoO5JY19Oo0TYtw1t8TBqBR9v7wbOXROLWtZ3PH937+ZfXrb6BUHEbXL+FCIfDw92e5zebg8GR54r/AaMVcBxE6hgPAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDEyLTA3LTIxVDEwOjUzOjE5LTA0OjAwYyXbYgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMi0wNy0yMVQxMDo1MzoxOS0wNDowMBJ4Y94AAAARdEVYdGpwZWc6Y29sb3JzcGFjZQAyLHVVnwAAACB0RVh0anBlZzpzYW1wbGluZy1mYWN0b3IAMXgxLDF4MSwxeDHplfxwAAAAAElFTkSuQmCC"
-  }
-};
-
-function deleteDatabase(then) {
-  cdb.close();
-  let req = indexedDB.deleteDatabase(DB_NAME);
-  req.onsuccess = then;
-  req.onblocked = makeFailure("blocked");
-  req.onupgradeneeded = makeFailure("onupgradeneeded");
-  req.onerror = makeFailure("onerror");
-}
-
-function saveContact() {
-  // takes fast upgrade path
-  cdb.saveContact(CONTACT_PROPS,
-    function() {
-      ok(true, "Saved contact successfully");
-      next();
-    }
-  );
-}
-
-function getContact(callback) {
-  return function() {
-    let req = indexedDB.open(STORE_NAME, DB_VERSION);
-    req.onsuccess = function(event) {
-      let db = event.target.result;
-      let txn = db.transaction([STORE_NAME], "readonly");
-      txn.onabort = makeFailure("Failed to open transaction");
-      let r2 = txn.objectStore(STORE_NAME).get(CONTACT_PROPS.id);
-      r2.onsuccess = function() {
-        db.close();
-        callback(r2.result);
-      };
-      r2.onerror = makeFailure("Failed to get contact");
+  function makeFailure(reason) {
+    return function() {
+      ok(false, reason);
+      SimpleTest.finish();
     };
   };
-}
 
-let savedContact;
+  const { 'utils': Cu } = Components;
+  Cu.import("resource://gre/modules/ContactDB.jsm", window);
+  Cu.importGlobalProperties(["indexedDB"]);
+
+  let cdb = new ContactDB();
+  cdb.init();
 
-let Tests = [
-  saveContact,
+  let CONTACT_PROPS = {
+    id: "ab74671e36be41b680f8f030e7e24ea2",
+    properties: {
+      name: ["Magnificentest foo bar the third"],
+      givenName: ["foo"],
+      familyName: ["bar"],
+      honorificPrefix: ["magnificentest"],
+      honorificSuffix: ["the third"],
+      additionalName: ["addl"],
+      nickname: ["foo"],
+      tel: [
+        {type: ["mobile"], value: "+12345678901", carrier: "ACME Telecommunications", pref: true},
+        {type: ["home", "custom"], value: "7932012346", pref: false},
+      ],
+      email: [{type: ["work"], value: "a@b.c"}, {value: "b@c.d", pref: true}],
+      adr: [
+        {
+          type: ["home"],
+          streetAddress: "street 1",
+          locality: "locality 1",
+          region: "region 1",
+          postalCode: "postal code 1",
+          countryName: "country 1",
+        }
+      ],
+      impp: [{type: ["aim"], value:"im1", pref: true}, {value: "im2"}],
+      org: ["org1", "org2"],
+      jobTitle: ["boss", "superboss"],
+      bday: new Date("1980, 12, 01"),
+      note: ["bla bla bla"],
+      category: ["cat1", "cat2"],
+      url: [{type: ["work", "work2"], value: "www.1.com", pref: true}, {value: "www2.com"}],
+      anniversary: new Date("2000, 12, 01"),
+      sex: "male",
+      genderIdentity: "trisexual",
+      key: "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAC4jAAAuIwF4pT92AAACrElEQVQozwXBTW8bRRgA4Hfemf1er7/iJI4Tq7VFlEZN1VZIlapy4MQBTkXcuSH+G/APKnGAAyCVCqmtCHETp64db5zdtdf7NbMzw/OQH378HkCZpmmapqYMy8yrNnadS6026HC/Z7k+SCkEBwKEEKaUQtQAmlDqrucH23nH4BRkJVRcwmod5gcn6LehFgCaEIIalFZaEcLCq73w355RdvY7nfGQGVTlmRXfqMlrUaSUMUQkhCISJIggKj3/YBHt7PRbpy+cwbF7dN/0vEqTMoo3s0tmGAAAoJAgImMq3xZ5WTPbHj4Mho8Nf+QcPtZBLxEkqeQ2WmklkRCtNdNaI1KpVCnqOC3j5ZK++4vnm6xSWZpzwQtRV2mOiBoRpEKtNQAQggjQcCwqinRxJeKlWW93dlqEsa2QRZbF85nWBAAZY4YUgl9fRJWKVuWgmhwHhpD1+ZrfVjAN867rMCne//rq7OuXjWaLCVHnOWHgFDwMw+Tvi09PdhtJXoVC7bWDIi8Lg8qyMk3rYjLzvJh2O30hwK6TpiG7zWDcck9GR17D9wxDcH7/oNtElRa1aZuLDJN4S7/87tssLVg0/eZs/3h0D5R89vR0v+1AVT0YHX31ZDy9uv7IeJrryeyu2+nS50/PqOXM5qt8Nf/jv08UwTfN27vkchldLpPf/nx/nqSz5sbzhkTYzLRppzNYre/ycrMIZwqsHdf96fd/Xr354AYBr/jESWhgGb6zVSuGrrQS1j4Zk8nc2Hs7frFb3Phc6+fOKDGLKOJTHvlj2u85N4t6vbw7OM4YRVquboPdsPNZ9eb8pvfAOf2iN4dN3EzWadnoO5JY19Oo0TYtw1t8TBqBR9v7wbOXROLWtZ3PH937+ZfXrb6BUHEbXL+FCIfDw92e5zebg8GR54r/AaMVcBxE6hgPAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDEyLTA3LTIxVDEwOjUzOjE5LTA0OjAwYyXbYgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMi0wNy0yMVQxMDo1MzoxOS0wNDowMBJ4Y94AAAARdEVYdGpwZWc6Y29sb3JzcGFjZQAyLHVVnwAAACB0RVh0anBlZzpzYW1wbGluZy1mYWN0b3IAMXgxLDF4MSwxeDHplfxwAAAAAElFTkSuQmCC"
+    }
+  };
 
-  getContact(function(contact) {
-    savedContact = contact;
-    next();
-  }),
+  function deleteDatabase(then) {
+    cdb.close();
+    let req = indexedDB.deleteDatabase(DB_NAME);
+    req.onsuccess = then;
+    req.onblocked = makeFailure("blocked");
+    req.onupgradeneeded = makeFailure("onupgradeneeded");
+    req.onerror = makeFailure("onerror");
+  }
 
-  function() {
-    deleteDatabase(function() {
-      info("slow upgrade");
-      cdb.useFastUpgrade = false;
-      cdb.init();
+  function saveContact() {
+    // takes fast upgrade path
+    cdb.saveContact(CONTACT_PROPS,
+      function() {
+        ok(true, "Saved contact successfully");
+        next();
+      }
+    );
+  }
+
+  function getContact(callback) {
+    return function() {
+      let req = indexedDB.open(STORE_NAME, DB_VERSION);
+      req.onsuccess = function(event) {
+        let db = event.target.result;
+        let txn = db.transaction([STORE_NAME], "readonly");
+        txn.onabort = makeFailure("Failed to open transaction");
+        let r2 = txn.objectStore(STORE_NAME).get(CONTACT_PROPS.id);
+        r2.onsuccess = function() {
+          db.close();
+          callback(r2.result);
+        };
+        r2.onerror = makeFailure("Failed to get contact");
+      };
+    };
+  }
+
+  let savedContact;
+
+  let Tests = [
+    saveContact,
+
+    getContact(function(contact) {
+      savedContact = contact;
       next();
-    });
-  },
+    }),
+
+    function() {
+      deleteDatabase(function() {
+        info("slow upgrade");
+        cdb.useFastUpgrade = false;
+        cdb.init();
+        next();
+      });
+    },
+
+    saveContact,
 
-  saveContact,
+    getContact(function(contact) {
+      checkDBContacts(savedContact, contact);
+      next();
+    }),
+  ];
 
-  getContact(function(contact) {
-    checkDBContacts(savedContact, contact);
+  function next() {
+    let step = Tests.shift();
+    if (step) {
+      step();
+    } else {
+      info("All done");
+      SimpleTest.finish();
+    }
+  }
+
+  // Skip tests on Android
+  if (!isAndroid) {
+    SimpleTest.waitForExplicitFinish();
     next();
-  }),
-];
-
-function next() {
-  let step = Tests.shift();
-  if (step) {
-    step();
   } else {
-    info("All done");
-    SimpleTest.finish();
+    ok(true, "Skip test on Android");
   }
-}
 
-// Skip tests on Android
-if (!isAndroid) {
-  SimpleTest.waitForExplicitFinish();
-  next();
-} else {
-  ok(true, "Skip test on Android");
-}
+  ]]>
+  </script>
 
-</script>
-</pre>
-</body>
-</html>
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=889239"
+     target="_blank">Mozilla Bug 889239</a>
+  </body>
+</window>
--- a/dom/datastore/DataStore.jsm
+++ b/dom/datastore/DataStore.jsm
@@ -23,16 +23,17 @@ const REVISION_VOID = "void";
 // and yet we don't know if it's too low or too high.
 const MAX_REQUESTS = 25;
 
 Cu.import("resource://gre/modules/DataStoreCursor.jsm");
 Cu.import("resource://gre/modules/DataStoreDB.jsm");
 Cu.import("resource://gre/modules/ObjectWrapper.jsm");
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.importGlobalProperties(["indexedDB"]);
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsIMessageSender");
 
 /* Helper functions */
 function createDOMError(aWindow, aEvent) {
   return new aWindow.DOMError(aEvent.target.error.name);
--- a/dom/datastore/DataStoreDB.jsm
+++ b/dom/datastore/DataStoreDB.jsm
@@ -14,16 +14,17 @@ function debug(s) {
 
 const DATASTOREDB_VERSION = 1;
 const DATASTOREDB_OBJECTSTORE_NAME = 'DataStoreDB';
 const DATASTOREDB_REVISION = 'revision';
 const DATASTOREDB_REVISION_INDEX = 'revisionIndex';
 
 Cu.import('resource://gre/modules/IndexedDBHelper.jsm');
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.importGlobalProperties(["indexedDB"]);
 
 XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
                                    "@mozilla.org/uuid-generator;1",
                                    "nsIUUIDGenerator");
 
 this.DataStoreDB = function DataStoreDB() {}
 
 DataStoreDB.prototype = {
--- a/dom/encoding/moz.build
+++ b/dom/encoding/moz.build
@@ -11,16 +11,19 @@ EXPORTS.mozilla.dom += [
     'FallbackEncoding.h',
     'TextDecoder.h',
     'TextEncoder.h',
 ]
 
 SOURCES += [
     'EncodingUtils.cpp',
     'FallbackEncoding.cpp',
+]
+
+UNIFIED_SOURCES += [
     'TextDecoder.cpp',
     'TextEncoder.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -106,45 +106,16 @@ END_INDEXEDDB_NAMESPACE
 
 namespace {
 
 mozilla::StaticRefPtr<IndexedDatabaseManager> gInstance;
 
 mozilla::Atomic<int32_t> gInitialized(0);
 mozilla::Atomic<int32_t> gClosed(0);
 
-// See ResolveConstructors below.
-struct ConstructorInfo {
-  const char* const name;
-  JS::Handle<JSObject*> (* const resolve)(JSContext*, JS::Handle<JSObject*>,
-                                          bool);
-  jsid id;
-};
-
-ConstructorInfo gConstructorInfo[] = {
-
-#define BINDING_ENTRY(_name) \
-  { #_name, _name##Binding::GetConstructorObject, JSID_VOID },
-
-  BINDING_ENTRY(IDBCursor)
-  BINDING_ENTRY(IDBCursorWithValue)
-  BINDING_ENTRY(IDBDatabase)
-  BINDING_ENTRY(IDBFactory)
-  BINDING_ENTRY(IDBFileHandle)
-  BINDING_ENTRY(IDBIndex)
-  BINDING_ENTRY(IDBKeyRange)
-  BINDING_ENTRY(IDBObjectStore)
-  BINDING_ENTRY(IDBOpenDBRequest)
-  BINDING_ENTRY(IDBRequest)
-  BINDING_ENTRY(IDBTransaction)
-  BINDING_ENTRY(IDBVersionChangeEvent)
-
-#undef BINDING_ENTRY
-};
-
 class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId);
 
@@ -202,63 +173,16 @@ struct MOZ_STACK_CLASS InvalidateInfo
   InvalidateInfo(PersistenceType aPersistenceType, const nsACString& aPattern)
   : persistenceType(aPersistenceType), pattern(aPattern)
   { }
 
   PersistenceType persistenceType;
   const nsACString& pattern;
 };
 
-bool
-GetIndexedDB(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
-             JS::MutableHandle<JS::Value> aResult)
-{
-  MOZ_ASSERT(nsContentUtils::IsCallerChrome(), "Only for chrome!");
-  MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
-             "Not a global object!");
-
-  nsRefPtr<IDBFactory> factory;
-  if (NS_FAILED(IDBFactory::Create(aCx, aGlobal, nullptr,
-                                   getter_AddRefs(factory)))) {
-    return false;
-  }
-
-  MOZ_ASSERT(factory, "This should never fail for chrome!");
-
-  return !!WrapNewBindingObject(aCx, aGlobal, factory, aResult);
-}
-
-bool
-IndexedDBLazyGetter(JSContext* aCx, JS::Handle<JSObject*> aGlobal,
-                    JS::Handle<jsid> aId, JS::MutableHandle<JS::Value> aVp)
-{
-  MOZ_ASSERT(nsContentUtils::IsCallerChrome(), "Only for chrome!");
-  MOZ_ASSERT(JSID_IS_STRING(aId), "Bad id!");
-  MOZ_ASSERT(JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(aId), IDB_STR),
-             "Bad id!");
-
-  JS::Rooted<JSObject*> global(aCx, CheckedUnwrap(aGlobal,
-                                                  /* stopAtOuter = */ false));
-  NS_ENSURE_TRUE(global, false);
-  NS_ENSURE_TRUE(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL, false);
-
-  JS::Rooted<JS::Value> indexedDB(aCx);
-  if (!GetIndexedDB(aCx, global, &indexedDB)) {
-    return false;
-  }
-
-  if (!JS_DefinePropertyById(aCx, global, aId, indexedDB, nullptr, nullptr,
-                             JSPROP_ENUMERATE)) {
-    return false;
-  }
-
-  aVp.set(indexedDB);
-  return true;
-}
-
 } // anonymous namespace
 
 IndexedDatabaseManager::IndexedDatabaseManager()
 : mFileMutex("IndexedDatabaseManager.mFileMutex")
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 }
 
@@ -477,65 +401,59 @@ IndexedDatabaseManager::TabContextMayAcc
                                                 aContext.IsBrowserElement(),
                                                 pattern);
 
   return PatternMatchesOrigin(pattern, aOrigin);
 }
 
 // static
 bool
-IndexedDatabaseManager::DefineConstructors(JSContext* aCx,
-                                           JS::Handle<JSObject*> aGlobal)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  for (uint32_t i = 0; i < mozilla::ArrayLength(gConstructorInfo); i++) {
-    if (!gConstructorInfo[i].resolve(aCx, aGlobal, true)) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-// static
-bool
-IndexedDatabaseManager::DefineIndexedDBGetter(JSContext* aCx,
-                                              JS::Handle<JSObject*> aGlobal)
+IndexedDatabaseManager::DefineIndexedDB(JSContext* aCx,
+                                        JS::Handle<JSObject*> aGlobal)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(nsContentUtils::IsCallerChrome(), "Only for chrome!");
   MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
              "Passed object is not a global object!");
 
+  if (!IDBCursorBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBCursorWithValueBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBDatabaseBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBFactoryBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBFileHandleBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBIndexBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBKeyRangeBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBObjectStoreBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBOpenDBRequestBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBRequestBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBTransactionBinding::GetConstructorObject(aCx, aGlobal) ||
+      !IDBVersionChangeEventBinding::GetConstructorObject(aCx, aGlobal))
+  {
+    return false;
+  }
+
+  nsRefPtr<IDBFactory> factory;
+  if (NS_FAILED(IDBFactory::Create(aCx, aGlobal, nullptr,
+                                   getter_AddRefs(factory)))) {
+    return false;
+  }
+
+  MOZ_ASSERT(factory, "This should never fail for chrome!");
+
   JS::Rooted<JS::Value> indexedDB(aCx);
-  if (!GetIndexedDB(aCx, aGlobal, &indexedDB)) {
+  if (!WrapNewBindingObject(aCx, aGlobal, factory, &indexedDB)) {
     return false;
   }
 
   return JS_DefineProperty(aCx, aGlobal, IDB_STR, indexedDB, nullptr, nullptr,
                            JSPROP_ENUMERATE);
 }
 
 // static
 bool
-IndexedDatabaseManager::DefineIndexedDBLazyGetter(JSContext* aCx,
-                                                  JS::Handle<JSObject*> aGlobal)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(nsContentUtils::IsCallerChrome(), "Only for chrome!");
-  MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
-             "Passed object is not a global object!");
-
-  return JS_DefineProperty(aCx, aGlobal, IDB_STR, JSVAL_VOID,
-                           IndexedDBLazyGetter, nullptr, 0);
-}
-
-// static
-bool
 IndexedDatabaseManager::IsClosed()
 {
   return !!gClosed;
 }
 
 #ifdef DEBUG
 // static
 bool
@@ -744,17 +662,17 @@ IndexedDatabaseManager::InitWindowless(c
     return NS_ERROR_FAILURE;
   }
 
   if (hasIndexedDB) {
     NS_WARNING("Passed object already has an 'indexedDB' property!");
     return NS_ERROR_FAILURE;
   }
 
-  if (!DefineConstructors(aCx, global) || !DefineIndexedDBGetter(aCx, global)) {
+  if (!DefineIndexedDB(aCx, global)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 IndexedDatabaseManager::Observe(nsISupports* aSubject, const char* aTopic,
@@ -996,54 +914,8 @@ GetFileReferencesHelper::Run()
   mozilla::MutexAutoLock lock(mMutex);
   NS_ASSERTION(mWaiting, "Huh?!");
 
   mWaiting = false;
   mCondVar.Notify();
 
   return NS_OK;
 }
-
-BEGIN_INDEXEDDB_NAMESPACE
-
-bool
-ResolveConstructors(JSContext* aCx, JS::Handle<JSObject*> aObj,
-                    JS::Handle<jsid> aId, JS::MutableHandle<JSObject*> aObjp)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  // The first time this function is called we need to intern all the strings we
-  // care about.
-  if (JSID_IS_VOID(gConstructorInfo[0].id)) {
-    for (uint32_t i = 0; i < mozilla::ArrayLength(gConstructorInfo); i++) {
-      JS::Rooted<JSString*> str(aCx,
-                                JS_InternString(aCx, gConstructorInfo[i].name));
-      if (!str) {
-        NS_WARNING("Failed to intern string!");
-        while (i) {
-          gConstructorInfo[--i].id = JSID_VOID;
-        }
-        return false;
-      }
-      gConstructorInfo[i].id = INTERNED_STRING_TO_JSID(aCx, str);
-    }
-  }
-
-  // Now resolve.
-  for (uint32_t i = 0; i < mozilla::ArrayLength(gConstructorInfo); i++) {
-    if (gConstructorInfo[i].id == aId) {
-      JS::Rooted<JSObject*> constructor(aCx,
-        gConstructorInfo[i].resolve(aCx, aObj, true));
-      if (!constructor) {
-        return false;
-      }
-
-      aObjp.set(aObj);
-      return true;
-    }
-  }
-
-  // Not resolved.
-  aObjp.set(nullptr);
-  return true;
-}
-
-END_INDEXEDDB_NAMESPACE
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -135,23 +135,17 @@ public:
   FireWindowOnError(nsPIDOMWindow* aOwner,
                     nsEventChainPostVisitor& aVisitor);
 
   static bool
   TabContextMayAccessOrigin(const mozilla::dom::TabContext& aContext,
                             const nsACString& aOrigin);
 
   static bool
-  DefineConstructors(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
-
-  static bool
-  DefineIndexedDBGetter(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
-
-  static bool
-  DefineIndexedDBLazyGetter(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
+  DefineIndexedDB(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
 
 private:
   IndexedDatabaseManager();
   ~IndexedDatabaseManager();
 
   nsresult
   Init();
 
@@ -171,15 +165,11 @@ private:
   // It's s also used to atomically update FileInfo.mRefCnt, FileInfo.mDBRefCnt
   // and FileInfo.mSliceRefCnt
   mozilla::Mutex mFileMutex;
 
   static bool sIsMainProcess;
   static mozilla::Atomic<int32_t> sLowDiskSpaceMode;
 };
 
-bool
-ResolveConstructors(JSContext* aCx, JS::Handle<JSObject*> aObj,
-                    JS::Handle<jsid> aId, JS::MutableHandle<JSObject*> aObjp);
-
 END_INDEXEDDB_NAMESPACE
 
 #endif /* mozilla_dom_indexeddb_indexeddatabasemanager_h__ */
--- a/dom/indexedDB/test/chrome.ini
+++ b/dom/indexedDB/test/chrome.ini
@@ -1,4 +1,5 @@
 [DEFAULT]
 support-files = chromeHelpers.js
 
-[test_globalObjects.xul]
+[test_globalObjects_chrome.xul]
+[test_globalObjects_other.xul]
--- a/dom/indexedDB/test/chromeHelpers.js
+++ b/dom/indexedDB/test/chromeHelpers.js
@@ -2,21 +2,25 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu } = Components;
 
 let testGenerator = testSteps();
 
-function runTest()
-{
-  SimpleTest.waitForExplicitFinish();
+if (!window.runTest) {
+  window.runTest = function()
+  {
+    Cu.importGlobalProperties(["indexedDB"]);
 
-  testGenerator.next();
+    SimpleTest.waitForExplicitFinish();
+
+    testGenerator.next();
+  }
 }
 
 function finishTest()
 {
   SimpleTest.executeSoon(function() {
     testGenerator.close();
     SimpleTest.finish();
   });
--- a/dom/indexedDB/test/mochitest.ini
+++ b/dom/indexedDB/test/mochitest.ini
@@ -55,17 +55,17 @@ support-files =
 [test_file_resurrection_transaction_abort.html]
 [test_file_sharing.html]
 [test_file_transaction_abort.html]
 [test_filehandle_quota.html]
 [test_filehandle_serialization.html]
 [test_filehandle_store_snapshot.html]
 [test_getAll.html]
 [test_get_filehandle.html]
-[test_globalObjects.html]
+[test_globalObjects_content.html]
 [test_global_data.html]
 [test_index_empty_keyPath.html]
 [test_index_getAll.html]
 [test_index_getAllObjects.html]
 [test_index_object_cursors.html]
 [test_index_update_delete.html]
 [test_indexes.html]
 [test_indexes_bad_values.html]
rename from dom/indexedDB/test/test_globalObjects.xul
rename to dom/indexedDB/test/test_globalObjects_chrome.xul
--- a/dom/indexedDB/test/test_globalObjects.xul
+++ b/dom/indexedDB/test/test_globalObjects_chrome.xul
@@ -23,45 +23,16 @@
     var request = indexedDB.open(name, 1);
     request.onerror = errorHandler;
     request.onsuccess = grabEventAndContinueHandler;
     let event = yield undefined;
 
     let db = event.target.result;
     ok(db, "Got database");
 
-    // Test for IDBKeyRange and indexedDB availability in bootstrap files.
-    let test = Cc["@mozilla.org/dom/indexeddb/GlobalObjectsComponent;1"].
-               createInstance(Ci.nsISupports).wrappedJSObject;
-    test.ok = ok;
-    test.finishTest = continueToNextStep;
-    test.runTest();
-    yield undefined;
-
-    Cu.import("resource://gre/modules/AddonManager.jsm");
-    AddonManager.getAddonByID("indexedDB-test@mozilla.org",
-                              grabEventAndContinueHandler);
-    let addon = yield undefined;
-    addon.uninstall();
-
-    Cu.import("resource://gre/modules/Services.jsm");
-    for each (var stage in [ "install", "startup", "shutdown", "uninstall" ]) {
-      for each (var symbol in [ "IDBKeyRange", "indexedDB" ]) {
-        let pref;
-        try {
-          pref = Services.prefs.getBoolPref("indexeddbtest.bootstrap." + stage +
-                                            "." + symbol);
-        }
-        catch(ex) {
-          pref = false;
-        }
-        ok(pref, "Symbol '" + symbol + "' present during '" + stage + "'");
-      }
-    }
-
     finishTest();
     yield undefined;
   }
   ]]>
   </script>
 
   <script type="text/javascript;version=1.7" src="chromeHelpers.js"></script>
 
rename from dom/indexedDB/test/test_globalObjects.html
rename to dom/indexedDB/test/test_globalObjects_content.html
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_globalObjects_other.xul
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<window title="Mozilla Bug 832883"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        onload="runTest();">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <script type="application/javascript;version=1.7">
+  <![CDATA[
+  function testSteps() {
+    // Test for IDBKeyRange and indexedDB availability in bootstrap files.
+    let test = Cc["@mozilla.org/dom/indexeddb/GlobalObjectsComponent;1"].
+               createInstance(Ci.nsISupports).wrappedJSObject;
+    test.ok = ok;
+    test.finishTest = continueToNextStep;
+    test.runTest();
+    yield undefined;
+
+    Cu.import("resource://gre/modules/AddonManager.jsm");
+    AddonManager.getAddonByID("indexedDB-test@mozilla.org",
+                              grabEventAndContinueHandler);
+    let addon = yield undefined;
+    addon.uninstall();
+
+    Cu.import("resource://gre/modules/Services.jsm");
+    for each (var stage in [ "install", "startup", "shutdown", "uninstall" ]) {
+      for each (var symbol in [ "IDBKeyRange", "indexedDB" ]) {
+        let pref;
+        try {
+          pref = Services.prefs.getBoolPref("indexeddbtest.bootstrap." + stage +
+                                            "." + symbol);
+        }
+        catch(ex) {
+          pref = false;
+        }
+        ok(pref, "Symbol '" + symbol + "' present during '" + stage + "'");
+      }
+    }
+
+    finishTest();
+    yield undefined;
+  }
+
+  window.runTest = function() {
+    SimpleTest.waitForExplicitFinish();
+
+    testGenerator.next();
+  }
+  ]]>
+  </script>
+
+  <script type="text/javascript;version=1.7" src="chromeHelpers.js"></script>
+
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=832883"
+     target="_blank">Mozilla Bug 832883</a>
+  </body>
+</window>
--- a/dom/indexedDB/test/unit/GlobalObjectsChild.js
+++ b/dom/indexedDB/test/unit/GlobalObjectsChild.js
@@ -13,16 +13,18 @@ function finishTest()
   do_execute_soon(function() {
     do_test_finished();
   });
 }
 
 function run_test() {
   const name = "Splendid Test";
 
+  Cu.importGlobalProperties(["indexedDB"]);
+
   do_test_pending();
 
   let keyRange = IDBKeyRange.only(42);
   ok(keyRange, "Got keyRange");
 
   let request = indexedDB.open(name, 1);
   request.onerror = function(event) {
     ok(false, "indexedDB error, '" + event.target.error.name + "'");
--- a/dom/indexedDB/test/unit/GlobalObjectsComponent.js
+++ b/dom/indexedDB/test/unit/GlobalObjectsComponent.js
@@ -1,14 +1,17 @@
 /**
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.importGlobalProperties(["indexedDB"]);
 
 function GlobalObjectsComponent() {
   this.wrappedJSObject = this;
 }
 
 GlobalObjectsComponent.prototype =
 {
   classID: Components.ID("{949ebf50-e0da-44b9-8335-cbfd4febfdcc}"),
--- a/dom/indexedDB/test/unit/GlobalObjectsModule.jsm
+++ b/dom/indexedDB/test/unit/GlobalObjectsModule.jsm
@@ -1,13 +1,15 @@
 /**
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+Components.utils.importGlobalProperties(["indexedDB"]);
+
 this.EXPORTED_SYMBOLS = [
   "GlobalObjectsModule"
 ];
 
 this.GlobalObjectsModule = function GlobalObjectsModule() {
 }
 
 GlobalObjectsModule.prototype = {
--- a/dom/indexedDB/test/unit/head.js
+++ b/dom/indexedDB/test/unit/head.js
@@ -33,25 +33,29 @@ function todo(condition, name, diag) {
 function info(name, message) {
   do_print(name);
 }
 
 function run_test() {
   runTest();
 };
 
-function runTest()
-{
-  // XPCShell does not get a profile by default.
-  do_get_profile();
+if (!this.runTest) {
+  this.runTest = function()
+  {
+    // XPCShell does not get a profile by default.
+    do_get_profile();
 
-  enableExperimental();
+    enableExperimental();
+
+    Cu.importGlobalProperties(["indexedDB"]);
 
-  do_test_pending();
-  testGenerator.next();
+    do_test_pending();
+    testGenerator.next();
+  }
 }
 
 function finishTest()
 {
   resetExperimental();
   SpecialPowers.notifyObserversInParentProcess(null, "disk-space-watcher",
                                                "free");
 
--- a/dom/indexedDB/test/unit/mochitest.ini
+++ b/dom/indexedDB/test/unit/mochitest.ini
@@ -13,18 +13,19 @@
 [test_create_objectStore.js]
 [test_cursor_mutation.js]
 [test_cursor_update_updates_indexes.js]
 [test_cursors.js]
 [test_deleteDatabase.js]
 [test_deleteDatabase_interactions.js]
 [test_event_source.js]
 [test_getAll.js]
-[test_globalObjects.js]
 [test_globalObjects_ipc.js]
+[test_globalObjects_other.js]
+[test_globalObjects_xpc.js]
 [test_global_data.js]
 [test_index_empty_keyPath.js]
 [test_index_getAll.js]
 [test_index_getAllObjects.js]
 [test_index_object_cursors.js]
 [test_index_update_delete.js]
 [test_indexes.js]
 [test_indexes_bad_values.js]
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_globalObjects_other.js
@@ -0,0 +1,60 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var testGenerator = testSteps();
+
+function testSteps()
+{
+  let ioService =
+    Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
+
+  function getSpec(filename) {
+    let file = do_get_file(filename);
+    let uri = ioService.newFileURI(file);
+    return uri.spec;
+  }
+
+  // Test for IDBKeyRange and indexedDB availability in JS modules.
+  Cu.import(getSpec("GlobalObjectsModule.jsm"));
+  let test = new GlobalObjectsModule();
+  test.ok = ok;
+  test.finishTest = continueToNextStep;
+  test.runTest();
+  yield undefined;
+
+  // Test for IDBKeyRange and indexedDB availability in JS components.
+  do_load_manifest("GlobalObjectsComponent.manifest");
+  test = Cc["@mozilla.org/dom/indexeddb/GlobalObjectsComponent;1"].
+         createInstance(Ci.nsISupports).wrappedJSObject;
+  test.ok = ok;
+  test.finishTest = continueToNextStep;
+  test.runTest();
+  yield undefined;
+
+  // Test for IDBKeyRange and indexedDB availability in JS sandboxes.
+  let principal = Cc["@mozilla.org/systemprincipal;1"].
+                  createInstance(Ci.nsIPrincipal);
+  let sandbox = new Cu.Sandbox(principal,
+                               { wantGlobalProperties: ["indexedDB"] });
+  sandbox.__SCRIPT_URI_SPEC__ = getSpec("GlobalObjectsSandbox.js");
+  Cu.evalInSandbox(
+    "Components.classes['@mozilla.org/moz/jssubscript-loader;1'] \
+               .createInstance(Components.interfaces.mozIJSSubScriptLoader) \
+               .loadSubScript(__SCRIPT_URI_SPEC__);", sandbox, "1.7");
+  sandbox.ok = ok;
+  sandbox.finishTest = continueToNextStep;
+  Cu.evalInSandbox("runTest();", sandbox);
+  yield undefined;
+
+  finishTest();
+  yield undefined;
+}
+
+this.runTest = function() {
+  do_get_profile();
+
+  do_test_pending();
+  testGenerator.next();
+}
rename from dom/indexedDB/test/unit/test_globalObjects.js
rename to dom/indexedDB/test/unit/test_globalObjects_xpc.js
--- a/dom/indexedDB/test/unit/test_globalObjects.js
+++ b/dom/indexedDB/test/unit/test_globalObjects_xpc.js
@@ -4,64 +4,23 @@
  */
 
 var testGenerator = testSteps();
 
 function testSteps()
 {
   const name = "Splendid Test";
 
-  let ioService =
-    Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
-
-  function getSpec(filename) {
-    let file = do_get_file(filename);
-    let uri = ioService.newFileURI(file);
-    return uri.spec;
-  }
-
   // Test for IDBKeyRange and indexedDB availability in xpcshell.
   let keyRange = IDBKeyRange.only(42);
   ok(keyRange, "Got keyRange");
 
   let request = indexedDB.open(name, 1);
   request.onerror = errorHandler;
   request.onsuccess = grabEventAndContinueHandler;
   let event = yield undefined;
 
   let db = event.target.result;
   ok(db, "Got database");
 
-  // Test for IDBKeyRange and indexedDB availability in JS modules.
-  Cu.import(getSpec("GlobalObjectsModule.jsm"));
-  let test = new GlobalObjectsModule();
-  test.ok = ok;
-  test.finishTest = continueToNextStep;
-  test.runTest();
-  yield undefined;
-
-  // Test for IDBKeyRange and indexedDB availability in JS components.
-  do_load_manifest("GlobalObjectsComponent.manifest");
-  test = Cc["@mozilla.org/dom/indexeddb/GlobalObjectsComponent;1"].
-         createInstance(Ci.nsISupports).wrappedJSObject;
-  test.ok = ok;
-  test.finishTest = continueToNextStep;
-  test.runTest();
-  yield undefined;
-
-  // Test for IDBKeyRange and indexedDB availability in JS sandboxes.
-  let principal = Cc["@mozilla.org/systemprincipal;1"].
-                  createInstance(Ci.nsIPrincipal);
-  let sandbox = new Cu.Sandbox(principal,
-                               { wantGlobalProperties: ["indexedDB"] });
-  sandbox.__SCRIPT_URI_SPEC__ = getSpec("GlobalObjectsSandbox.js");
-  Cu.evalInSandbox(
-    "Components.classes['@mozilla.org/moz/jssubscript-loader;1'] \
-               .createInstance(Components.interfaces.mozIJSSubScriptLoader) \
-               .loadSubScript(__SCRIPT_URI_SPEC__);", sandbox, "1.7");
-  sandbox.ok = ok;
-  sandbox.finishTest = continueToNextStep;
-  Cu.evalInSandbox("runTest();", sandbox);
-  yield undefined;
-
   finishTest();
   yield undefined;
 }
--- a/dom/indexedDB/test/unit/xpcshell.ini
+++ b/dom/indexedDB/test/unit/xpcshell.ini
@@ -23,20 +23,21 @@ support-files =
 [test_create_objectStore.js]
 [test_cursor_mutation.js]
 [test_cursor_update_updates_indexes.js]
 [test_cursors.js]
 [test_deleteDatabase.js]
 [test_deleteDatabase_interactions.js]
 [test_event_source.js]
 [test_getAll.js]
-[test_globalObjects.js]
 [test_globalObjects_ipc.js]
 # FIXME/bug 575918: out-of-process xpcshell is broken on OS X
 skip-if = os == "mac" || os == "android"
+[test_globalObjects_other.js]
+[test_globalObjects_xpc.js]
 [test_global_data.js]
 [test_index_empty_keyPath.js]
 [test_index_getAll.js]
 [test_index_getAllObjects.js]
 [test_index_object_cursors.js]
 [test_index_update_delete.js]
 [test_indexes.js]
 [test_indexes_bad_values.js]
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -221,19 +221,22 @@ parent:
 
     PContentDialog(uint32_t aType, nsCString aName, nsCString aFeatures,
                    int32_t[] aIntParams, nsString[] aStringParams);
 
     /**
      * Create a layout frame (encapsulating a remote layer tree) for
      * the page that is currently loaded in the <browser>.
      */
-    sync PRenderFrame()
+    sync PRenderFrame();
+
+    sync InitRenderFrame(PRenderFrame aFrame)
         returns (ScrollingBehavior scrolling,
-                 TextureFactoryIdentifier textureFactoryIdentifier, uint64_t layersId);
+                 TextureFactoryIdentifier textureFactoryIdentifier, uint64_t layersId,
+                 bool success);
 
     /** 
      * Starts an offline application cache update.
      * @param manifestURI
      *   URI of the manifest to fetch, the application cache group ID
      * @param documentURI
      *   URI of the document that referred the manifest
      * @param stickDocument
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2161,19 +2161,17 @@ TabChild::RecvDestroy()
 bool
 TabChild::RecvSetUpdateHitRegion(const bool& aEnabled)
 {
     mUpdateHitRegion = aEnabled;
     return true;
 }
 
 PRenderFrameChild*
-TabChild::AllocPRenderFrameChild(ScrollingBehavior* aScrolling,
-                            TextureFactoryIdentifier* aTextureFactoryIdentifier,
-                            uint64_t* aLayersId)
+TabChild::AllocPRenderFrameChild()
 {
     return new RenderFrameChild();
 }
 
 bool
 TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame)
 {
     delete aFrame;
@@ -2221,21 +2219,27 @@ TabChild::InitTabChildGlobal(FrameScript
 }
 
 bool
 TabChild::InitRenderingState()
 {
     static_cast<PuppetWidget*>(mWidget.get())->InitIMEState();
 
     uint64_t id;
+    bool success;
     RenderFrameChild* remoteFrame =
-        static_cast<RenderFrameChild*>(SendPRenderFrameConstructor(
-                                         &mScrolling, &mTextureFactoryIdentifier, &id));
+        static_cast<RenderFrameChild*>(SendPRenderFrameConstructor());
     if (!remoteFrame) {
+        NS_WARNING("failed to construct RenderFrame");
+        return false;
+    }
+    SendInitRenderFrame(remoteFrame, &mScrolling, &mTextureFactoryIdentifier, &id, &success);
+    if (!success) {
       NS_WARNING("failed to construct RenderFrame");
+      PRenderFrameChild::Send__delete__(remoteFrame);
       return false;
     }
 
     PLayerTransactionChild* shadowManager = nullptr;
     if (id != 0) {
         // Pushing layers transactions directly to a separate
         // compositor context.
         PCompositorChild* compositorChild = CompositorChild::Get();
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -357,19 +357,17 @@ public:
     GetFrom(nsIDOMWindow* aWindow)
     {
       nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
       nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webNav);
       return GetFrom(docShell);
     }
 
 protected:
-    virtual PRenderFrameChild* AllocPRenderFrameChild(ScrollingBehavior* aScrolling,
-                                                      TextureFactoryIdentifier* aTextureFactoryIdentifier,
-                                                      uint64_t* aLayersId) MOZ_OVERRIDE;
+    virtual PRenderFrameChild* AllocPRenderFrameChild() MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) MOZ_OVERRIDE;
     virtual bool RecvDestroy() MOZ_OVERRIDE;
     virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) MOZ_OVERRIDE;
 
     nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& event);
 
     virtual PIndexedDBChild* AllocPIndexedDBChild(const nsCString& aGroup,
                                                   const nsCString& aASCIIOrigin,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1440,33 +1440,46 @@ TabParent::HandleDelayedDialogs()
   }
   if (ShouldDelayDialogs() && mDelayedDialogs.Length()) {
     nsContentUtils::DispatchTrustedEvent(mFrameElement->OwnerDoc(), mFrameElement,
                                          NS_LITERAL_STRING("MozDelayedModalDialog"),
                                          true, true);
   }
 }
 
-PRenderFrameParent*
-TabParent::AllocPRenderFrameParent(ScrollingBehavior* aScrolling,
-                                   TextureFactoryIdentifier* aTextureFactoryIdentifier,
-                                   uint64_t* aLayersId)
+bool
+TabParent::RecvInitRenderFrame(PRenderFrameParent* aFrame,
+                               ScrollingBehavior* aScrolling,
+                               TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                               uint64_t* aLayersId,
+                               bool *aSuccess)
 {
-  MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty());
+  *aScrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
+  *aTextureFactoryIdentifier = TextureFactoryIdentifier();
+  *aLayersId = 0;
 
   nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
   if (!frameLoader) {
-    NS_WARNING("Can't allocate graphics resources, aborting subprocess");
-    return nullptr;
+    NS_WARNING("Can't allocate graphics resources. May already be shutting down.");
+    *aSuccess = false;
+    return true;
   }
 
-  *aScrolling = UseAsyncPanZoom() ? ASYNC_PAN_ZOOM : DEFAULT_SCROLLING;
-  return new RenderFrameParent(frameLoader,
-                               *aScrolling,
-                               aTextureFactoryIdentifier, aLayersId);
+  static_cast<RenderFrameParent*>(aFrame)->Init(frameLoader, *aScrolling,
+                                                aTextureFactoryIdentifier, aLayersId);
+
+  *aSuccess = true;
+  return true;
+}
+
+PRenderFrameParent*
+TabParent::AllocPRenderFrameParent()
+{
+  MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty());
+  return new RenderFrameParent();
 }
 
 bool
 TabParent::DeallocPRenderFrameParent(PRenderFrameParent* aFrame)
 {
   delete aFrame;
   return true;
 }
@@ -1595,20 +1608,17 @@ TabParent::RecvBrowserFrameOpenWindow(PB
   BrowserElementParent::OpenWindowResult opened =
     BrowserElementParent::OpenWindowOOP(static_cast<TabParent*>(aOpener),
                                         this, aURL, aName, aFeatures);
   *aOutWindowOpened = (opened != BrowserElementParent::OPEN_WINDOW_CANCELLED);
   return true;
 }
 
 bool
-TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* actor,
-                                       ScrollingBehavior* scrolling,
-                                       TextureFactoryIdentifier* factoryIdentifier,
-                                       uint64_t* layersId)
+TabParent::RecvPRenderFrameConstructor(PRenderFrameParent* actor)
 {
   RenderFrameParent* rfp = GetRenderFrame();
   if (mDimensions != nsIntSize() && rfp) {
     rfp->NotifyDimensionsChanged(ScreenIntSize::FromUnknownSize(
       gfx::IntSize(mDimensions.width, mDimensions.height)));
   }
 
   return true;
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -104,20 +104,22 @@ public:
      * capturer.
      */
     bool TryCapture(const WidgetGUIEvent& aEvent);
 
     void Destroy();
 
     virtual bool RecvMoveFocus(const bool& aForward);
     virtual bool RecvEvent(const RemoteDOMEvent& aEvent);
-    virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* actor,
-                                             ScrollingBehavior* scrolling,
-                                             TextureFactoryIdentifier* identifier,
-                                             uint64_t* layersId);
+    virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* aFrame);
+    virtual bool RecvInitRenderFrame(PRenderFrameParent* aFrame,
+                                     ScrollingBehavior* aScrolling,
+                                     TextureFactoryIdentifier* aTextureFactoryIdentifier,
+                                     uint64_t* aLayersId,
+                                     bool *aSuccess);
     virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
                                             const nsString& aURL,
                                             const nsString& aName,
                                             const nsString& aFeatures,
                                             bool* aOutWindowOpened);
     virtual bool AnswerCreateWindow(PBrowserParent** retval);
     virtual bool RecvSyncMessage(const nsString& aMessage,
                                  const ClonedMessageData& aData,
@@ -302,19 +304,17 @@ protected:
       nsCString mFeatures;
       nsCOMPtr<nsIDialogParamBlock> mParams;
     };
     InfallibleTArray<DelayedDialogData*> mDelayedDialogs;
 
     bool ShouldDelayDialogs();
     bool AllowContentIME();
 
-    virtual PRenderFrameParent* AllocPRenderFrameParent(ScrollingBehavior* aScrolling,
-                                                        TextureFactoryIdentifier* aTextureFactoryIdentifier,
-                                                        uint64_t* aLayersId) MOZ_OVERRIDE;
+    virtual PRenderFrameParent* AllocPRenderFrameParent() MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrameParent(PRenderFrameParent* aFrame) MOZ_OVERRIDE;
 
     // IME
     static TabParent *mIMETabParent;
     nsString mIMECacheText;
     uint32_t mIMESelectionAnchor;
     uint32_t mIMESelectionFocus;
     bool mIMEComposing;
--- a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
+++ b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
@@ -4,16 +4,17 @@
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/PhoneNumberUtils.jsm");
+Cu.importGlobalProperties(["indexedDB"]);
 
 var RIL = {};
 Cu.import("resource://gre/modules/ril_consts.js", RIL);
 
 const RIL_MOBILEMESSAGEDATABASESERVICE_CONTRACTID =
   "@mozilla.org/mobilemessage/rilmobilemessagedatabaseservice;1";
 const RIL_MOBILEMESSAGEDATABASESERVICE_CID =
   Components.ID("{29785f90-6b5b-11e2-9201-3b280170b2ec}");
--- a/dom/network/src/NetworkStatsDB.jsm
+++ b/dom/network/src/NetworkStatsDB.jsm
@@ -8,16 +8,17 @@ this.EXPORTED_SYMBOLS = ['NetworkStatsDB
 
 const DEBUG = false;
 function debug(s) { dump("-*- NetworkStatsDB: " + s + "\n"); }
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
+Cu.importGlobalProperties(["indexedDB"]);
 
 const DB_NAME = "net_stats";
 const DB_VERSION = 3;
 const STORE_NAME = "net_stats";
 
 // Constant defining the maximum values allowed per interface. If more, older
 // will be erased.
 const VALUES_MAX_LENGTH = 6 * 30;
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -6,27 +6,30 @@
 
 #include "mozilla/dom/Promise.h"
 
 #include "jsfriendapi.h"
 #include "mozilla/dom/OwningNonNull.h"
 #include "mozilla/dom/PromiseBinding.h"
 #include "mozilla/Preferences.h"
 #include "PromiseCallback.h"
+#include "PromiseNativeHandler.h"
 #include "nsContentUtils.h"
 #include "nsPIDOMWindow.h"
 #include "WorkerPrivate.h"
 #include "nsJSPrincipals.h"
 #include "nsJSUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsJSEnvironment.h"
 
 namespace mozilla {
 namespace dom {
 
+NS_IMPL_ISUPPORTS0(PromiseNativeHandler)
+
 // PromiseTask
 
 // This class processes the promise's callbacks with promise's result.
 class PromiseTask MOZ_FINAL : public nsRunnable
 {
 public:
   PromiseTask(Promise* aPromise)
     : mPromise(aPromise)
@@ -186,35 +189,35 @@ Promise::EnabledForScope(JSContext* aCx,
 
   nsIPrincipal* prin = nsContentUtils::GetSubjectPrincipal();
   return nsContentUtils::IsSystemPrincipal(prin) ||
     prin->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED;
 }
 
 void
 Promise::MaybeResolve(JSContext* aCx,
-                      const Optional<JS::Handle<JS::Value> >& aValue)
+                      JS::Handle<JS::Value> aValue)
 {
   MaybeResolveInternal(aCx, aValue);
 }
 
 void
 Promise::MaybeReject(JSContext* aCx,
-                     const Optional<JS::Handle<JS::Value> >& aValue)
+                     JS::Handle<JS::Value> aValue)
 {
   MaybeRejectInternal(aCx, aValue);
 }
 
 static void
 EnterCompartment(Maybe<JSAutoCompartment>& aAc, JSContext* aCx,
-                 const Optional<JS::Handle<JS::Value> >& aValue)
+                 JS::Handle<JS::Value> aValue)
 {
   // FIXME Bug 878849
-  if (aValue.WasPassed() && aValue.Value().isObject()) {
-    JS::Rooted<JSObject*> rooted(aCx, &aValue.Value().toObject());
+  if (aValue.isObject()) {
+    JS::Rooted<JSObject*> rooted(aCx, &aValue.toObject());
     aAc.construct(aCx, rooted);
   }
 }
 
 enum {
   SLOT_PROMISE = 0,
   SLOT_TASK
 };
@@ -229,28 +232,23 @@ Promise::JSCallback(JSContext *aCx, unsi
                                                         SLOT_PROMISE));
   MOZ_ASSERT(v.isObject());
 
   Promise* promise;
   if (NS_FAILED(UNWRAP_OBJECT(Promise, aCx, &v.toObject(), promise))) {
     return Throw(aCx, NS_ERROR_UNEXPECTED);
   }
 
-  Optional<JS::Handle<JS::Value> > value(aCx);
-  if (aArgc) {
-    value.Value() = args[0];
-  }
-
   v = js::GetFunctionNativeReserved(&args.callee(), SLOT_TASK);
   PromiseCallback::Task task = static_cast<PromiseCallback::Task>(v.toInt32());
 
   if (task == PromiseCallback::Resolve) {
-    promise->MaybeResolveInternal(aCx, value);
+    promise->MaybeResolveInternal(aCx, args.get(0));
   } else {
-    promise->MaybeRejectInternal(aCx, value);
+    promise->MaybeRejectInternal(aCx, args.get(0));
   }
 
   return true;
 }
 
 /* static */ JSObject*
 Promise::CreateFunction(JSContext* aCx, JSObject* aParent, Promise* aPromise,
                         int32_t aTask)
@@ -304,18 +302,18 @@ Promise::Constructor(const GlobalObject&
     return nullptr;
   }
 
   aInit.Call(promise, resolveFunc, rejectFunc, aRv,
              CallbackObject::eRethrowExceptions);
   aRv.WouldReportJSException();
 
   if (aRv.IsJSException()) {
-    Optional<JS::Handle<JS::Value> > value(cx);
-    aRv.StealJSException(cx, &value.Value());
+    JS::Rooted<JS::Value> value(cx);
+    aRv.StealJSException(cx, &value);
 
     Maybe<JSAutoCompartment> ac;
     EnterCompartment(ac, cx, value);
     promise->MaybeRejectInternal(cx, value);
   }
 
   return promise.forget();
 }
@@ -327,35 +325,33 @@ Promise::Resolve(const GlobalObject& aGl
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
   if (!window) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<Promise> promise = new Promise(window);
 
-  Optional<JS::Handle<JS::Value> > value(aCx, aValue);
-  promise->MaybeResolveInternal(aCx, value);
+  promise->MaybeResolveInternal(aCx, aValue);
   return promise.forget();
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
   if (!window) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<Promise> promise = new Promise(window);
 
-  Optional<JS::Handle<JS::Value> > value(aCx, aValue);
-  promise->MaybeRejectInternal(aCx, value);
+  promise->MaybeRejectInternal(aCx, aValue);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 Promise::Then(const Optional<OwningNonNull<AnyCallback> >& aResolveCallback,
               const Optional<OwningNonNull<AnyCallback> >& aRejectCallback)
 {
   nsRefPtr<Promise> promise = new Promise(GetParentObject());
@@ -382,16 +378,28 @@ Promise::Then(const Optional<OwningNonNu
 already_AddRefed<Promise>
 Promise::Catch(const Optional<OwningNonNull<AnyCallback> >& aRejectCallback)
 {
   Optional<OwningNonNull<AnyCallback> > resolveCb;
   return Then(resolveCb, aRejectCallback);
 }
 
 void
+Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable)
+{
+  nsRefPtr<PromiseCallback> resolveCb =
+  new NativePromiseCallback(aRunnable, Resolved);
+
+  nsRefPtr<PromiseCallback> rejectCb =
+  new NativePromiseCallback(aRunnable, Rejected);
+
+  AppendCallbacks(resolveCb, rejectCb);
+}
+
+void
 Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
                          PromiseCallback* aRejectCallback)
 {
   if (aResolveCallback) {
     mResolveCallbacks.AppendElement(aResolveCallback);
   }
 
   if (aRejectCallback) {
@@ -415,18 +423,19 @@ Promise::RunTask()
   MOZ_ASSERT(mState != Pending);
 
   nsTArray<nsRefPtr<PromiseCallback> > callbacks;
   callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
                                             : mRejectCallbacks);
   mResolveCallbacks.Clear();
   mRejectCallbacks.Clear();
 
-  JSAutoRequest ar(nsContentUtils::GetSafeJSContext());
-  Optional<JS::Handle<JS::Value> > value(nsContentUtils::GetSafeJSContext(), mResult);
+  JSContext* cx = nsContentUtils::GetSafeJSContext();
+  JSAutoRequest ar(cx);
+  JS::Rooted<JS::Value> value(cx, mResult);
 
   for (uint32_t i = 0; i < callbacks.Length(); ++i) {
     callbacks[i]->Call(value);
   }
 }
 
 void
 Promise::MaybeReportRejected()
@@ -452,79 +461,77 @@ Promise::MaybeReportRejected()
                            report,
                            nullptr,
                            nsContentUtils::IsSystemPrincipal(principal),
                            win));
 }
 
 void
 Promise::MaybeResolveInternal(JSContext* aCx,
-                              const Optional<JS::Handle<JS::Value> >& aValue,
+                              JS::Handle<JS::Value> aValue,
                               PromiseTaskSync aAsynchronous)
 {
   if (mResolvePending) {
     return;
   }
 
   ResolveInternal(aCx, aValue, aAsynchronous);
 }
 
 void
 Promise::MaybeRejectInternal(JSContext* aCx,
-                             const Optional<JS::Handle<JS::Value> >& aValue,
+                             JS::Handle<JS::Value> aValue,
                              PromiseTaskSync aAsynchronous)
 {
   if (mResolvePending) {
     return;
   }
 
   RejectInternal(aCx, aValue, aAsynchronous);
 }
 
 void
 Promise::ResolveInternal(JSContext* aCx,
-                         const Optional<JS::Handle<JS::Value> >& aValue,
+                         JS::Handle<JS::Value> aValue,
                          PromiseTaskSync aAsynchronous)
 {
   mResolvePending = true;
 
   // TODO: Bug 879245 - Then-able objects
-  if (aValue.WasPassed() && aValue.Value().isObject()) {
-    JS::Rooted<JSObject*> valueObj(aCx, &aValue.Value().toObject());
+  if (aValue.isObject()) {
+    JS::Rooted<JSObject*> valueObj(aCx, &aValue.toObject());
     Promise* nextPromise;
     nsresult rv = UNWRAP_OBJECT(Promise, aCx, valueObj, nextPromise);
 
     if (NS_SUCCEEDED(rv)) {
       nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(this);
       nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(this);
       nextPromise->AppendCallbacks(resolveCb, rejectCb);
       return;
     }
   }
 
   // If the synchronous flag is set, process our resolve callbacks with
   // value. Otherwise, the synchronous flag is unset, queue a task to process
   // own resolve callbacks with value. Otherwise, the synchronous flag is
   // unset, queue a task to process our resolve callbacks with value.
-  RunResolveTask(aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
-                 Resolved, aAsynchronous);
+  RunResolveTask(aValue, Resolved, aAsynchronous);
 }
 
 void
 Promise::RejectInternal(JSContext* aCx,
-                        const Optional<JS::Handle<JS::Value> >& aValue,
+                        JS::Handle<JS::Value> aValue,
                         PromiseTaskSync aAsynchronous)
 {
   mResolvePending = true;
 
   // If the synchronous flag is set, process our reject callbacks with
   // value. Otherwise, the synchronous flag is unset, queue a task to process
   // promise's reject callbacks with value.
-  RunResolveTask(aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
-                 Rejected, aAsynchronous);
+  RunResolveTask(aValue, Rejected, aAsynchronous);
 }
 
 void
 Promise::RunResolveTask(JS::Handle<JS::Value> aValue,
                         PromiseState aState,
                         PromiseTaskSync aAsynchronous)
 {
   // If the synchronous flag is unset, queue a task to process our
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -15,23 +15,25 @@
 #include "nsWrapperCache.h"
 #include "nsAutoPtr.h"
 #include "nsPIDOMWindow.h"
 #include "js/TypeDecls.h"
 
 namespace mozilla {
 namespace dom {
 
-class PromiseInit;
+class AnyCallback;
 class PromiseCallback;
-class AnyCallback;
+class PromiseInit;
+class PromiseNativeHandler;
 
 class Promise MOZ_FINAL : public nsISupports,
                           public nsWrapperCache
 {
+  friend class NativePromiseCallback;
   friend class PromiseTask;
   friend class PromiseResolverTask;
   friend class ResolvePromiseCallback;
   friend class RejectPromiseCallback;
   friend class WrapperPromiseCallback;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -39,19 +41,19 @@ public:
 
   Promise(nsPIDOMWindow* aWindow);
   ~Promise();
 
   static bool PrefEnabled();
   static bool EnabledForScope(JSContext* aCx, JSObject* /* unused */);
 
   void MaybeResolve(JSContext* aCx,
-                    const Optional<JS::Handle<JS::Value> >& aValue);
+                    JS::Handle<JS::Value> aValue);
   void MaybeReject(JSContext* aCx,
-                   const Optional<JS::Handle<JS::Value> >& aValue);
+                   JS::Handle<JS::Value> aValue);
 
   // WebIDL
 
   nsPIDOMWindow* GetParentObject() const
   {
     return mWindow;
   }
 
@@ -73,16 +75,18 @@ public:
   already_AddRefed<Promise>
   Then(const Optional<OwningNonNull<AnyCallback> >& aResolveCallback,
        const Optional<OwningNonNull<AnyCallback> >& aRejectCallback);
 
 
   already_AddRefed<Promise>
   Catch(const Optional<OwningNonNull<AnyCallback> >& aRejectCallback);
 
+  void AppendNativeHandler(PromiseNativeHandler* aRunnable);
+
 private:
   enum PromiseState {
     Pending,
     Resolved,
     Rejected
   };
 
   enum PromiseTaskSync {
@@ -115,28 +119,28 @@ private:
   void AppendCallbacks(PromiseCallback* aResolveCallback,
                        PromiseCallback* aRejectCallback);
 
   // If we have been rejected and our mResult is a JS exception,
   // report it to the error console.
   void MaybeReportRejected();
 
   void MaybeResolveInternal(JSContext* aCx,
-                            const Optional<JS::Handle<JS::Value> >& aValue,
+                            JS::Handle<JS::Value> aValue,
                             PromiseTaskSync aSync = AsyncTask);
   void MaybeRejectInternal(JSContext* aCx,
-                           const Optional<JS::Handle<JS::Value> >& aValue,
+                           JS::Handle<JS::Value> aValue,
                            PromiseTaskSync aSync = AsyncTask);
 
   void ResolveInternal(JSContext* aCx,
-                       const Optional<JS::Handle<JS::Value> >& aValue,
+                       JS::Handle<JS::Value> aValue,
                        PromiseTaskSync aSync = AsyncTask);
 
   void RejectInternal(JSContext* aCx,
-                      const Optional<JS::Handle<JS::Value> >& aValue,
+                      JS::Handle<JS::Value> aValue,
                       PromiseTaskSync aSync = AsyncTask);
 
   // Static methods for the PromiseInit functions.
   static bool
   JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
   static JSObject*
   CreateFunction(JSContext* aCx, JSObject* aParent, Promise* aPromise,
                 int32_t aTask);
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "PromiseCallback.h"
 #include "mozilla/dom/Promise.h"
+#include "mozilla/dom/PromiseNativeHandler.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
@@ -32,21 +33,21 @@ PromiseCallback::PromiseCallback()
 
 PromiseCallback::~PromiseCallback()
 {
   MOZ_COUNT_DTOR(PromiseCallback);
 }
 
 static void
 EnterCompartment(Maybe<JSAutoCompartment>& aAc, JSContext* aCx,
-                 const Optional<JS::Handle<JS::Value> >& aValue)
+                 JS::Handle<JS::Value> aValue)
 {
   // FIXME Bug 878849
-  if (aValue.WasPassed() && aValue.Value().isObject()) {
-    JS::Rooted<JSObject*> rooted(aCx, &aValue.Value().toObject());
+  if (aValue.isObject()) {
+    JS::Rooted<JSObject*> rooted(aCx, &aValue.toObject());
     aAc.construct(aCx, rooted);
   }
 }
 
 // ResolvePromiseCallback
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ResolvePromiseCallback,
                                      PromiseCallback,
@@ -66,17 +67,17 @@ ResolvePromiseCallback::ResolvePromiseCa
 }
 
 ResolvePromiseCallback::~ResolvePromiseCallback()
 {
   MOZ_COUNT_DTOR(ResolvePromiseCallback);
 }
 
 void
-ResolvePromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
+ResolvePromiseCallback::Call(JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
   AutoJSContext cx;
   Maybe<JSAutoCompartment> ac;
   EnterCompartment(ac, cx, aValue);
 
   mPromise->ResolveInternal(cx, aValue, Promise::SyncTask);
 }
@@ -101,17 +102,17 @@ RejectPromiseCallback::RejectPromiseCall
 }
 
 RejectPromiseCallback::~RejectPromiseCallback()
 {
   MOZ_COUNT_DTOR(RejectPromiseCallback);
 }
 
 void
-RejectPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
+RejectPromiseCallback::Call(JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
   AutoJSContext cx;
   Maybe<JSAutoCompartment> ac;
   EnterCompartment(ac, cx, aValue);
 
   mPromise->RejectInternal(cx, aValue, Promise::SyncTask);
 }
@@ -138,35 +139,35 @@ WrapperPromiseCallback::WrapperPromiseCa
 }
 
 WrapperPromiseCallback::~WrapperPromiseCallback()
 {
   MOZ_COUNT_DTOR(WrapperPromiseCallback);
 }
 
 void
-WrapperPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
+WrapperPromiseCallback::Call(JS::Handle<JS::Value> aValue)
 {
   AutoJSContext cx;
   Maybe<JSAutoCompartment> ac;
   EnterCompartment(ac, cx, aValue);
 
   ErrorResult rv;
 
   // If invoking callback threw an exception, run resolver's reject with the
   // thrown exception as argument and the synchronous flag set.
-  Optional<JS::Handle<JS::Value> > value(cx,
+  JS::Rooted<JS::Value> value(cx,
     mCallback->Call(mNextPromise->GetParentObject(), aValue, rv,
                     CallbackObject::eRethrowExceptions));
 
   rv.WouldReportJSException();
 
   if (rv.Failed() && rv.IsJSException()) {
-    Optional<JS::Handle<JS::Value> > value(cx);
-    rv.StealJSException(cx, &value.Value());
+    JS::Rooted<JS::Value> value(cx);
+    rv.StealJSException(cx, &value);
 
     Maybe<JSAutoCompartment> ac2;
     EnterCompartment(ac2, cx, value);
     mNextPromise->RejectInternal(cx, value, Promise::SyncTask);
     return;
   }
 
   // Otherwise, run resolver's resolve with value and the synchronous flag
@@ -198,22 +199,63 @@ SimpleWrapperPromiseCallback::SimpleWrap
 }
 
 SimpleWrapperPromiseCallback::~SimpleWrapperPromiseCallback()
 {
   MOZ_COUNT_DTOR(SimpleWrapperPromiseCallback);
 }
 
 void
-SimpleWrapperPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
+SimpleWrapperPromiseCallback::Call(JS::Handle<JS::Value> aValue)
 {
   ErrorResult rv;
   mCallback->Call(mPromise, aValue, rv);
 }
 
+// NativePromiseCallback
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(NativePromiseCallback,
+                                     PromiseCallback, mHandler)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
+NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
+
+NS_IMPL_ADDREF_INHERITED(NativePromiseCallback, PromiseCallback)
+NS_IMPL_RELEASE_INHERITED(NativePromiseCallback, PromiseCallback)
+
+NativePromiseCallback::NativePromiseCallback(PromiseNativeHandler* aHandler,
+                                             Promise::PromiseState aState)
+  : mHandler(aHandler)
+  , mState(aState)
+{
+  MOZ_ASSERT(aHandler);
+  MOZ_COUNT_CTOR(NativePromiseCallback);
+}
+
+NativePromiseCallback::~NativePromiseCallback()
+{
+  MOZ_COUNT_DTOR(NativePromiseCallback);
+}
+
+void
+NativePromiseCallback::Call(JS::Handle<JS::Value> aValue)
+{
+  if (mState == Promise::Resolved) {
+    mHandler->ResolvedCallback(aValue);
+    return;
+  }
+
+  if (mState == Promise::Rejected) {
+    mHandler->RejectedCallback(aValue);
+    return;
+  }
+
+  NS_NOTREACHED("huh?");
+}
+
 /* static */ PromiseCallback*
 PromiseCallback::Factory(Promise* aNextPromise, AnyCallback* aCallback,
                          Task aTask)
 {
   MOZ_ASSERT(aNextPromise);
 
   // If we have a callback and a next resolver, we have to exec the callback and
   // then propagate the return value to the next resolver->resolve().
--- a/dom/promise/PromiseCallback.h
+++ b/dom/promise/PromiseCallback.h
@@ -19,17 +19,17 @@ class PromiseCallback : public nsISuppor
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(PromiseCallback)
 
   PromiseCallback();
   virtual ~PromiseCallback();
 
-  virtual void Call(const Optional<JS::Handle<JS::Value> >& aValue) = 0;
+  virtual void Call(JS::Handle<JS::Value> aValue) = 0;
 
   enum Task {
     Resolve,
     Reject
   };
 
   // This factory returns a PromiseCallback object with refcount of 0.
   static PromiseCallback*
@@ -41,17 +41,17 @@ public:
 // aNextPromise->RejectFunction() if the JS Callback throws.
 class WrapperPromiseCallback MOZ_FINAL : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WrapperPromiseCallback,
                                            PromiseCallback)
 
-  void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
+  void Call(JS::Handle<JS::Value> aValue) MOZ_OVERRIDE;
 
   WrapperPromiseCallback(Promise* aNextPromise, AnyCallback* aCallback);
   ~WrapperPromiseCallback();
 
 private:
   nsRefPtr<Promise> mNextPromise;
   nsRefPtr<AnyCallback> mCallback;
 };
@@ -59,17 +59,17 @@ private:
 // SimpleWrapperPromiseCallback execs a JS Callback with a value.
 class SimpleWrapperPromiseCallback MOZ_FINAL : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SimpleWrapperPromiseCallback,
                                            PromiseCallback)
 
-  void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
+  void Call(JS::Handle<JS::Value> aValue) MOZ_OVERRIDE;
 
   SimpleWrapperPromiseCallback(Promise* aPromise,
                                AnyCallback* aCallback);
   ~SimpleWrapperPromiseCallback();
 
 private:
   nsRefPtr<Promise> mPromise;
   nsRefPtr<AnyCallback> mCallback;
@@ -79,17 +79,17 @@ private:
 // received by Call().
 class ResolvePromiseCallback MOZ_FINAL : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ResolvePromiseCallback,
                                            PromiseCallback)
 
-  void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
+  void Call(JS::Handle<JS::Value> aValue) MOZ_OVERRIDE;
 
   ResolvePromiseCallback(Promise* aPromise);
   ~ResolvePromiseCallback();
 
 private:
   nsRefPtr<Promise> mPromise;
 };
 
@@ -97,21 +97,40 @@ private:
 // received by Call().
 class RejectPromiseCallback MOZ_FINAL : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RejectPromiseCallback,
                                            PromiseCallback)
 
-  void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
+  void Call(JS::Handle<JS::Value> aValue) MOZ_OVERRIDE;
 
   RejectPromiseCallback(Promise* aPromise);
   ~RejectPromiseCallback();
 
 private:
   nsRefPtr<Promise> mPromise;
 };
 
+// NativePromiseCallback wraps a NativePromiseHandler.
+class NativePromiseCallback MOZ_FINAL : public PromiseCallback
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback,
+                                           PromiseCallback)
+
+  void Call(JS::Handle<JS::Value> aValue) MOZ_OVERRIDE;
+
+  NativePromiseCallback(PromiseNativeHandler* aHandler,
+                        Promise::PromiseState aState);
+  ~NativePromiseCallback();
+
+private:
+  nsRefPtr<PromiseNativeHandler> mHandler;
+  Promise::PromiseState mState;
+};
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_PromiseCallback_h
new file mode 100644
--- /dev/null
+++ b/dom/promise/PromiseNativeHandler.h
@@ -0,0 +1,39 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef mozilla_dom_PromiseNativeHandler_h
+#define mozilla_dom_PromiseNativeHandler_h
+
+#include "nsISupports.h"
+
+namespace mozilla {
+namespace dom {
+
+/*
+ * PromiseNativeHandler allows C++ to react to a Promise being rejected/resolved.
+ * A PromiseNativeHandler can be appended to a Promise using
+ * Promise::AppendNativeHandler().
+ */
+class PromiseNativeHandler : public nsISupports
+{
+public:
+  // NS_IMPL_ISUPPORTS0 in Promise.cpp.
+  NS_DECL_ISUPPORTS
+
+  virtual ~PromiseNativeHandler()
+  { }
+
+  virtual void
+  ResolvedCallback(JS::Handle<JS::Value> aValue) = 0;
+
+  virtual void
+  RejectedCallback(JS::Handle<JS::Value> aValue) = 0;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PromiseNativeHandler_h
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 TEST_DIRS += ['tests']
 
 XPIDL_MODULE = 'dom_promise'
 
 EXPORTS.mozilla.dom += [
     'Promise.h',
+    'PromiseNativeHandler.h'
 ]
 
 SOURCES += [
     'Promise.cpp',
     'PromiseCallback.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
--- a/dom/push/src/PushService.jsm
+++ b/dom/push/src/PushService.jsm
@@ -18,16 +18,17 @@ const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
+Cu.importGlobalProperties(["indexedDB"]);
 
 XPCOMUtils.defineLazyModuleGetter(this, "AlarmService",
                                   "resource://gre/modules/AlarmService.jsm");
 
 this.EXPORTED_SYMBOLS = ["PushService"];
 
 const prefs = new Preferences("services.push.");
 // Set debug first so that all debugging actually works.
--- a/dom/src/notification/Notification.cpp
+++ b/dom/src/notification/Notification.cpp
@@ -82,18 +82,17 @@ public:
       return NS_ERROR_FAILURE;
     }
     return NS_OK;
   }
 
   NS_IMETHOD Done(JSContext* aCx)
   {
     JSAutoCompartment ac(aCx, mGlobal);
-    Optional<JS::Handle<JS::Value>> result(aCx,
-                                           JS::ObjectValue(*mNotifications));
+    JS::Rooted<JS::Value> result(aCx, JS::ObjectValue(*mNotifications));
     mPromise->MaybeResolve(aCx, result);
     return NS_OK;
   }
 
 private:
   ~NotificationStorageCallback()
   {
     DropData();
--- a/dom/webidl/Promise.webidl
+++ b/dom/webidl/Promise.webidl
@@ -6,17 +6,17 @@
  * The origin of this IDL file is
  * http://dom.spec.whatwg.org/#promises
  */
 
 // TODO We use object instead Function.  There is an open issue on WebIDL to
 // have different types for "platform-provided function" and "user-provided
 // function"; for now, we just use "object".
 callback PromiseInit = void (object resolve, object reject);
-callback AnyCallback = any (optional any value);
+callback AnyCallback = any (any value);
 
 [Func="mozilla::dom::Promise::EnabledForScope", Constructor(PromiseInit init)]
 interface Promise {
   // TODO bug 875289 - static Promise fulfill(any value);
 
   // Disable the static methods when the interface object is supposed to be
   // disabled, just in case some code decides to walk over to .constructor from
   // the proto of a promise object or someone screws up and manages to create a
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -30,17 +30,17 @@
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ErrorEventBinding.h"
 #include "mozilla/dom/EventTargetBinding.h"
 #include "mozilla/dom/MessageEventBinding.h"
 #include "mozilla/dom/WorkerBinding.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Util.h"
-#include <Navigator.h>
+#include "mozilla/dom/Navigator.h"
 #include "nsContentUtils.h"
 #include "nsCycleCollector.h"
 #include "nsDOMJSUtils.h"
 #include "nsLayoutStatics.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsTraceRefcnt.h"
@@ -800,16 +800,18 @@ CreateJSContextForWorker(WorkerPrivate* 
   for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
     const JSSettings::JSGCSetting& setting = gcSettings[index];
     if (setting.IsSet()) {
       NS_ASSERTION(setting.value, "Can't handle 0 values!");
       JS_SetGCParameter(aRuntime, setting.key, setting.value);
     }
   }
 
+  JS_SetIsWorkerRuntime(aRuntime);
+
   JS_SetNativeStackQuota(aRuntime, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
 
   // Security policy:
   static JSSecurityCallbacks securityCallbacks = {
     nullptr,
     ContentSecurityPolicyAllows
   };
   JS_SetSecurityCallbacks(aRuntime, &securityCallbacks);
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -44,16 +44,20 @@ In this order:
     Fixes TCompiler::Init to treat `resources.ArrayIndexClampingStrategy`
     as a request for the default strategy.
 
   angle-tex-pool-default.patch:
     Don't use D3DPOOL_MANAGED on D3D9. Just use D3DPOOL_DEFAULT.
 
   angle-build-unified.patch:
     Fixes required to make angle compile in unified mode
+    Note that a different version of this patch was upstreamed, so the next time that
+    Angle is updated this patch can be discarded.  See:
+    https://chromium.googlesource.com/angle/angle/+/0dd3b3ff66cdc50882125d21e60112d5161279b4
+    https://chromium.googlesource.com/angle/angle/+/0685fbde65a3e90d8d4d4a6c72f2cc1771617fd0
 
 In addition to these patches, the Makefile.in and moz.build build files are ours,
 they're not present in upsteam ANGLE. Therefore, changes made to the build files
 should not be stored in the local .patch files.
 
 
 == How to do a clean-slate upgrade ==
 1.  Backup our moz-specific files:
--- a/gfx/cairo/cairo/src/moz.build
+++ b/gfx/cairo/cairo/src/moz.build
@@ -109,24 +109,28 @@ if CONFIG['MOZ_ENABLE_CAIRO_FT']:
         'cairo-ft.h',
     ]
     SOURCES += [
         'cairo-ft-font.c',
         'cairo-type1-subset.c',
     ]
 
 SOURCES += [
+    'cairo-bentley-ottmann-rectangular.c', # redefinition of '_cairo_bo_trap'
+    'cairo-bentley-ottmann-rectilinear.c', # redefinition of '_cairo_bo_trap'
+    'cairo-bentley-ottmann.c', # redefinition of '_cairo_bo_trap'
+    'cairo-surface-wrapper.c', #  redefinition of '_copy_transformed_pattern'
+]
+
+UNIFIED_SOURCES += [
     'cairo-analysis-surface.c',
     'cairo-arc.c',
     'cairo-array.c',
     'cairo-atomic.c',
     'cairo-base64-stream.c',
-    'cairo-bentley-ottmann-rectangular.c',
-    'cairo-bentley-ottmann-rectilinear.c',
-    'cairo-bentley-ottmann.c',
     'cairo-botor-scan-converter.c',
     'cairo-boxes.c',
     'cairo-cache.c',
     'cairo-clip.c',
     'cairo-color.c',
     'cairo-composite-rectangles.c',
     'cairo-debug.c',
     'cairo-device.c',
@@ -168,17 +172,16 @@ SOURCES += [
     'cairo-spans.c',
     'cairo-spline.c',
     'cairo-stroke-style.c',
     'cairo-surface-clipper.c',
     'cairo-surface-fallback.c',
     'cairo-surface-offset.c',
     'cairo-surface-snapshot.c',
     'cairo-surface-subsurface.c',
-    'cairo-surface-wrapper.c',
     'cairo-surface.c',
     'cairo-tee-surface.c',
     'cairo-tor-scan-converter.c',
     'cairo-toy-font-face.c',
     'cairo-traps.c',
     'cairo-unicode.c',
     'cairo-user-font.c',
     'cairo-version.c',
--- a/gfx/harfbuzz/src/moz.build
+++ b/gfx/harfbuzz/src/moz.build
@@ -18,34 +18,37 @@ EXPORTS.harfbuzz += [
     'hb-shape-plan.h',
     'hb-shape.h',
     'hb-unicode.h',
     'hb-version.h',
     'hb.h',
 ]
 
 SOURCES += [
+    'hb-common.cc', # error: use of undeclared identifier 'strdup'
+    'hb-ot-shape-complex-indic.cc', # error: redefinition of enumerator 'INIT'
+    'hb-ot-shape-complex-sea.cc', # error: redefinition of 'basic_features'
+    'hb-ot-shape.cc', # error: functions that differ only in their return type cannot be overloaded
+]
+
+UNIFIED_SOURCES += [
     'hb-blob.cc',
     'hb-buffer.cc',
-    'hb-common.cc',
     'hb-face.cc',
     'hb-fallback-shape.cc',
     'hb-font.cc',
     'hb-ot-layout.cc',
     'hb-ot-map.cc',
     'hb-ot-shape-complex-arabic.cc',
     'hb-ot-shape-complex-default.cc',
     'hb-ot-shape-complex-indic-table.cc',
-    'hb-ot-shape-complex-indic.cc',
     'hb-ot-shape-complex-myanmar.cc',
-    'hb-ot-shape-complex-sea.cc',
     'hb-ot-shape-complex-thai.cc',
     'hb-ot-shape-fallback.cc',
     'hb-ot-shape-normalize.cc',
-    'hb-ot-shape.cc',
     'hb-ot-tag.cc',
     'hb-set.cc',
     'hb-shape-plan.cc',
     'hb-shape.cc',
     'hb-shaper.cc',
     'hb-unicode.cc',
     'hb-warning.cc',
 ]
--- a/gfx/layers/ThebesLayerBuffer.h
+++ b/gfx/layers/ThebesLayerBuffer.h
@@ -57,26 +57,30 @@ public:
 
   RotatedBuffer(gfxASurface* aBuffer, gfxASurface* aBufferOnWhite,
                 const nsIntRect& aBufferRect,
                 const nsIntPoint& aBufferRotation)
     : mBuffer(aBuffer)
     , mBufferOnWhite(aBufferOnWhite)
     , mBufferRect(aBufferRect)
     , mBufferRotation(aBufferRotation)
+    , mDidSelfCopy(false)
   { }
   RotatedBuffer(gfx::DrawTarget* aDTBuffer, gfx::DrawTarget* aDTBufferOnWhite,
                 const nsIntRect& aBufferRect,
                 const nsIntPoint& aBufferRotation)
     : mDTBuffer(aDTBuffer)
     , mDTBufferOnWhite(aDTBufferOnWhite)
     , mBufferRect(aBufferRect)
     , mBufferRotation(aBufferRotation)
+    , mDidSelfCopy(false)
   { }
-  RotatedBuffer() { }
+  RotatedBuffer()
+    : mDidSelfCopy(false)
+  { }
 
   /*
    * Which buffer should be drawn to/read from.
    */
   enum ContextSource {
     BUFFER_BLACK, // The normal buffer, or buffer with black background when using component alpha.
     BUFFER_WHITE, // The buffer with white background, only valid with component alpha.
     BUFFER_BOTH // The combined black/white buffers, only valid for writing operations, not reading.
--- a/hal/linux/udev.h
+++ b/hal/linux/udev.h
@@ -25,23 +25,37 @@ struct udev_monitor;
 class udev_lib {
  public:
   udev_lib() : lib(nullptr),
                udev(nullptr) {
     // Be careful about ABI compat! 0 -> 1 didn't change any
     // symbols this code relies on, per:
     // https://lists.fedoraproject.org/pipermail/devel/2012-June/168227.html
     const char* lib_names[] = {"libudev.so.0", "libudev.so.1"};
+    // Check whether a library is already loaded so we don't load two
+    // conflicting libs.
     for (unsigned i = 0; i < ArrayLength(lib_names); i++) {
-      lib = dlopen(lib_names[i], RTLD_LAZY | RTLD_GLOBAL);
-      if (lib)
+      lib = dlopen(lib_names[i], RTLD_NOLOAD | RTLD_LAZY | RTLD_GLOBAL);
+      if (lib) {
         break;
+      }
     }
-    if (lib && LoadSymbols())
+    // If nothing loads the first time through, it means no version of libudev
+    // was already loaded.
+    if (!lib) {
+      for (unsigned i = 0; i < ArrayLength(lib_names); i++) {
+        lib = dlopen(lib_names[i], RTLD_LAZY | RTLD_GLOBAL);
+        if (lib) {
+          break;
+        }
+      }
+    }
+    if (lib && LoadSymbols()) {
       udev = udev_new();
+    }
   }
 
   ~udev_lib() {
     if (udev) {
       udev_unref(udev);
     }
 
     if (lib) {
--- a/ipc/chromium/src/third_party/libevent/README.mozilla
+++ b/ipc/chromium/src/third_party/libevent/README.mozilla
@@ -7,8 +7,9 @@ mac/event2/event-config.h
 android/event2/event-config.h
 
 These files are taken from libevent-2.0.21-stable built on the development environment indicated by the first path component. You have to run "./configure" and "make" to get all of the pre-processing done. The file can then be found in "include/event2/".
 
 2. This is ugly, prepare yourself. OS X has a weird problem with how the "TAILQ_END(head)" is used, causing a linking error. Just replace all use of the "TAILQ_END(head)" macro with "NULL".
 
 3. Apply "add mac-arc4random-buf.patch", which removes some bad OS X compatibility code. This will allow libevent to compile on all supported versions of OS X.
 
+4. Apply "openbsd-no-arc4random_addrandom.patch", which fixes the build on OpenBSD (which doesnt provide arc4random_addrandom anymore, see #931354)
--- a/ipc/chromium/src/third_party/libevent/evutil_rand.c
+++ b/ipc/chromium/src/third_party/libevent/evutil_rand.c
@@ -134,15 +134,16 @@ ev_arc4random_buf(void *buf, size_t n)
 #endif /* } !_EVENT_HAVE_ARC4RANDOM */
 
 void
 evutil_secure_rng_get_bytes(void *buf, size_t n)
 {
 	ev_arc4random_buf(buf, n);
 }
 
+#ifndef __OpenBSD__
 void
 evutil_secure_rng_add_bytes(const char *buf, size_t n)
 {
 	arc4random_addrandom((unsigned char*)buf,
 	    n>(size_t)INT_MAX ? INT_MAX : (int)n);
 }
-
+#endif
--- a/ipc/chromium/src/third_party/libevent/include/event2/util.h
+++ b/ipc/chromium/src/third_party/libevent/include/event2/util.h
@@ -667,29 +667,31 @@ void evutil_secure_rng_get_bytes(void *b
  * numbers.  You only need to call it if (a) you want to double-check
  * that one of the seeding methods did succeed, or (b) you plan to drop
  * the capability to seed (by chrooting, or dropping capabilities, or
  * whatever), and you want to make sure that seeding happens before your
  * program loses the ability to do it.
  */
 int evutil_secure_rng_init(void);
 
+#ifndef __OpenBSD__
 /** Seed the random number generator with extra random bytes.
 
     You should almost never need to call this function; it should be
     sufficient to invoke evutil_secure_rng_init(), or let Libevent take
     care of calling evutil_secure_rng_init() on its own.
 
     If you call this function as a _replacement_ for the regular
     entropy sources, then you need to be sure that your input
     contains a fairly large amount of strong entropy.  Doing so is
     notoriously hard: most people who try get it wrong.  Watch out!
 
     @param dat a buffer full of a strong source of random numbers
     @param datlen the number of bytes to read from datlen
  */
 void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
+#endif
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif /* _EVUTIL_H_ */
new file mode 100644
--- /dev/null
+++ b/ipc/chromium/src/third_party/libevent/openbsd-no-arc4random_addrandom.patch
@@ -0,0 +1,64 @@
+# HG changeset patch
+# User Landry Breuil <landry@openbsd.org>
+# Date 1384377262 -3600
+#      Wed Nov 13 22:14:22 2013 +0100
+# Node ID 026009b2c94dc564413d48df824fabec98e2c631
+# Parent  f2b602a5ee27b2e05abe84ea7cbd358dadd2ffb5
+Bug 931354: OpenBSD doesn't provide arc4random_addrandom anymore, fix libevent accordingly by #ifndef'ing out its caller evutil_secure_rng_add_bytes() (which isnt called anywhere) r=joshaas
+
+diff --git a/ipc/chromium/src/third_party/libevent/evutil_rand.c b/ipc/chromium/src/third_party/libevent/evutil_rand.c
+--- a/ipc/chromium/src/third_party/libevent/evutil_rand.c
++++ b/ipc/chromium/src/third_party/libevent/evutil_rand.c
+@@ -134,15 +134,16 @@ ev_arc4random_buf(void *buf, size_t n)
+ #endif /* } !_EVENT_HAVE_ARC4RANDOM */
+ 
+ void
+ evutil_secure_rng_get_bytes(void *buf, size_t n)
+ {
+ 	ev_arc4random_buf(buf, n);
+ }
+ 
++#ifndef __OpenBSD__
+ void
+ evutil_secure_rng_add_bytes(const char *buf, size_t n)
+ {
+ 	arc4random_addrandom((unsigned char*)buf,
+ 	    n>(size_t)INT_MAX ? INT_MAX : (int)n);
+ }
+-
++#endif
+diff --git a/ipc/chromium/src/third_party/libevent/include/event2/util.h b/ipc/chromium/src/third_party/libevent/include/event2/util.h
+--- a/ipc/chromium/src/third_party/libevent/include/event2/util.h
++++ b/ipc/chromium/src/third_party/libevent/include/event2/util.h
+@@ -667,29 +667,31 @@ void evutil_secure_rng_get_bytes(void *b
+  * numbers.  You only need to call it if (a) you want to double-check
+  * that one of the seeding methods did succeed, or (b) you plan to drop
+  * the capability to seed (by chrooting, or dropping capabilities, or
+  * whatever), and you want to make sure that seeding happens before your
+  * program loses the ability to do it.
+  */
+ int evutil_secure_rng_init(void);
+ 
++#ifndef __OpenBSD__
+ /** Seed the random number generator with extra random bytes.
+ 
+     You should almost never need to call this function; it should be
+     sufficient to invoke evutil_secure_rng_init(), or let Libevent take
+     care of calling evutil_secure_rng_init() on its own.
+ 
+     If you call this function as a _replacement_ for the regular
+     entropy sources, then you need to be sure that your input
+     contains a fairly large amount of strong entropy.  Doing so is
+     notoriously hard: most people who try get it wrong.  Watch out!
+ 
+     @param dat a buffer full of a strong source of random numbers
+     @param datlen the number of bytes to read from datlen
+  */
+ void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
++#endif
+ 
+ #ifdef __cplusplus
+ }
+ #endif
+ 
+ #endif /* _EVUTIL_H_ */
--- a/ipc/ipdl/ipdl/parser.py
+++ b/ipc/ipdl/ipdl/parser.py
@@ -214,17 +214,16 @@ def p_TranslationUnit(p):
 
     # The "canonical" namespace of the tu, what it's considered to be
     # in for the purposes of C++: |#include "foo/bar/TU.h"|
     if tu.protocol:
         assert tu.filetype == 'protocol'
         tu.namespaces = tu.protocol.namespaces
         tu.name = tu.protocol.name
     else:
-        print tu.filetype
         assert tu.filetype == 'header'
         # There's not really a canonical "thing" in headers.  So
         # somewhat arbitrarily use the namespace of the last
         # interesting thing that was declared.
         for thing in reversed(tu.structsAndUnions):
             tu.namespaces = thing.namespaces
             break
 
--- a/js/public/HashTable.h
+++ b/js/public/HashTable.h
@@ -132,30 +132,31 @@ class HashMap
     //    assert(p->key == 3);
     //    char val = p->value;
     typedef typename Impl::AddPtr AddPtr;
     AddPtr lookupForAdd(const Lookup &l) const {
         return impl.lookupForAdd(l);
     }
 
     template<typename KeyInput, typename ValueInput>
-    bool add(AddPtr &p, const KeyInput &k, const ValueInput &v) {
-        Entry e(k, v);
-        return impl.add(p, mozilla::OldMove(e));
+    bool add(AddPtr &p, KeyInput &&k, ValueInput &&v) {
+        Entry e(mozilla::Forward<KeyInput>(k), mozilla::Forward<ValueInput>(v));
+        return impl.add(p, mozilla::Move(e));
     }
 
-    bool add(AddPtr &p, const Key &k) {
-        Entry e(k, Value());
-        return impl.add(p, mozilla::OldMove(e));
+    template<typename KeyInput>
+    bool add(AddPtr &p, KeyInput &&k) {