Merge mozilla-central to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 23 Oct 2013 15:03:32 +0200
changeset 165613 d91823b449d10871c3504247adf4b99907f4ac3e
parent 165612 ff5a19df4bed1bbb2c515de7d0bd388dcdb4b623 (current diff)
parent 165602 8803e8c0ee3efe4c0c07be612ce51c1d274b7c96 (diff)
child 165614 2d8cdd7baa58bfab0b5cd805e555f4bdb26a4c9b
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.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 mozilla-central to fx-team
accessible/src/base/RoleAsserts.cpp
--- a/CLOBBER
+++ b/CLOBBER
@@ -13,9 +13,9 @@
 #          |               |
 #          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/
 #
 
-Bug 926091 says hello to bug 924992 by touching webidl
+Bug 918207 needed a clobber on every platform because we can't have nice things
--- a/accessible/src/atk/AccessibleWrap.cpp
+++ b/accessible/src/atk/AccessibleWrap.cpp
@@ -866,66 +866,58 @@ refStateSetCB(AtkObject *aAtkObj)
     }
 
     // Map states
     TranslateStates(accWrap->State(), state_set);
 
     return state_set;
 }
 
+static void
+UpdateAtkRelation(RelationType aType, Accessible* aAcc,
+                  AtkRelationType aAtkType, AtkRelationSet* aAtkSet)
+{
+  if (aAtkType == ATK_RELATION_NULL)
+    return;
+
+  AtkRelation* atkRelation =
+    atk_relation_set_get_relation_by_type(aAtkSet, aAtkType);
+  if (atkRelation)
+    atk_relation_set_remove(aAtkSet, atkRelation);
+
+  Relation rel(aAcc->RelationByType(aType));
+  nsTArray<AtkObject*> targets;
+  Accessible* tempAcc = nullptr;
+  while ((tempAcc = rel.Next()))
+    targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc));
+
+  if (targets.Length()) {
+    atkRelation = atk_relation_new(targets.Elements(),
+                                   targets.Length(), aAtkType);
+    atk_relation_set_add(aAtkSet, atkRelation);
+    g_object_unref(atkRelation);
+  }
+}
+
 AtkRelationSet *
 refRelationSetCB(AtkObject *aAtkObj)
 {
   AtkRelationSet* relation_set =
     ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
 
   AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
   if (!accWrap)
     return relation_set;
 
-  // Keep in sync with AtkRelationType enum.
-  static const RelationType relationTypes[] = {
-    RelationType::CONTROLLED_BY,
-    RelationType::CONTROLLER_FOR,
-    RelationType::LABEL_FOR,
-    RelationType::LABELLED_BY,
-    RelationType::MEMBER_OF,
-    RelationType::NODE_CHILD_OF,
-    RelationType::FLOWS_TO,
-    RelationType::FLOWS_FROM,
-    RelationType::SUBWINDOW_OF,
-    RelationType::EMBEDS,
-    RelationType::EMBEDDED_BY,
-    RelationType::POPUP_FOR,
-    RelationType::PARENT_WINDOW_OF,
-    RelationType::DESCRIBED_BY,
-    RelationType::DESCRIPTION_FOR,
-    RelationType::NODE_PARENT_OF
-  };
+#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
+  UpdateAtkRelation(RelationType::geckoType, accWrap, atkType, relation_set);
 
-  for (uint32_t i = 0; i < ArrayLength(relationTypes); i++) {
-    // Shift to 1 to skip ATK_RELATION_NULL.
-    AtkRelationType atkType = static_cast<AtkRelationType>(i + 1);
-    AtkRelation* atkRelation =
-      atk_relation_set_get_relation_by_type(relation_set, atkType);
-    if (atkRelation)
-      atk_relation_set_remove(relation_set, atkRelation);
+#include "RelationTypeMap.h"
 
-    Relation rel(accWrap->RelationByType(relationTypes[i]));
-    nsTArray<AtkObject*> targets;
-    Accessible* tempAcc = nullptr;
-    while ((tempAcc = rel.Next()))
-      targets.AppendElement(AccessibleWrap::GetAtkObject(tempAcc));
-
-    if (targets.Length()) {
-      atkRelation = atk_relation_new(targets.Elements(), targets.Length(), atkType);
-      atk_relation_set_add(relation_set, atkRelation);
-      g_object_unref(atkRelation);
-    }
-  }
+#undef RELATIONTYPE
 
   return relation_set;
 }
 
 // Check if aAtkObj is a valid MaiAtkObject, and return the AccessibleWrap
 // for it.
 AccessibleWrap*
 GetAccessibleWrap(AtkObject* aAtkObj)
rename from accessible/src/base/RoleAsserts.cpp
rename to accessible/src/base/Asserts.cpp
--- a/accessible/src/base/RoleAsserts.cpp
+++ b/accessible/src/base/Asserts.cpp
@@ -1,17 +1,26 @@
 /* -*- 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 "nsIAccessibleRelation.h"
 #include "nsIAccessibleRole.h"
+#include "RelationType.h"
 #include "Role.h"
 
 using namespace mozilla::a11y;
 
 #define ROLE(geckoRole, stringRole, atkRole, macRole, msaaRole, ia2Role, nameRule) \
   static_assert(static_cast<uint32_t>(roles::geckoRole) \
                 == static_cast<uint32_t>(nsIAccessibleRole::ROLE_ ## geckoRole), \
                 "internal and xpcom roles differ!");
 #include "RoleMap.h"
 #undef ROLE
+
+#define RELATIONTYPE(geckoType, stringType, atkType, msaaType, ia2Type) \
+  static_assert(static_cast<uint32_t>(RelationType::geckoType) \
+                == static_cast<uint32_t>(nsIAccessibleRelation::RELATION_ ## geckoType), \
+                "internal and xpcom relations differ!");
+#include "RelationTypeMap.h"
+#undef RELATIONTYPE
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/RelationTypeMap.h
@@ -0,0 +1,112 @@
+/* -*- 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/. */
+
+/**
+ * Usage: declare the macro RELATIONTYPE()with the following arguments:
+ * RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type)
+ */
+
+RELATIONTYPE(LABELLED_BY,
+             "labelled by",
+             ATK_RELATION_LABELLED_BY,
+             NAVRELATION_LABELLED_BY,
+             IA2_RELATION_LABELLED_BY)
+
+RELATIONTYPE(LABEL_FOR,
+             "label for",
+             ATK_RELATION_LABEL_FOR,
+             NAVRELATION_LABEL_FOR,
+             IA2_RELATION_LABEL_FOR)
+
+RELATIONTYPE(DESCRIBED_BY,
+             "described by",
+             ATK_RELATION_DESCRIBED_BY,
+             NAVRELATION_DESCRIBED_BY,
+             IA2_RELATION_DESCRIBED_BY)
+
+RELATIONTYPE(DESCRIPTION_FOR,
+             "description for",
+             ATK_RELATION_DESCRIPTION_FOR,
+             NAVRELATION_DESCRIPTION_FOR,
+             IA2_RELATION_DESCRIPTION_FOR)
+
+RELATIONTYPE(NODE_CHILD_OF,
+             "node child of",
+             ATK_RELATION_NODE_CHILD_OF,
+             NAVRELATION_NODE_CHILD_OF,
+             IA2_RELATION_NODE_CHILD_OF)
+
+RELATIONTYPE(NODE_PARENT_OF,
+             "node parent of",
+             ATK_RELATION_NODE_PARENT_OF,
+             NAVRELATION_NODE_PARENT_OF,
+             IA2_RELATION_NODE_PARENT_OF)
+
+RELATIONTYPE(CONTROLLED_BY,
+             "controlled by",
+             ATK_RELATION_CONTROLLED_BY,
+             NAVRELATION_CONTROLLED_BY,
+             IA2_RELATION_CONTROLLED_BY)
+
+RELATIONTYPE(CONTROLLER_FOR,
+             "controller for",
+             ATK_RELATION_CONTROLLER_FOR,
+             NAVRELATION_CONTROLLER_FOR,
+             IA2_RELATION_CONTROLLER_FOR)
+
+RELATIONTYPE(FLOWS_TO,
+             "flows to",
+             ATK_RELATION_FLOWS_TO,
+             NAVRELATION_FLOWS_TO,
+             IA2_RELATION_FLOWS_TO)
+
+RELATIONTYPE(FLOWS_FROM,
+             "flows from",
+             ATK_RELATION_FLOWS_FROM,
+             NAVRELATION_FLOWS_FROM,
+             IA2_RELATION_FLOWS_FROM)
+
+RELATIONTYPE(MEMBER_OF,
+             "member of",
+             ATK_RELATION_MEMBER_OF,
+             NAVRELATION_MEMBER_OF,
+             IA2_RELATION_MEMBER_OF)
+
+RELATIONTYPE(SUBWINDOW_OF,
+             "subwindow of",
+             ATK_RELATION_SUBWINDOW_OF,
+             NAVRELATION_SUBWINDOW_OF,
+             IA2_RELATION_SUBWINDOW_OF)
+
+RELATIONTYPE(EMBEDS,
+             "embeds",
+             ATK_RELATION_EMBEDS,
+             NAVRELATION_EMBEDS,
+             IA2_RELATION_EMBEDS)
+
+RELATIONTYPE(EMBEDDED_BY,
+             "embedded by",
+             ATK_RELATION_EMBEDDED_BY,
+             NAVRELATION_EMBEDDED_BY,
+             IA2_RELATION_EMBEDDED_BY)
+
+RELATIONTYPE(POPUP_FOR,
+             "popup for",
+             ATK_RELATION_POPUP_FOR,
+             NAVRELATION_POPUP_FOR,
+             IA2_RELATION_POPUP_FOR)
+
+RELATIONTYPE(PARENT_WINDOW_OF,
+             "parent window of",
+             ATK_RELATION_PARENT_WINDOW_OF,
+             NAVRELATION_PARENT_WINDOW_OF,
+             IA2_RELATION_PARENT_WINDOW_OF)
+
+RELATIONTYPE(DEFAULT_BUTTON,
+             "default button",
+             ATK_RELATION_NULL,
+             NAVRELATION_DEFAULT_BUTTON,
+             IA2_RELATION_NULL)
--- a/accessible/src/base/moz.build
+++ b/accessible/src/base/moz.build
@@ -32,29 +32,29 @@ if CONFIG['MOZ_DEBUG']:
 
 CPP_SOURCES += [
     'AccCollector.cpp',
     'AccEvent.cpp',
     'AccGroupInfo.cpp',
     'AccIterator.cpp',
     'ARIAMap.cpp',
     'ARIAStateMap.cpp',
+    'Asserts.cpp',
     'DocManager.cpp',
     'EventQueue.cpp',
     'Filters.cpp',
     'FocusManager.cpp',
     'NotificationController.cpp',
     'nsAccessibilityService.cpp',
     'nsAccessiblePivot.cpp',
     'nsAccessNode.cpp',
     'nsAccUtils.cpp',
     'nsCoreUtils.cpp',
     'nsEventShell.cpp',
     'nsTextEquivUtils.cpp',
-    'RoleAsserts.cpp',
     'SelectionManager.cpp',
     'StyleInfo.cpp',
     'TextAttrs.cpp',
     'TextUpdater.cpp',
     'TreeWalker.cpp',
 ]
 
 if a11y_log:
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -708,23 +708,32 @@ nsAccessibilityService::GetStringEventTy
   return NS_OK;
 }
 
 // nsIAccessibleRetrieval::getStringRelationType()
 NS_IMETHODIMP
 nsAccessibilityService::GetStringRelationType(uint32_t aRelationType,
                                               nsAString& aString)
 {
-  if (aRelationType >= ArrayLength(kRelationTypeNames)) {
-    aString.AssignLiteral("unknown");
+  NS_ENSURE_ARG(aRelationType <= static_cast<uint32_t>(RelationType::LAST));
+
+#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
+  case RelationType::geckoType: \
+    aString.AssignLiteral(geckoTypeName); \
     return NS_OK;
+
+  RelationType relationType = static_cast<RelationType>(aRelationType);
+  switch (relationType) {
+#include "RelationTypeMap.h"
+    default:
+      aString.AssignLiteral("unknown");
+      return NS_OK;
   }
 
-  CopyUTF8toUTF16(kRelationTypeNames[aRelationType], aString);
-  return NS_OK;
+#undef RELATIONTYPE
 }
 
 NS_IMETHODIMP
 nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
                                                nsIAccessible** aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
   *aAccessible = nullptr;
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -327,34 +327,10 @@ static const char kEventTypeNames[][40] 
   "hypertext link selected",                 // EVENT_HYPERTEXT_LINK_SELECTED
   "hyperlink start index changed",           // EVENT_HYPERLINK_START_INDEX_CHANGED
   "hypertext changed",                       // EVENT_HYPERTEXT_CHANGED
   "hypertext links count changed",           // EVENT_HYPERTEXT_NLINKS_CHANGED
   "object attribute changed",                // EVENT_OBJECT_ATTRIBUTE_CHANGED
   "virtual cursor changed"                   // EVENT_VIRTUALCURSOR_CHANGED
 };
 
-/**
- * Map nsIAccessibleRelation constants to strings. Used by
- * nsIAccessibleRetrieval::getStringRelationType() method.
- */
-static const char kRelationTypeNames[][20] = {
-  "labelled by",         // RELATION_LABELLED_BY
-  "label for",           // RELATION_LABEL_FOR
-  "described by",        // RELATION_DESCRIBED_BY
-  "description for",     // RELATION_DESCRIPTION_FOR
-  "node child of",       // RELATION_NODE_CHILD_OF
-  "node parent of",      // RELATION_NODE_PARENT_OF
-  "controlled by",       // RELATION_CONTROLLED_BY
-  "controller for",      // RELATION_CONTROLLER_FOR
-  "flows to",            // RELATION_FLOWS_TO
-  "flows from",          // RELATION_FLOWS_FROM
-  "member of",           // RELATION_MEMBER_OF
-  "subwindow of",        // RELATION_SUBWINDOW_OF
-  "embeds",              // RELATION_EMBEDS
-  "embedded by",         // RELATION_EMBEDDED_BY
-  "popup for",           // RELATION_POPUP_FOR
-  "parent window of",    // RELATION_PARENT_WINDOW_OF
-  "default button"       // RELATION_DEFAULT_BUTTON
-};
-
 #endif /* __nsIAccessibilityService_h__ */
 
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -25,16 +25,17 @@
 #include "TableAccessible.h"
 #include "TableCellAccessible.h"
 #include "TreeWalker.h"
 
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMNodeFilter.h"
 #include "nsIDOMHTMLElement.h"
+#include "nsIDOMKeyEvent.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULLabelElement.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsPIDOMWindow.h"
--- a/accessible/src/windows/ia2/ia2Accessible.cpp
+++ b/accessible/src/windows/ia2/ia2Accessible.cpp
@@ -55,18 +55,21 @@ ia2Accessible::get_nRelations(long* aNRe
   if (!aNRelations)
     return E_INVALIDARG;
   *aNRelations = 0;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
-    Relation rel = acc->RelationByType(sRelationTypesForIA2[idx]);
+  for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
+    if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
+      continue;
+
+    Relation rel = acc->RelationByType(sRelationTypePairs[idx].first);
     if (rel.Next())
       (*aNRelations)++;
   }
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
@@ -80,18 +83,21 @@ ia2Accessible::get_relation(long aRelati
     return E_INVALIDARG;
   *aRelation = nullptr;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   long relIdx = 0;
-  for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2); idx++) {
-    RelationType relationType = sRelationTypesForIA2[idx];
+  for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs); idx++) {
+    if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
+      continue;
+
+    RelationType relationType = sRelationTypePairs[idx].first;
     Relation rel = acc->RelationByType(relationType);
     nsRefPtr<ia2AccessibleRelation> ia2Relation =
       new ia2AccessibleRelation(relationType, &rel);
     if (ia2Relation->HasTargets()) {
       if (relIdx == aRelationIndex) {
         ia2Relation.forget(aRelation);
         return S_OK;
       }
@@ -115,19 +121,22 @@ ia2Accessible::get_relations(long aMaxRe
   if (!aRelation || !aNRelations)
     return E_INVALIDARG;
   *aNRelations = 0;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
-  for (unsigned int idx = 0; idx < ArrayLength(sRelationTypesForIA2) &&
+  for (uint32_t idx = 0; idx < ArrayLength(sRelationTypePairs) &&
        *aNRelations < aMaxRelations; idx++) {
-    RelationType relationType = sRelationTypesForIA2[idx];
+    if (sRelationTypePairs[idx].second == IA2_RELATION_NULL)
+      continue;
+
+    RelationType relationType = sRelationTypePairs[idx].first;
     Relation rel = acc->RelationByType(relationType);
     nsRefPtr<ia2AccessibleRelation> ia2Rel =
       new ia2AccessibleRelation(relationType, &rel);
     if (ia2Rel->HasTargets()) {
       ia2Rel.forget(aRelation + (*aNRelations));
       (*aNRelations)++;
     }
   }
--- a/accessible/src/windows/ia2/ia2AccessibleRelation.cpp
+++ b/accessible/src/windows/ia2/ia2AccessibleRelation.cpp
@@ -28,74 +28,32 @@ ia2AccessibleRelation::ia2AccessibleRela
 IMPL_IUNKNOWN_QUERY_HEAD(ia2AccessibleRelation)
   IMPL_IUNKNOWN_QUERY_IFACE(IAccessibleRelation)
   IMPL_IUNKNOWN_QUERY_IFACE(IUnknown)
 IMPL_IUNKNOWN_QUERY_TAIL
 
 // IAccessibleRelation
 
 STDMETHODIMP
-ia2AccessibleRelation::get_relationType(BSTR *aRelationType)
+ia2AccessibleRelation::get_relationType(BSTR* aRelationType)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aRelationType)
     return E_INVALIDARG;
 
   *aRelationType = nullptr;
 
+#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
+  case RelationType::geckoType: \
+    *aRelationType = ::SysAllocString(ia2Type); \
+    break;
+
   switch (mType) {
-    case RelationType::CONTROLLED_BY:
-      *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLED_BY);
-      break;
-    case RelationType::CONTROLLER_FOR:
-      *aRelationType = ::SysAllocString(IA2_RELATION_CONTROLLER_FOR);
-      break;
-    case RelationType::DESCRIBED_BY:
-      *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIBED_BY);
-      break;
-    case RelationType::DESCRIPTION_FOR:
-      *aRelationType = ::SysAllocString(IA2_RELATION_DESCRIPTION_FOR);
-      break;
-    case RelationType::EMBEDDED_BY:
-      *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDDED_BY);
-      break;
-    case RelationType::EMBEDS:
-      *aRelationType = ::SysAllocString(IA2_RELATION_EMBEDS);
-      break;
-    case RelationType::FLOWS_FROM:
-      *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_FROM);
-      break;
-    case RelationType::FLOWS_TO:
-      *aRelationType = ::SysAllocString(IA2_RELATION_FLOWS_TO);
-      break;
-    case RelationType::LABEL_FOR:
-      *aRelationType = ::SysAllocString(IA2_RELATION_LABEL_FOR);
-      break;
-    case RelationType::LABELLED_BY:
-      *aRelationType = ::SysAllocString(IA2_RELATION_LABELED_BY);
-      break;
-    case RelationType::MEMBER_OF:
-      *aRelationType = ::SysAllocString(IA2_RELATION_MEMBER_OF);
-      break;
-    case RelationType::NODE_CHILD_OF:
-      *aRelationType = ::SysAllocString(IA2_RELATION_NODE_CHILD_OF);
-      break;
-    case RelationType::NODE_PARENT_OF:
-      *aRelationType = ::SysAllocString(IA2_RELATION_NODE_PARENT_OF);
-      break;
-    case RelationType::PARENT_WINDOW_OF:
-      *aRelationType = ::SysAllocString(IA2_RELATION_PARENT_WINDOW_OF);
-      break;
-    case RelationType::POPUP_FOR:
-      *aRelationType = ::SysAllocString(IA2_RELATION_POPUP_FOR);
-      break;
-    case RelationType::SUBWINDOW_OF:
-      *aRelationType = ::SysAllocString(IA2_RELATION_SUBWINDOW_OF);
-      break;
+#include "RelationTypeMap.h"
   }
 
   return *aRelationType ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
@@ -161,9 +119,8 @@ ia2AccessibleRelation::get_targets(long 
   for (long idx = 0; idx < maxTargets; idx++)
     get_target(idx, aTargets + idx);
 
   *aNTargets = maxTargets;
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
-
--- a/accessible/src/windows/ia2/ia2AccessibleRelation.h
+++ b/accessible/src/windows/ia2/ia2AccessibleRelation.h
@@ -7,16 +7,17 @@
 
 #ifndef _NS_ACCESSIBLE_RELATION_WRAP_H
 #define _NS_ACCESSIBLE_RELATION_WRAP_H
 
 #include "Accessible.h"
 #include "IUnknownImpl.h"
 #include "nsIAccessibleRelation.h"
 
+#include <utility>
 #include "nsTArray.h"
 
 #include "AccessibleRelation.h"
 
 namespace mozilla {
 namespace a11y {
 
 class ia2AccessibleRelation MOZ_FINAL : public IAccessibleRelation
@@ -55,34 +56,27 @@ private:
   ia2AccessibleRelation& operator = (const ia2AccessibleRelation&);
 
   RelationType mType;
   nsTArray<nsRefPtr<Accessible> > mTargets;
 };
 
 
 /**
- * Relations exposed to IAccessible2.
+ * Gecko to IAccessible2 relation types map.
  */
-static const RelationType sRelationTypesForIA2[] = {
-  RelationType::LABELLED_BY,
-  RelationType::LABEL_FOR,
-  RelationType::DESCRIBED_BY,
-  RelationType::DESCRIPTION_FOR,
-  RelationType::NODE_CHILD_OF,
-  RelationType::NODE_PARENT_OF,
-  RelationType::CONTROLLED_BY,
-  RelationType::CONTROLLER_FOR,
-  RelationType::FLOWS_TO,
-  RelationType::FLOWS_FROM,
-  RelationType::MEMBER_OF,
-  RelationType::SUBWINDOW_OF,
-  RelationType::EMBEDS,
-  RelationType::EMBEDDED_BY,
-  RelationType::POPUP_FOR,
-  RelationType::PARENT_WINDOW_OF
+
+const WCHAR *const IA2_RELATION_NULL = L"";
+
+#define RELATIONTYPE(geckoType, name, atkType, msaaType, ia2Type) \
+  std::pair<RelationType, const WCHAR *const>(RelationType::geckoType, ia2Type),
+
+static const std::pair<RelationType, const WCHAR *const> sRelationTypePairs[] = {
+#include "RelationTypeMap.h"
 };
 
+#undef RELATIONTYPE
+
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 
--- a/accessible/src/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/AccessibleWrap.cpp
@@ -893,16 +893,21 @@ AccessibleWrap::accNavigate(
     return E_INVALIDARG;
 
   if (accessible->IsDefunct())
     return CO_E_OBJNOTCONNECTED;
 
   Accessible* navAccessible = nullptr;
   Maybe<RelationType> xpRelation;
 
+#define RELATIONTYPE(geckoType, stringType, atkType, msaaType, ia2Type) \
+  case msaaType: \
+    xpRelation.construct(RelationType::geckoType); \
+    break;
+
   switch(navDir) {
     case NAVDIR_FIRSTCHILD:
       if (!nsAccUtils::MustPrune(accessible))
         navAccessible = accessible->FirstChild();
       break;
     case NAVDIR_LASTCHILD:
       if (!nsAccUtils::MustPrune(accessible))
         navAccessible = accessible->LastChild();
@@ -915,72 +920,24 @@ AccessibleWrap::accNavigate(
       break;
     case NAVDIR_DOWN:
     case NAVDIR_LEFT:
     case NAVDIR_RIGHT:
     case NAVDIR_UP:
       return E_NOTIMPL;
 
     // MSAA relationship extensions to accNavigate
-    case NAVRELATION_CONTROLLED_BY:
-      xpRelation.construct(RelationType::CONTROLLED_BY);
-      break;
-    case NAVRELATION_CONTROLLER_FOR:
-      xpRelation.construct(RelationType::CONTROLLER_FOR);
-      break;
-    case NAVRELATION_LABEL_FOR:
-      xpRelation.construct(RelationType::LABEL_FOR);
-      break;
-    case NAVRELATION_LABELLED_BY:
-      xpRelation.construct(RelationType::LABELLED_BY);
-      break;
-    case NAVRELATION_MEMBER_OF:
-      xpRelation.construct(RelationType::MEMBER_OF);
-      break;
-    case NAVRELATION_NODE_CHILD_OF:
-      xpRelation.construct(RelationType::NODE_CHILD_OF);
-      break;
-    case NAVRELATION_FLOWS_TO:
-      xpRelation.construct(RelationType::FLOWS_TO);
-      break;
-    case NAVRELATION_FLOWS_FROM:
-      xpRelation.construct(RelationType::FLOWS_FROM);
-      break;
-    case NAVRELATION_SUBWINDOW_OF:
-      xpRelation.construct(RelationType::SUBWINDOW_OF);
-      break;
-    case NAVRELATION_EMBEDS:
-      xpRelation.construct(RelationType::EMBEDS);
-      break;
-    case NAVRELATION_EMBEDDED_BY:
-      xpRelation.construct(RelationType::EMBEDDED_BY);
-      break;
-    case NAVRELATION_POPUP_FOR:
-      xpRelation.construct(RelationType::POPUP_FOR);
-      break;
-    case NAVRELATION_PARENT_WINDOW_OF:
-      xpRelation.construct(RelationType::PARENT_WINDOW_OF);
-      break;
-    case NAVRELATION_DEFAULT_BUTTON:
-      xpRelation.construct(RelationType::DEFAULT_BUTTON);
-      break;
-    case NAVRELATION_DESCRIBED_BY:
-      xpRelation.construct(RelationType::DESCRIBED_BY);
-      break;
-    case NAVRELATION_DESCRIPTION_FOR:
-      xpRelation.construct(RelationType::DESCRIPTION_FOR);
-      break;
-    case NAVRELATION_NODE_PARENT_OF:
-      xpRelation.construct(RelationType::NODE_PARENT_OF);
-      break;
+#include "RelationTypeMap.h"
 
     default:
       return E_INVALIDARG;
   }
 
+#undef RELATIONTYPE
+
   pvarEndUpAt->vt = VT_EMPTY;
 
   if (!xpRelation.empty()) {
     Relation rel = RelationByType(xpRelation.ref());
     navAccessible = rel.Next();
   }
 
   if (!navAccessible)
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "ef355aa8244d698a5b226ac4ef2408a2eb0812bb", 
+    "revision": "a57a913f1dd723afa191124f27b8d9fc4b0cb1c0", 
     "repo_path": "/integration/gaia-central"
 }
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -589,17 +589,17 @@ pref("browser.gesture.pinch.in.shift", "
 #endif
 pref("browser.gesture.twist.latched", false);
 pref("browser.gesture.twist.threshold", 0);
 pref("browser.gesture.twist.right", "cmd_gestureRotateRight");
 pref("browser.gesture.twist.left", "cmd_gestureRotateLeft");
 pref("browser.gesture.twist.end", "cmd_gestureRotateEnd");
 pref("browser.gesture.tap", "cmd_fullZoomReset");
 
-pref("browser.snapshots.limit", 0);
+pref("browser.snapshots.limit", 5);
 
 // 0: Nothing happens
 // 1: Scrolling contents
 // 2: Go back or go forward, in your history
 // 3: Zoom in or out.
 #ifdef XP_MACOSX
 // On OS X, if the wheel has one axis only, shift+wheel comes through as a
 // horizontal scroll event. Thus, we can't assign anything other than normal
--- a/configure.in
+++ b/configure.in
@@ -217,27 +217,34 @@ if test -n "$gonkdir" ; then
         ARCH_DIR=arch-x86
         ;;
     esac
 
     case "$ANDROID_VERSION" in
     15)
         GONK_INCLUDES="-I$gonkdir/frameworks/base/opengl/include -I$gonkdir/frameworks/base/native/include -I$gonkdir/frameworks/base/include -I$gonkdir/frameworks/base/services/camera -I$gonkdir/frameworks/base/include/media/stagefright -I$gonkdir/frameworks/base/include/media/stagefright/openmax -I$gonkdir/frameworks/base/media/libstagefright/rtsp -I$gonkdir/frameworks/base/media/libstagefright/include -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib -I$gonkdir/dalvik/libnativehelper/include/nativehelper"
         MOZ_B2G_BT=1
+        MOZ_B2G_BT_BLUEZ=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_RTSP=1
         ;;
     17|18)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         if test -d "$gonkdir/external/bluetooth/bluez"; then
-            GONK_INCLUDES+=" -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
+          GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
             MOZ_B2G_BT=1
+            MOZ_B2G_BT_BLUEZ=1
         fi
+        if test -d "$gonkdir/external/bluetooth/bluedroid"; then
+            MOZ_B2G_BT=1
+            MOZ_B2G_BT_BLUEDROID=1
+        fi
+
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         ;;
     *)
         AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
         ;;
     esac
@@ -7296,16 +7303,18 @@ dnl ====================================
 MOZ_ARG_ENABLE_BOOL(b2g-bt,
 [  --enable-b2g-bt      Set compile flags necessary for compiling Bluetooth API for B2G ],
     MOZ_B2G_BT=1,
     MOZ_B2G_BT= )
 if test -n "$MOZ_B2G_BT"; then
     AC_DEFINE(MOZ_B2G_BT)
 fi
 AC_SUBST(MOZ_B2G_BT)
+AC_SUBST(MOZ_B2G_BT_BLUEZ)
+AC_SUBST(MOZ_B2G_BT_BLUEDROID)
 
 dnl ========================================================
 dnl = Enable Pico Speech Synthesis (Gonk usually)
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(synth-pico,
 [  --enable-synth-pico  Set compile flags necessary for compiling Pico Web Speech API ],
     MOZ_SYNTH_PICO=1,
     MOZ_SYNTH_PICO= )
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -3114,30 +3114,34 @@ Element::GetMarkup(bool aIncludeSelf, ns
   nsIDocument* doc = OwnerDoc();
   if (IsInHTMLDocument()) {
     Serialize(this, !aIncludeSelf, aMarkup);
     return;
   }
 
   nsAutoString contentType;
   doc->GetContentType(contentType);
+  bool tryToCacheEncoder = !aIncludeSelf;
 
   nsCOMPtr<nsIDocumentEncoder> docEncoder = doc->GetCachedEncoder();
   if (!docEncoder) {
     docEncoder =
       do_CreateInstance(PromiseFlatCString(
         nsDependentCString(NS_DOC_ENCODER_CONTRACTID_BASE) +
         NS_ConvertUTF16toUTF8(contentType)
       ).get());
   }
   if (!docEncoder) {
     // This could be some type for which we create a synthetic document.  Try
     // again as XML
     contentType.AssignLiteral("application/xml");
     docEncoder = do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "application/xml");
+    // Don't try to cache the encoder since it would point to a different
+    // contentType once it has been reinitialized.
+    tryToCacheEncoder = false;
   }
 
   NS_ENSURE_TRUE_VOID(docEncoder);
 
   uint32_t flags = nsIDocumentEncoder::OutputEncodeBasicEntities |
                    // Output DOM-standard newlines
                    nsIDocumentEncoder::OutputLFLineBreak |
                    // Don't do linebreaking that's not present in
@@ -3158,17 +3162,17 @@ Element::GetMarkup(bool aIncludeSelf, ns
 
   if (aIncludeSelf) {
     docEncoder->SetNativeNode(this);
   } else {
     docEncoder->SetNativeContainerNode(this);
   }
   rv = docEncoder->EncodeToString(aMarkup);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
-  if (!aIncludeSelf) {
+  if (tryToCacheEncoder) {
     doc->SetCachedEncoder(docEncoder.forget());
   }
 }
 
 /**
  * Fire mutation events for changes caused by parsing directly into a
  * context node.
  *
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -73,16 +73,17 @@
 #include "GeckoProfiler.h"
 #include "nsObjectFrame.h"
 #include "nsDOMClassInfo.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsDOMJSUtils.h"
 
 #include "nsWidgetsCID.h"
 #include "nsContentCID.h"
+#include "mozilla/BasicEvents.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/Telemetry.h"
 
 #ifdef XP_WIN
 // Thanks so much, Microsoft! :(
 #ifdef CreateEvent
 #undef CreateEvent
 #endif
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -21,16 +21,17 @@
 #include "nsTextFrame.h"
 #include "nsISelectionController.h"
 #include "nsISelectionPrivate.h"
 #include "nsContentUtils.h"
 #include "nsLayoutUtils.h"
 #include "nsIMEStateManager.h"
 #include "nsIObjectFrame.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/TextEvents.h"
 #include <algorithm>
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 /******************************************************************/
 /* nsContentEventHandler                                          */
 /******************************************************************/
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -9,16 +9,17 @@
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/dom/TabParent.h"
 
 #include "nsCOMPtr.h"
 #include "nsEventStateManager.h"
+#include "nsFocusManager.h"
 #include "nsIMEStateManager.h"
 #include "nsContentEventHandler.h"
 #include "nsIContent.h"
 #include "nsINodeInfo.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "nsIWidget.h"
 #include "nsPresContext.h"
@@ -1950,17 +1951,17 @@ nsEventStateManager::FireContextClick()
         if (frameSel && frameSel->GetMouseDownState()) {
           // note that this can cause selection changed events to fire if we're in
           // a text field, which will null out mCurrentTarget
           frameSel->SetMouseDownState(false);
         }
       }
 
       nsIDocument* doc = mGestureDownContent->GetCurrentDoc();
-      nsAutoHandlingUserInputStatePusher userInpStatePusher(true, &event, doc);
+      AutoHandlingUserInputStatePusher userInpStatePusher(true, &event, doc);
 
       // dispatch to DOM
       nsEventDispatcher::Dispatch(mGestureDownContent, mPresContext, &event,
                                   nullptr, &status);
 
       // We don't need to dispatch to frame handling because no frames
       // watch NS_CONTEXTMENU except for nsMenuFrame and that's only for
       // dismissal. That's just as well since we don't really know
@@ -5843,9 +5844,56 @@ nsEventStateManager::Prefs::GetAccessMod
       return sChromeAccessModifierMask;
     case nsIDocShellTreeItem::typeContent:
       return sContentAccessModifierMask;
     default:
       return 0;
   }
 }
 
-
+/******************************************************************/
+/* mozilla::AutoHandlingUserInputStatePusher                      */
+/******************************************************************/
+
+AutoHandlingUserInputStatePusher::AutoHandlingUserInputStatePusher(
+                                    bool aIsHandlingUserInput,
+                                    WidgetEvent* aEvent,
+                                    nsIDocument* aDocument) :
+  mIsHandlingUserInput(aIsHandlingUserInput),
+  mIsMouseDown(aEvent && aEvent->message == NS_MOUSE_BUTTON_DOWN),
+  mResetFMMouseDownState(false)
+{
+  if (!aIsHandlingUserInput) {
+    return;
+  }
+  nsEventStateManager::StartHandlingUserInput();
+  if (!mIsMouseDown) {
+    return;
+  }
+  nsIPresShell::SetCapturingContent(nullptr, 0);
+  nsIPresShell::AllowMouseCapture(true);
+  if (!aDocument || !aEvent->mFlags.mIsTrusted) {
+    return;
+  }
+  nsFocusManager* fm = nsFocusManager::GetFocusManager();
+  NS_ENSURE_TRUE_VOID(fm);
+  fm->SetMouseButtonDownHandlingDocument(aDocument);
+  mResetFMMouseDownState = true;
+}
+
+AutoHandlingUserInputStatePusher::~AutoHandlingUserInputStatePusher()
+{
+  if (!mIsHandlingUserInput) {
+    return;
+  }
+  nsEventStateManager::StopHandlingUserInput();
+  if (!mIsMouseDown) {
+    return;
+  }
+  nsIPresShell::AllowMouseCapture(false);
+  if (!mResetFMMouseDownState) {
+    return;
+  }
+  nsFocusManager* fm = nsFocusManager::GetFocusManager();
+  NS_ENSURE_TRUE_VOID(fm);
+  fm->SetMouseButtonDownHandlingDocument(nullptr);
+}
+
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -1,30 +1,29 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 nsEventStateManager_h__
 #define nsEventStateManager_h__
 
-#include "mozilla/BasicEvents.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/TypedEnum.h"
 
 #include "nsIObserver.h"
 #include "nsWeakReference.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsFocusManager.h"
 #include "mozilla/TimeStamp.h"
 #include "nsIFrame.h"
 #include "Units.h"
 
+class nsFrameLoader;
 class nsIContent;
 class nsIDocument;
 class nsIDocShell;
 class nsIDocShellTreeNode;
 class nsIDocShellTreeItem;
 class imgIContainer;
 class nsDOMDataTransfer;
 class MouseEnterLeaveDispatcher;
@@ -842,73 +841,43 @@ public:
                             mozilla::WidgetGUIEvent* aMouseDownEvent);
   void KillClickHoldTimer();
   void FireContextClick();
 
   void SetPointerLock(nsIWidget* aWidget, nsIContent* aElement) ;
   static void sClickHoldCallback ( nsITimer* aTimer, void* aESM ) ;
 };
 
+namespace mozilla {
+
 /**
  * This class is used while processing real user input. During this time, popups
  * are allowed. For mousedown events, mouse capturing is also permitted.
  */
-class nsAutoHandlingUserInputStatePusher
+class AutoHandlingUserInputStatePusher
 {
 public:
-  nsAutoHandlingUserInputStatePusher(bool aIsHandlingUserInput,
-                                     mozilla::WidgetEvent* aEvent,
-                                     nsIDocument* aDocument)
-    : mIsHandlingUserInput(aIsHandlingUserInput),
-      mIsMouseDown(aEvent && aEvent->message == NS_MOUSE_BUTTON_DOWN),
-      mResetFMMouseDownState(false)
-  {
-    if (aIsHandlingUserInput) {
-      nsEventStateManager::StartHandlingUserInput();
-      if (mIsMouseDown) {
-        nsIPresShell::SetCapturingContent(nullptr, 0);
-        nsIPresShell::AllowMouseCapture(true);
-        if (aDocument && aEvent->mFlags.mIsTrusted) {
-          nsFocusManager* fm = nsFocusManager::GetFocusManager();
-          if (fm) {
-            fm->SetMouseButtonDownHandlingDocument(aDocument);
-            mResetFMMouseDownState = true;
-          }
-        }
-      }
-    }
-  }
-
-  ~nsAutoHandlingUserInputStatePusher()
-  {
-    if (mIsHandlingUserInput) {
-      nsEventStateManager::StopHandlingUserInput();
-      if (mIsMouseDown) {
-        nsIPresShell::AllowMouseCapture(false);
-        if (mResetFMMouseDownState) {
-          nsFocusManager* fm = nsFocusManager::GetFocusManager();
-          if (fm) {
-            fm->SetMouseButtonDownHandlingDocument(nullptr);
-          }
-        }
-      }
-    }
-  }
+  AutoHandlingUserInputStatePusher(bool aIsHandlingUserInput,
+                                   WidgetEvent* aEvent,
+                                   nsIDocument* aDocument);
+  ~AutoHandlingUserInputStatePusher();
 
 protected:
   bool mIsHandlingUserInput;
   bool mIsMouseDown;
   bool mResetFMMouseDownState;
 
 private:
   // Hide so that this class can only be stack-allocated
   static void* operator new(size_t /*size*/) CPP_THROW_NEW { return nullptr; }
   static void operator delete(void* /*memory*/) {}
 };
 
+} // namespace mozilla
+
 // Click and double-click events need to be handled even for content that
 // has no frame. This is required for Web compatibility.
 #define NS_EVENT_NEEDS_FRAME(event) \
     (!(event)->HasPluginActivationEventMessage() && \
      (event)->message != NS_MOUSE_CLICK && \
      (event)->message != NS_MOUSE_DOUBLECLICK)
 
 #endif // nsEventStateManager_h__
--- a/content/events/src/nsPrivateTextRange.h
+++ b/content/events/src/nsPrivateTextRange.h
@@ -5,17 +5,17 @@
 
 #ifndef nsPrivateTextRange_h__
 #define nsPrivateTextRange_h__
 
 #include "nsIPrivateTextRange.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/TextEvents.h"
+#include "mozilla/TextRange.h"
 
 class nsPrivateTextRange MOZ_FINAL : public nsIPrivateTextRange
 {
 	NS_DECL_ISUPPORTS
 public:
 
 	nsPrivateTextRange(const mozilla::TextRange &aTextRange);
 	virtual ~nsPrivateTextRange(void);
--- a/content/html/content/src/HTMLAudioElement.cpp
+++ b/content/html/content/src/HTMLAudioElement.cpp
@@ -12,33 +12,28 @@
 #include "nsGkAtoms.h"
 #include "nsIDocument.h"
 #include "jsfriendapi.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "AudioSampleFormat.h"
 #include "AudioChannelCommon.h"
 #include <algorithm>
-#include "mozilla/Preferences.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIHttpChannel.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "AudioStream.h"
 
-static bool
-IsAudioAPIEnabled()
-{
-  return mozilla::Preferences::GetBool("media.audio_data.enabled", true);
-}
-
 NS_IMPL_NS_NEW_HTML_ELEMENT(Audio)
 
 namespace mozilla {
 namespace dom {
 
+extern bool IsAudioAPIEnabled();
+
 NS_IMPL_ISUPPORTS_INHERITED4(HTMLAudioElement, HTMLMediaElement,
                              nsIDOMHTMLMediaElement, nsIDOMHTMLAudioElement,
                              nsITimerCallback, nsIAudioChannelAgentCallback)
 
 NS_IMPL_ELEMENT_CLONE(HTMLAudioElement)
 
 
 HTMLAudioElement::HTMLAudioElement(already_AddRefed<nsINodeInfo> aNodeInfo)
--- a/content/html/content/src/HTMLFormElement.cpp
+++ b/content/html/content/src/HTMLFormElement.cpp
@@ -802,19 +802,19 @@ HTMLFormElement::SubmitSubmission(nsForm
   //
   // Submit
   //
   nsCOMPtr<nsIDocShell> docShell;
 
   {
     nsAutoPopupStatePusher popupStatePusher(mSubmitPopupState);
 
-    nsAutoHandlingUserInputStatePusher userInpStatePusher(
-                                         mSubmitInitiatedFromUserInput,
-                                         nullptr, doc);
+    AutoHandlingUserInputStatePusher userInpStatePusher(
+                                       mSubmitInitiatedFromUserInput,
+                                       nullptr, doc);
 
     nsCOMPtr<nsIInputStream> postDataStream;
     rv = aFormSubmission->GetEncodedSubmission(actionURI,
                                                getter_AddRefs(postDataStream));
     NS_ENSURE_SUBMIT_SUCCESS(rv);
 
     rv = linkHandler->OnLinkClickSync(this, actionURI,
                                       target.get(),
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -987,16 +987,22 @@ static bool IsAutoplayEnabled()
   return Preferences::GetBool("media.autoplay.enabled");
 }
 
 static bool UseAudioChannelService()
 {
   return Preferences::GetBool("media.useAudioChannelService");
 }
 
+// Not static because it's used in HTMLAudioElement.
+bool IsAudioAPIEnabled()
+{
+  return mozilla::Preferences::GetBool("media.audio_data.enabled", false);
+}
+
 void HTMLMediaElement::UpdatePreloadAction()
 {
   PreloadAction nextAction = PRELOAD_UNDEFINED;
   // If autoplay is set, or we're playing, we should always preload data,
   // as we'll need it to play.
   if ((IsAutoplayEnabled() && HasAttr(kNameSpaceID_None, nsGkAtoms::autoplay)) ||
       !mPaused)
   {
@@ -1532,16 +1538,21 @@ NS_IMETHODIMP HTMLMediaElement::SetVolum
   ErrorResult rv;
   SetVolume(aVolume, rv);
   return rv.ErrorCode();
 }
 
 uint32_t
 HTMLMediaElement::GetMozChannels(ErrorResult& aRv) const
 {
+  if (!IsAudioAPIEnabled()) {
+    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return 0;
+  }
+
   if (!mDecoder && !mAudioStream) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return 0;
   }
 
   return mChannels;
 }
 
@@ -1551,16 +1562,21 @@ HTMLMediaElement::GetMozChannels(uint32_
   ErrorResult rv;
   *aMozChannels = GetMozChannels(rv);
  return rv.ErrorCode();
 }
 
 uint32_t
 HTMLMediaElement::GetMozSampleRate(ErrorResult& aRv) const
 {
+  if (!IsAudioAPIEnabled()) {
+    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return 0;
+  }
+
   if (!mDecoder && !mAudioStream) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return 0;
   }
 
   return mRate;
 }
 
@@ -1642,16 +1658,21 @@ HTMLMediaElement::MozGetMetadata(JSConte
   }
 
   return rv.ErrorCode();
 }
 
 uint32_t
 HTMLMediaElement::GetMozFrameBufferLength(ErrorResult& aRv) const
 {
+  if (!IsAudioAPIEnabled()) {
+    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return 0;
+  }
+
   // The framebuffer (via MozAudioAvailable events) is only available
   // when reading vs. writing audio directly.
   if (!mDecoder) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return 0;
   }
 
   return mDecoder->GetFrameBufferLength();
@@ -1663,16 +1684,21 @@ HTMLMediaElement::GetMozFrameBufferLengt
   ErrorResult rv;
   *aMozFrameBufferLength = GetMozFrameBufferLength(rv);
   return rv.ErrorCode();
 }
 
 void
 HTMLMediaElement::SetMozFrameBufferLength(uint32_t aMozFrameBufferLength, ErrorResult& aRv)
 {
+  if (!IsAudioAPIEnabled()) {
+    aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return;
+  }
+
   if (!mDecoder) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   aRv = mDecoder->RequestFrameBufferLength(aMozFrameBufferLength);
 }
 
@@ -3185,16 +3211,20 @@ nsresult HTMLMediaElement::DispatchAudio
                                                        float aTime)
 {
   // Auto manage the memory for the frame buffer. If we fail and return
   // an error, this ensures we free the memory in the frame buffer. Otherwise
   // we hand off ownership of the frame buffer to the audioavailable event,
   // which frees the memory when it's destroyed.
   nsAutoArrayPtr<float> frameBuffer(aFrameBuffer);
 
+  if (!IsAudioAPIEnabled()) {
+    return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+  }
+
   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(OwnerDoc());
   nsRefPtr<HTMLMediaElement> kungFuDeathGrip = this;
   NS_ENSURE_TRUE(domDoc, NS_ERROR_INVALID_ARG);
 
   nsCOMPtr<nsIDOMEvent> event;
   nsresult rv = domDoc->CreateEvent(NS_LITERAL_STRING("MozAudioAvailableEvent"),
                                     getter_AddRefs(event));
   nsCOMPtr<nsIDOMNotifyAudioAvailableEvent> audioavailableEvent(do_QueryInterface(event));
--- a/content/media/ogg/OggCodecState.cpp
+++ b/content/media/ogg/OggCodecState.cpp
@@ -57,17 +57,17 @@ static int64_t LEInt64(const unsigned ch
 
 // Reads a little-endian encoded unsigned 16bit integer at p.
 static uint16_t LEUint16(const unsigned char* p)
 {
   return p[0] + (p[1] << 8);
 }
 
 // Reads a little-endian encoded signed 16bit integer at p.
-static int16_t LEInt16(const unsigned char* p)
+inline int16_t LEInt16(const unsigned char* p)
 {
   return static_cast<int16_t>(LEUint16(p));
 }
 
 /** Decoder base class for Ogg-encapsulated streams. */
 OggCodecState*
 OggCodecState::Create(ogg_page* aPage)
 {
--- a/content/media/ogg/OggReader.cpp
+++ b/content/media/ogg/OggReader.cpp
@@ -54,17 +54,19 @@ extern PRLogModuleInfo* gMediaDecoderLog
 // lands between the seek target and SEEK_FUZZ_USECS microseconds before the
 // seek target.  This is becaue it's usually quicker to just keep downloading
 // from an exisiting connection than to do another bisection inside that
 // small range, which would open a new HTTP connetion.
 static const uint32_t SEEK_FUZZ_USECS = 500000;
 
 // The number of microseconds of "pre-roll" we use for Opus streams.
 // The specification recommends 80 ms.
+#ifdef MOZ_OPUS
 static const int64_t SEEK_OPUS_PREROLL = 80 * USECS_PER_MS;
+#endif /* MOZ_OPUS */
 
 enum PageSyncResult {
   PAGE_SYNC_ERROR = 1,
   PAGE_SYNC_END_OF_RANGE= 2,
   PAGE_SYNC_OK = 3
 };
 
 // Reads a page from the media resource.
@@ -81,18 +83,20 @@ PageSync(MediaResource* aResource,
 // is about 4300 bytes, so we read the file in chunks larger than that.
 static const int PAGE_STEP = 8192;
 
 OggReader::OggReader(AbstractMediaDecoder* aDecoder)
   : MediaDecoderReader(aDecoder),
     mMonitor("OggReader"),
     mTheoraState(nullptr),
     mVorbisState(nullptr),
+#ifdef MOZ_OPUS
     mOpusState(nullptr),
     mOpusEnabled(MediaDecoder::IsOpusEnabled()),
+#endif /* MOZ_OPUS */
     mSkeletonState(nullptr),
     mVorbisSerial(0),
     mOpusSerial(0),
     mTheoraSerial(0),
     mOpusPreSkip(0),
     mIsChained(false),
     mDecodedAudioFrames(0)
 {
@@ -126,19 +130,21 @@ nsresult OggReader::ResetDecode(bool sta
     res = NS_ERROR_FAILURE;
   }
 
   // Discard any previously buffered packets/pages.
   ogg_sync_reset(&mOggState);
   if (mVorbisState && NS_FAILED(mVorbisState->Reset())) {
     res = NS_ERROR_FAILURE;
   }
+#ifdef MOZ_OPUS
   if (mOpusState && NS_FAILED(mOpusState->Reset(start))) {
     res = NS_ERROR_FAILURE;
   }
+#endif /* MOZ_OPUS */
   if (mTheoraState && NS_FAILED(mTheoraState->Reset())) {
     res = NS_ERROR_FAILURE;
   }
 
   return res;
 }
 
 bool OggReader::ReadHeaders(OggCodecState* aState)
@@ -157,18 +163,20 @@ bool OggReader::ReadHeaders(OggCodecStat
 void OggReader::BuildSerialList(nsTArray<uint32_t>& aTracks)
 {
   if (HasVideo()) {
     aTracks.AppendElement(mTheoraState->mSerial);
   }
   if (HasAudio()) {
     if (mVorbisState) {
       aTracks.AppendElement(mVorbisState->mSerial);
-    } else if(mOpusState) {
+#ifdef MOZ_OPUS
+    } else if (mOpusState) {
       aTracks.AppendElement(mOpusState->mSerial);
+#endif /* MOZ_OPUS */
     }
   }
 }
 
 nsresult OggReader::ReadMetadata(MediaInfo* aInfo,
                                  MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@@ -215,27 +223,29 @@ nsresult OggReader::ReadMetadata(MediaIn
       if (codecState &&
           codecState->GetType() == OggCodecState::TYPE_THEORA &&
           !mTheoraState)
       {
         // First Theora bitstream, we'll play this one. Subsequent Theora
         // bitstreams will be ignored.
         mTheoraState = static_cast<TheoraState*>(codecState);
       }
+#ifdef MOZ_OPUS
       if (codecState &&
           codecState->GetType() == OggCodecState::TYPE_OPUS &&
           !mOpusState)
       {
         if (mOpusEnabled) {
           mOpusState = static_cast<OpusState*>(codecState);
         } else {
           NS_WARNING("Opus decoding disabled."
                      " See media.opus.enabled in about:config");
         }
       }
+#endif /* MOZ_OPUS */
       if (codecState &&
           codecState->GetType() == OggCodecState::TYPE_SKELETON &&
           !mSkeletonState)
       {
         mSkeletonState = static_cast<SkeletonState*>(codecState);
       }
     }
 
@@ -249,17 +259,20 @@ nsresult OggReader::ReadMetadata(MediaIn
 
   // We've read all BOS pages, so we know the streams contained in the media.
   // Now process all available header packets in the active Theora, Vorbis and
   // Skeleton streams.
 
   // Deactivate any non-primary bitstreams.
   for (uint32_t i = 0; i < bitstreams.Length(); i++) {
     OggCodecState* s = bitstreams[i];
-    if (s != mVorbisState && s != mOpusState &&
+    if (s != mVorbisState &&
+#ifdef MOZ_OPUS
+        s != mOpusState &&
+#endif /* MOZ_OPUS */
         s != mTheoraState && s != mSkeletonState) {
       s->Deactivate();
     }
   }
 
   if (mTheoraState && ReadHeaders(mTheoraState)) {
     nsIntRect picture = nsIntRect(mTheoraState->mInfo.pic_x,
                                   mTheoraState->mInfo.pic_y,
@@ -600,26 +613,32 @@ void OggReader::DownmixToStereo(nsAutoAr
 #endif
   channels = out_channels;
   buffer = dBuffer;
 }
 
 bool OggReader::DecodeAudioData()
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
-  NS_ASSERTION(mVorbisState != nullptr || mOpusState != nullptr,
-    "Need audio codec state to decode audio");
+  DebugOnly<bool> haveCodecState = mVorbisState != nullptr
+#ifdef MOZ_OPUS
+    || mOpusState != nullptr
+#endif /* MOZ_OPUS */
+    ;
+  NS_ASSERTION(haveCodecState, "Need audio codec state to decode audio");
 
   // Read the next data packet. Skip any non-data packets we encounter.
   ogg_packet* packet = 0;
   OggCodecState* codecState;
   if (mVorbisState)
     codecState = static_cast<OggCodecState*>(mVorbisState);
+#ifdef MOZ_OPUS
   else
     codecState = static_cast<OggCodecState*>(mOpusState);
+#endif /* MOZ_OPUS */
   do {
     if (packet) {
       OggCodecState::ReleasePacket(packet);
     }
     packet = NextOggPacket(codecState);
   } while (packet && codecState->IsHeader(packet));
 
   if (!packet) {
@@ -656,17 +675,19 @@ void OggReader::SetChained(bool aIsChain
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mDecoder->SetMediaSeekable(false);
   }
 }
 
 bool OggReader::ReadOggChain()
 {
   bool chained = false;
+#ifdef MOZ_OPUS
   OpusState* newOpusState = nullptr;
+#endif /* MOZ_OPUS */
   VorbisState* newVorbisState = nullptr;
   int channels = 0;
   long rate = 0;
   MetadataTags* tags = nullptr;
 
   if (HasVideo() || HasSkeleton() || !HasAudio()) {
     return false;
   }
@@ -1335,20 +1356,22 @@ nsresult OggReader::SeekInUnbuffered(int
   // don't do this offsetting when seeking in a buffered range,
   // as the extra decoding causes a noticeable speed hit when all the data
   // is buffered (compared to just doing a bisection to exactly find the
   // keyframe).
   int64_t keyframeOffsetMs = 0;
   if (HasVideo() && mTheoraState) {
     keyframeOffsetMs = mTheoraState->MaxKeyframeOffset();
   }
+#ifdef MOZ_OPUS
   // Add in the Opus pre-roll if necessary, as well.
   if (HasAudio() && mOpusState) {
     keyframeOffsetMs = std::max(keyframeOffsetMs, SEEK_OPUS_PREROLL);
   }
+#endif /* MOZ_OPUS */
   int64_t seekTarget = std::max(aStartTime, aTarget - keyframeOffsetMs);
   // Minimize the bisection search space using the known timestamps from the
   // buffered ranges.
   SeekRange k = SelectSeekRange(aRanges, seekTarget, aStartTime, aEndTime, false);
   return SeekBisection(seekTarget, k, SEEK_FUZZ_USECS);
 }
 
 nsresult OggReader::Seek(int64_t aTarget,
@@ -1359,19 +1382,21 @@ nsresult OggReader::Seek(int64_t aTarget
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   if (mIsChained)
     return NS_ERROR_FAILURE;
   LOG(PR_LOG_DEBUG, ("%p About to seek to %lld", mDecoder, aTarget));
   nsresult res;
   MediaResource* resource = mDecoder->GetResource();
   NS_ENSURE_TRUE(resource != nullptr, NS_ERROR_FAILURE);
   int64_t adjustedTarget = aTarget;
+#ifdef MOZ_OPUS
   if (HasAudio() && mOpusState){
     adjustedTarget = std::max(aStartTime, aTarget - SEEK_OPUS_PREROLL);
   }
+#endif /* MOZ_OPUS */
 
   if (adjustedTarget == aStartTime) {
     // We've seeked to the media start. Just seek to the offset of the first
     // content page.
     res = resource->Seek(nsISeekableStream::NS_SEEK_SET, 0);
     NS_ENSURE_SUCCESS(res,res);
 
     res = ResetDecode(true);
@@ -1817,20 +1842,22 @@ nsresult OggReader::GetBuffered(TimeRang
         continue;
       }
 
       uint32_t serial = ogg_page_serialno(&page);
       if (mVorbisState && serial == mVorbisSerial) {
         startTime = VorbisState::Time(&mVorbisInfo, granulepos);
         NS_ASSERTION(startTime > 0, "Must have positive start time");
       }
+#ifdef MOZ_OPUS
       else if (mOpusState && serial == mOpusSerial) {
         startTime = OpusState::Time(mOpusPreSkip, granulepos);
         NS_ASSERTION(startTime > 0, "Must have positive start time");
       }
+#endif /* MOZ_OPUS */
       else if (mTheoraState && serial == mTheoraSerial) {
         startTime = TheoraState::Time(&mTheoraInfo, granulepos);
         NS_ASSERTION(startTime > 0, "Must have positive start time");
       }
       else if (mCodecStore.Contains(serial)) {
         // Stream is not the theora or vorbis stream we're playing,
         // but is one that we have header data for.
         startOffset += page.header_len + page.body_len;
--- a/content/media/ogg/OggReader.h
+++ b/content/media/ogg/OggReader.h
@@ -57,18 +57,21 @@ public:
 
   // If the Theora granulepos has not been captured, it may read several packets
   // until one with a granulepos has been captured, to ensure that all packets
   // read have valid time info.
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
                                   int64_t aTimeThreshold);
 
   virtual bool HasAudio() {
-    return (mVorbisState != 0 && mVorbisState->mActive) ||
-           (mOpusState != 0 && mOpusState->mActive);
+    return (mVorbisState != 0 && mVorbisState->mActive)
+#ifdef MOZ_OPUS
+      || (mOpusState != 0 && mOpusState->mActive)
+#endif /* MOZ_OPUS */
+      ;
   }
 
   virtual bool HasVideo() {
     return mTheoraState != 0 && mTheoraState->mActive;
   }
 
   virtual nsresult ReadMetadata(MediaInfo* aInfo,
                                 MetadataTags** aTags);
@@ -263,23 +266,25 @@ private:
   OggCodecStore mCodecStore;
 
   // Decode state of the Theora bitstream we're decoding, if we have video.
   TheoraState* mTheoraState;
 
   // Decode state of the Vorbis bitstream we're decoding, if we have audio.
   VorbisState* mVorbisState;
 
+#ifdef MOZ_OPUS
   // Decode state of the Opus bitstream we're decoding, if we have one.
   OpusState *mOpusState;
 
   // Represents the user pref media.opus.enabled at the time our
   // contructor was called. We can't check it dynamically because
   // we're not on the main thread;
   bool mOpusEnabled;
+#endif /* MOZ_OPUS */
 
   // Decode state of the Skeleton bitstream.
   SkeletonState* mSkeletonState;
 
   // Ogg decoding state.
   ogg_sync_state mOggState;
 
   // Vorbis/Opus/Theora data used to compute timestamps. This is written on the
--- a/content/media/test/test_a4_tone.html
+++ b/content/media/test/test_a4_tone.html
@@ -10,19 +10,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <title>Media test: simple audioAvalailable event checks</title>
   <script type="text/javascript" src="/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=490705">Mozilla Bug 490705</a>
 
-<!-- mute audio, since there is no need to hear the sound for these tests -->
-<audio id='a1' controls></audio>
-
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /**
 * FFT is a class for calculating the Discrete Fourier Transform of a signal
 * with the Fast Fourier Transform algorithm.
 *
 * Source: github.com/corbanbrook/dsp.js; License: MIT; Copyright: Corban Brook
@@ -238,27 +235,29 @@ function checkResults() {
   SimpleTest.finish();
 }
 
 function audioEnded() {
   checkResults();
 }
 
 function initTest() {
-  var a1 = document.getElementById('a1');
+  var a1 = document.createElement("audio");
+  a1.id = "a1";
   a1.addEventListener("ended", audioEnded, false);
   a1.addEventListener("loadedmetadata", loadedMetadata, false);
   a1.addEventListener("MozAudioAvailable", audioAvailable, false);
   a1.src = testFile;
   a1.muted = true;
   a1.play();
+  document.body.appendChild(a1);
 }
 
 window.addEventListener("load", function(e) {
-  initTest();
+  SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, initTest);
 }, false);
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/test/test_audio_event_adopt.html
+++ b/content/media/test/test_audio_event_adopt.html
@@ -19,19 +19,21 @@ https://bugzilla.mozilla.org/show_bug.cg
     return document.adoptNode(resultNode).checked;
   }
   function endTest() {
     is(wasAudioAvailableCalled(), true, "audioAvailable was not called");
 
     SimpleTest.finish();
   }
   function startTest() {
-    var audio = adopt();
-    audio.addEventListener("ended", endTest, false);
-    audio.play();
+    SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, function () {
+      var audio = adopt();
+      audio.addEventListener("ended", endTest, false);
+      audio.play();
+    });
   }
 
   SimpleTest.waitForExplicitFinish();
 </script>
 
 </head>
 <body>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=490705">Mozilla Bug 490705</a>
--- a/content/media/test/test_audiowrite.html
+++ b/content/media/test/test_audiowrite.html
@@ -63,17 +63,17 @@ function runTests() {
   } catch(e) {
     writeArgsOK = true;
   }
   ok(writeArgsOK, "mozWriteAudio args test failed.");
   SimpleTest.finish();
 }
 
 window.addEventListener("load", function(e) {
-  runTests();
+  SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, runTests);
 }, false);
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/test/test_bug686137.html
+++ b/content/media/test/test_bug686137.html
@@ -7,37 +7,41 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <title>Media test: changing mozFrameBufferLength</title>
   <script type="text/javascript" src="/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=686137">Mozilla Bug 686137</a>
 
-<audio id="a1" controls muted preload="metadata"></audio>
-
 <pre id="test">
 <script class="testbody" type="text/javascript">
-var testFile = "bug495794.ogg";
-var a1 = document.getElementById('a1');
+
+SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, function () {
+  var a1 = document.createElement("audio");
+  a1.controls = true;
+  a1.muted = true;
+  a1.preload = "metadata";
+  a1.addEventListener("loadedmetadata", metaDataLoaded, false);
+  a1.src = "bug495794.ogg";
+  a1.load();
+});
+SimpleTest.waitForExplicitFinish();
 
 function audioAvailable(event) {
+  var a1 = event.target;
   a1.removeEventListener("MozAudioAvailable", audioAvailable);
   is( event.frameBuffer.length, 9001, "event.frameBuffer.length should be 9001.");
   is( event.frameBuffer.length, a1.mozFrameBufferLength, "event.frameBuffer.length should be " + a1.mozFrameBufferLength + ".");
   SimpleTest.finish();
 }
 
-function metaDataLoaded(){
+function metaDataLoaded(event){
+  var a1 = event.target;
   a1.addEventListener("MozAudioAvailable", audioAvailable, false);
   a1.mozFrameBufferLength = 9001;
   a1.play();
 }
 
-a1.addEventListener("loadedmetadata", metaDataLoaded, false);
-a1.src = testFile;
-a1.load();
-SimpleTest.waitForExplicitFinish();
-
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/test/test_framebuffer.html
+++ b/content/media/test/test_framebuffer.html
@@ -7,19 +7,16 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <title>Media test: framebuffer size checks</title>
   <script type="text/javascript" src="/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=490705">Mozilla Bug 490705</a>
 
-<!-- mute audio, since there is no need to hear the sound for these tests -->
-<audio id="a1" preload="metadata" controls></audio>
-
 <pre id="test">
 <script class="testbody" type="text/javascript">
 var testFile = "bug495794.ogg";
 var testFileDuration = 0.30;
 var testFileChannelCount = 2;
 var testFileSampleRate = 48000;
 var testFileFrameBufferLength = testFileChannelCount * 1024;
 
@@ -79,27 +76,32 @@ function checkResults() {
   SimpleTest.finish();
 }
 
 function audioEnded() {
   checkResults();
 }
 
 function initTest() {
-  var a1 = document.getElementById('a1');
+  var a1 = document.createElement("audio");
+  a1.id = "a1";
+  a1.preload = "metadata";
+  a1.controls = true;
+  document.body.appendChild(a1);
+
   a1.addEventListener("ended", audioEnded, false);
   a1.addEventListener("loadedmetadata", loadedMetadata, false);
   a1.addEventListener("MozAudioAvailable", audioAvailable, false);
   a1.src = testFile;
   a1.muted = true;
   a1.play();
 }
 
 window.addEventListener("load", function(e) {
-  initTest();
+  SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]}, initTest);
 }, false);
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/test/test_wave_data_s16.html
+++ b/content/media/test/test_wave_data_s16.html
@@ -29,19 +29,22 @@ function audioavailable(e) {
 
   // Only care about the first few samples
   SimpleTest.finish();
 }
 
 function startTest() {
   if (completed)
     return;
-  var v = document.getElementById('v');
-  v.addEventListener('MozAudioAvailable', audioavailable, false);
-  v.play();
+  SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]},
+                            function () {
+    var v = document.getElementById('v');
+    v.addEventListener('MozAudioAvailable', audioavailable, false);
+    v.play();
+  });
 }
 
 SimpleTest.waitForExplicitFinish();
 </script>
 </pre>
 <audio id='v'
        preload="metadata"
        onloadedmetadata='return startTest();'>
--- a/content/media/test/test_wave_data_u8.html
+++ b/content/media/test/test_wave_data_u8.html
@@ -29,19 +29,22 @@ function audioavailable(e) {
 
   // Only care about the first few samples
   SimpleTest.finish();
 }
 
 function startTest() {
   if (completed)
     return;
-  var v = document.getElementById('v');
-  v.addEventListener('MozAudioAvailable', audioavailable, false);
-  v.play();
+  SpecialPowers.pushPrefEnv({"set": [["media.audio_data.enabled", true]]},
+                            function () {
+    var v = document.getElementById('v');
+    v.addEventListener('MozAudioAvailable', audioavailable, false);
+    v.play();
+  });
 }
 
 SimpleTest.waitForExplicitFinish();
 </script>
 </pre>
 <audio id='v'
        preload="metadata"
        onloadedmetadata='return startTest();'>
--- a/content/media/webaudio/test/mochitest.ini
+++ b/content/media/webaudio/test/mochitest.ini
@@ -106,8 +106,9 @@ support-files =
 [test_scriptProcessorNodeChannelCount.html]
 [test_scriptProcessorNodeZeroInputOutput.html]
 [test_singleSourceDest.html]
 [test_waveShaper.html]
 [test_waveShaperNoCurve.html]
 [test_waveShaperZeroLengthCurve.html]
 [test_audioDestinationNode.html]
 [test_mozaudiochannel.html]
+[test_waveDecoder.html]
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_waveDecoder.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<meta charset=utf-8>
+<head>
+  <title>Test that we decode uint8 and sint16 wave files with correct conversion to float64</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+var testsDone = 0;
+var tests = ["UklGRjUrAABXQVZFZm10IBAAAAABAAEAESsAABErAAABAAgAZGF0YQMAAAD/AIA=",
+             "UklGRkZWAABXQVZFZm10IBAAAAABAAEAESsAACJWAAACABAAZGF0YQYAAAD/fwCAAAA="];
+
+SimpleTest.waitForExplicitFinish();
+
+function base64ToUint8Buffer(b64) {
+  var str = atob(b64)
+  var u8 = new Uint8Array(str.length);
+  for (var i = 0; i < str.length; ++i) {
+    u8[i] = str.charCodeAt(i);
+  }
+  return u8;
+}
+
+function fixupBufferSampleRate(u8, rate) {
+  u8[24] = (rate & 0x000000ff) >> 0;
+  u8[25] = (rate & 0x0000ff00) >> 8;
+  u8[26] = (rate & 0x00ff0000) >> 16;
+  u8[27] = (rate & 0xff000000) >> 24;
+}
+
+function finishTest() {
+  testsDone += 1;
+  if (testsDone == tests.length) {
+    SimpleTest.finish();
+  }
+}
+
+function decodeComplete(b) {
+  ok(true, "Decoding succeeded.");
+  is(b.numberOfChannels, 1, "Should have 1 channel.");
+  is(b.length, 3, "Should have three samples.");
+  var samples = b.getChannelData(0);
+  ok(samples[0] >  0.99 && samples[0] <  1.01, "Check near  1.0. Got " + samples[0]);
+  ok(samples[1] > -1.01 && samples[1] < -0.99, "Check near -1.0. Got " + samples[1]);
+  ok(samples[2] > -0.01 && samples[2] <  0.01, "Check near  0.0. Got " + samples[2]);
+  finishTest();
+}
+
+function decodeFailed() {
+  ok(false, "Decoding failed.");
+  finishTest();
+}
+
+addLoadEvent(function() {
+  var context = new AudioContext();
+
+  for (var i = 0; i < tests.length; ++i) {
+    var u8 = base64ToUint8Buffer(tests[i]);
+    fixupBufferSampleRate(u8, context.sampleRate);
+    context.decodeAudioData(u8.buffer, decodeComplete, decodeFailed);
+  }
+});
+</script>
+</pre>
+</body>
+</html>
--- a/dom/apps/src/InterAppComm.cpp
+++ b/dom/apps/src/InterAppComm.cpp
@@ -7,17 +7,17 @@
 #include "nsPIDOMWindow.h"
 #include "nsJSPrincipals.h"
 #include "mozilla/Preferences.h"
 #include "AccessCheck.h"
 
 using namespace mozilla::dom;
 
 /* static */ bool
-InterAppComm::EnabledForScope(JSContext* /* unused */, JSObject* aObj)
+InterAppComm::EnabledForScope(JSContext* /* unused */, JS::Handle<JSObject*> aObj)
 {
   // Disable the constructors if they're disabled by the preference for sure.
   if (!Preferences::GetBool("dom.inter-app-communication-api.enabled", false)) {
   	return false;
   }
 
   // Only expose the constructors to the chrome codes for Gecko internal uses.
   // The content pages shouldn't be aware of the constructors.
--- a/dom/apps/src/InterAppComm.h
+++ b/dom/apps/src/InterAppComm.h
@@ -12,15 +12,15 @@ struct JSContext;
 class JSObject;
 
 namespace mozilla {
 namespace dom {
 
 class InterAppComm
 {
 public:
-  static bool EnabledForScope(JSContext* /* unused */, JSObject* aObj);
+  static bool EnabledForScope(JSContext* /* unused */, JS::Handle<JSObject*> aObj);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_apps_InterAppComm_h
--- a/dom/base/CompositionStringSynthesizer.h
+++ b/dom/base/CompositionStringSynthesizer.h
@@ -6,17 +6,17 @@
 #ifndef mozilla_dom_compositionstringsynthesizer_h__
 #define mozilla_dom_compositionstringsynthesizer_h__
 
 #include "nsICompositionStringSynthesizer.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWeakReference.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/TextEvents.h"
+#include "mozilla/TextRange.h"
 
 class nsIWidget;
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class CompositionStringSynthesizer MOZ_FINAL :
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -3,16 +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/. */
 
 #include "amIAddonManager.h"
 #include "nsWindowMemoryReporter.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
+#include "nsIDOMWindowCollection.h"
 #include "nsIEffectiveTLDService.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsNetCID.h"
 #include "nsPrintfCString.h"
 #include "XPCJSMemoryReporter.h"
@@ -26,24 +27,80 @@ StaticRefPtr<nsWindowMemoryReporter> sWi
 nsWindowMemoryReporter::nsWindowMemoryReporter()
   : mCheckForGhostWindowsCallbackPending(false)
 {
 }
 
 NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver,
                    nsSupportsWeakReference)
 
-/* static */
-void
+static nsresult
+AddNonJSSizeOfWindowAndItsDescendents(nsGlobalWindow* aWindow,
+                                      nsTabSizes* aSizes)
+{
+  // Measure the window.
+  nsWindowSizes windowSizes(moz_malloc_size_of);
+  aWindow->AddSizeOfIncludingThis(&windowSizes);
+  windowSizes.addToTabSizes(aSizes);
+
+  // Measure the inner window, if there is one.
+  nsWindowSizes innerWindowSizes(moz_malloc_size_of);
+  nsGlobalWindow* inner = aWindow->GetCurrentInnerWindowInternal();
+  if (inner) {
+    inner->AddSizeOfIncludingThis(&innerWindowSizes);
+    innerWindowSizes.addToTabSizes(aSizes);
+  }
+
+  nsCOMPtr<nsIDOMWindowCollection> frames;
+  nsresult rv = aWindow->GetFrames(getter_AddRefs(frames));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  uint32_t length;
+  rv = frames->GetLength(&length);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Measure this window's descendents.
+  for (uint32_t i = 0; i < length; i++) {
+      nsCOMPtr<nsIDOMWindow> child;
+      rv = frames->Item(i, getter_AddRefs(child));
+      NS_ENSURE_SUCCESS(rv, rv);
+      NS_ENSURE_STATE(child);
+
+      nsGlobalWindow* childWin =
+        static_cast<nsGlobalWindow*>(static_cast<nsIDOMWindow *>(child.get()));
+
+      rv = AddNonJSSizeOfWindowAndItsDescendents(childWin, aSizes);
+      NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return NS_OK;
+}
+
+static nsresult
+NonJSSizeOfTab(nsPIDOMWindow* aWindow, size_t* aDomSize, size_t* aStyleSize, size_t* aOtherSize)
+{
+  nsGlobalWindow* window = static_cast<nsGlobalWindow*>(aWindow);
+
+  nsTabSizes sizes;
+  nsresult rv = AddNonJSSizeOfWindowAndItsDescendents(window, &sizes);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aDomSize   = sizes.mDom;
+  *aStyleSize = sizes.mStyle;
+  *aOtherSize = sizes.mOther;
+  return NS_OK;
+}
+
+/* static */ void
 nsWindowMemoryReporter::Init()
 {
   MOZ_ASSERT(!sWindowReporter);
   sWindowReporter = new nsWindowMemoryReporter();
   ClearOnShutdown(&sWindowReporter);
   NS_RegisterMemoryReporter(sWindowReporter);
+  RegisterNonJSSizeOfTab(NonJSSizeOfTab);
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
     // DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment",
     // when a window's docshell is set to NULL.
     os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC,
                     /* weakRef = */ true);
     os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
--- a/dom/base/nsWindowMemoryReporter.h
+++ b/dom/base/nsWindowMemoryReporter.h
@@ -7,48 +7,69 @@
 #ifndef nsWindowMemoryReporter_h__
 #define nsWindowMemoryReporter_h__
 
 #include "nsIMemoryReporter.h"
 #include "nsIObserver.h"
 #include "nsDataHashtable.h"
 #include "nsWeakReference.h"
 #include "nsAutoPtr.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Assertions.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/PodOperations.h"
 #include "mozilla/TimeStamp.h"
 #include "nsArenaMemoryStats.h"
-#include "mozilla/Attributes.h"
 
 // This should be used for any nsINode sub-class that has fields of its own
 // that it needs to measure;  any sub-class that doesn't use it will inherit
 // SizeOfExcludingThis from its super-class.  SizeOfIncludingThis() need not be
 // defined, it is inherited from nsINode.
 #define NS_DECL_SIZEOF_EXCLUDING_THIS \
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 class nsWindowSizes {
+#define FOR_EACH_SIZE(macro) \
+  macro(DOM,   mDOMElementNodes) \
+  macro(DOM,   mDOMTextNodes) \
+  macro(DOM,   mDOMCDATANodes) \
+  macro(DOM,   mDOMCommentNodes) \
+  macro(DOM,   mDOMEventTargets) \
+  macro(DOM,   mDOMOther) \
+  macro(Style, mStyleSheets) \
+  macro(Other, mLayoutPresShell) \
+  macro(Style, mLayoutStyleSets) \
+  macro(Other, mLayoutTextRuns) \
+  macro(Other, mLayoutPresContext) \
+  macro(Other, mPropertyTables) \
+
 public:
-  nsWindowSizes(mozilla::MallocSizeOf aMallocSizeOf) {
-    memset(this, 0, sizeof(nsWindowSizes));
-    mMallocSizeOf = aMallocSizeOf;
+  nsWindowSizes(mozilla::MallocSizeOf aMallocSizeOf)
+    :
+      #define ZERO_SIZE(kind, mSize)  mSize(0),
+      FOR_EACH_SIZE(ZERO_SIZE)
+      #undef ZERO_SIZE
+      mArenaStats(),
+      mMallocSizeOf(aMallocSizeOf)
+  {}
+
+  void addToTabSizes(nsTabSizes *sizes) const {
+    #define ADD_TO_TAB_SIZES(kind, mSize) sizes->add(nsTabSizes::kind, mSize);
+    FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
+    #undef ADD_TO_TAB_SIZES
+    mArenaStats.addToTabSizes(sizes);
   }
-  mozilla::MallocSizeOf mMallocSizeOf;
+
+  #define DECL_SIZE(kind, mSize) size_t mSize;
+  FOR_EACH_SIZE(DECL_SIZE);
+  #undef DECL_SIZE
   nsArenaMemoryStats mArenaStats;
-  size_t mDOMElementNodes;
-  size_t mDOMTextNodes;
-  size_t mDOMCDATANodes;
-  size_t mDOMCommentNodes;
-  size_t mDOMEventTargets;
-  size_t mDOMOther;
-  size_t mStyleSheets;
-  size_t mLayoutPresShell;
-  size_t mLayoutStyleSets;
-  size_t mLayoutTextRuns;
-  size_t mLayoutPresContext;
-  size_t mPropertyTables;
+  mozilla::MallocSizeOf mMallocSizeOf;
+
+#undef FOR_EACH_SIZE
 };
 
 /**
  * nsWindowMemoryReporter is responsible for the 'explicit/window-objects'
  * memory reporter.
  *
  * We classify DOM window objects into one of three categories:
  *
--- a/dom/bluetooth/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/BluetoothHfpManager.cpp
@@ -556,18 +556,17 @@ BluetoothHfpManager::HandleVolumeChanged
 void
 BluetoothHfpManager::HandleVoiceConnectionChanged()
 {
   nsCOMPtr<nsIMobileConnectionProvider> connection =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   NS_ENSURE_TRUE_VOID(connection);
 
   nsCOMPtr<nsIDOMMozMobileConnectionInfo> voiceInfo;
-  // TODO: Bug 921991 - B2G BT: support multiple sim cards
-  connection->GetVoiceConnectionInfo(0, getter_AddRefs(voiceInfo));
+  connection->GetVoiceConnectionInfo(getter_AddRefs(voiceInfo));
   NS_ENSURE_TRUE_VOID(voiceInfo);
 
   nsString type;
   voiceInfo->GetType(type);
   mPhoneType = GetPhoneType(type);
 
   bool roaming;
   voiceInfo->GetRoaming(&roaming);
@@ -593,18 +592,17 @@ BluetoothHfpManager::HandleVoiceConnecti
 
   /**
    * Possible return values for mode are:
    * - null (unknown): set mNetworkSelectionMode to 0 (auto)
    * - automatic: set mNetworkSelectionMode to 0 (auto)
    * - manual: set mNetworkSelectionMode to 1 (manual)
    */
   nsString mode;
-  // TODO: Bug 921991 - B2G BT: support multiple sim cards
-  connection->GetNetworkSelectionMode(0, mode);
+  connection->GetNetworkSelectionMode(mode);
   if (mode.EqualsLiteral("manual")) {
     mNetworkSelectionMode = 1;
   } else {
     mNetworkSelectionMode = 0;
   }
 
   nsCOMPtr<nsIDOMMozMobileNetworkInfo> network;
   voiceInfo->GetNetwork(getter_AddRefs(network));
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -287,32 +287,30 @@ BluetoothRilListener::StopIccListening()
 
 bool
 BluetoothRilListener::StartMobileConnectionListening()
 {
   nsCOMPtr<nsIMobileConnectionProvider> provider =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   NS_ENSURE_TRUE(provider, false);
 
-  // TODO: Bug 921991 - B2G BT: support multiple sim cards
   nsresult rv = provider->
-                  RegisterMobileConnectionMsg(0, mMobileConnectionListener);
+                  RegisterMobileConnectionMsg(mMobileConnectionListener);
   return NS_SUCCEEDED(rv);
 }
 
 bool
 BluetoothRilListener::StopMobileConnectionListening()
 {
   nsCOMPtr<nsIMobileConnectionProvider> provider =
     do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   NS_ENSURE_TRUE(provider, false);
 
-  // TODO: Bug 921991 - B2G BT: support multiple sim cards
   nsresult rv = provider->
-                  UnregisterMobileConnectionMsg(0, mMobileConnectionListener);
+                  UnregisterMobileConnectionMsg(mMobileConnectionListener);
   return NS_SUCCEEDED(rv);
 }
 
 bool
 BluetoothRilListener::StartTelephonyListening()
 {
   nsCOMPtr<nsITelephonyProvider> provider =
     do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
--- a/dom/bluetooth/BluetoothService.cpp
+++ b/dom/bluetooth/BluetoothService.cpp
@@ -39,17 +39,21 @@
 #include "nsXPCOM.h"
 
 #if defined(MOZ_WIDGET_GONK)
 #include "cutils/properties.h"
 #endif
 
 #if defined(MOZ_B2G_BT)
 # if defined(MOZ_BLUETOOTH_GONK)
-#  include "BluetoothGonkService.h"
+#ifdef MOZ_B2G_BT_BLUEZ
+#include "BluetoothGonkService.h"
+#else
+#include "BluetoothServiceBluedroid.h"
+#endif
 # elif defined(MOZ_BLUETOOTH_DBUS)
 #  include "BluetoothDBusService.h"
 # else
 #  error No_suitable_backend_for_bluetooth!
 # endif
 #endif
 
 #define MOZSETTINGS_CHANGED_ID      "mozsettings-changed"
@@ -299,20 +303,26 @@ BluetoothService::Create()
 {
 #if defined(MOZ_B2G_BT)
   if (!IsMainProcess()) {
     return BluetoothServiceChildProcess::Create();
   }
 #endif
 
 #if defined(MOZ_BLUETOOTH_GONK)
+#ifdef MOZ_B2G_BT_BLUEDROID
+  return new BluetoothServiceBluedroid();
+#else
   return new BluetoothGonkService();
+#endif
 #elif defined(MOZ_BLUETOOTH_DBUS)
+#ifdef MOZ_B2G_BT_BLUEZ
   return new BluetoothDBusService();
 #endif
+#endif
   BT_WARNING("No platform support for bluetooth!");
   return nullptr;
 }
 
 bool
 BluetoothService::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothServiceBluedroid.cpp
@@ -0,0 +1,341 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*-
+/* vim: set ts=2 et sw=2 tw=80: */
+/*
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "BluetoothServiceBluedroid.h"
+#include "BluetoothReplyRunnable.h"
+#include "BluetoothUtils.h"
+#include "BluetoothUuid.h"
+#include "mozilla/dom/bluetooth/BluetoothTypes.h"
+#include "mozilla/ipc/UnixSocket.h"
+
+using namespace mozilla;
+using namespace mozilla::ipc;
+USING_BLUETOOTH_NAMESPACE
+
+nsresult
+BluetoothServiceBluedroid::StartInternal()
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::StopInternal()
+{
+  return NS_OK;
+}
+
+bool
+BluetoothServiceBluedroid::IsEnabledInternal()
+{
+  return true;
+}
+
+nsresult
+BluetoothServiceBluedroid::GetDefaultAdapterPathInternal(
+  BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::GetConnectedDevicePropertiesInternal(
+  uint16_t aProfileId, BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+
+}
+
+nsresult
+BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
+  const nsTArray<nsString>& aDeviceAddress, BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::StartDiscoveryInternal(
+  BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::StopDiscoveryInternal(
+  BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::GetDevicePropertiesInternal(
+  const BluetoothSignal& aSignal)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
+                                       const BluetoothNamedValue& aValue,
+                                       BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+}
+
+bool
+BluetoothServiceBluedroid::GetDevicePath(const nsAString& aAdapterPath,
+                                         const nsAString& aDeviceAddress,
+                                         nsAString& aDevicePath)
+{
+  return true;
+}
+
+bool
+BluetoothServiceBluedroid::AddServiceRecords(const char* serviceName,
+                                             unsigned long long uuidMsb,
+                                             unsigned long long uuidLsb,
+                                             int channel)
+{
+  return true;
+}
+
+bool
+BluetoothServiceBluedroid::RemoveServiceRecords(const char* serviceName,
+                                                unsigned long long uuidMsb,
+                                                unsigned long long uuidLsb,
+                                                int channel)
+{
+  return true;
+}
+
+bool
+BluetoothServiceBluedroid::AddReservedServicesInternal(
+  const nsTArray<uint32_t>& aServices,
+  nsTArray<uint32_t>& aServiceHandlesContainer)
+{
+  return true;
+
+}
+
+bool
+BluetoothServiceBluedroid::RemoveReservedServicesInternal(
+  const nsTArray<uint32_t>& aServiceHandles)
+{
+  return true;
+}
+
+nsresult
+BluetoothServiceBluedroid::GetScoSocket(
+  const nsAString& aObjectPath, bool aAuth, bool aEncrypt,
+  mozilla::ipc::UnixSocketConsumer* aConsumer)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::GetServiceChannel(
+  const nsAString& aDeviceAddress,
+  const nsAString& aServiceUuid,
+  BluetoothProfileManagerBase* aManager)
+{
+  return NS_OK;
+}
+
+bool
+BluetoothServiceBluedroid::UpdateSdpRecords(
+  const nsAString& aDeviceAddress,
+  BluetoothProfileManagerBase* aManager)
+{
+  return true;
+}
+
+nsresult
+BluetoothServiceBluedroid::CreatePairedDeviceInternal(
+  const nsAString& aDeviceAddress, int aTimeout,
+  BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::RemoveDeviceInternal(
+  const nsAString& aDeviceObjectPath,
+  BluetoothReplyRunnable* aRunnable)
+{
+  return NS_OK;
+}
+
+bool
+BluetoothServiceBluedroid::SetPinCodeInternal(
+  const nsAString& aDeviceAddress, const nsAString& aPinCode,
+  BluetoothReplyRunnable* aRunnable)
+{
+  return true;
+}
+
+bool
+BluetoothServiceBluedroid::SetPasskeyInternal(
+  const nsAString& aDeviceAddress, uint32_t aPasskey,
+  BluetoothReplyRunnable* aRunnable)
+{
+  return true;
+}
+
+bool
+BluetoothServiceBluedroid::SetPairingConfirmationInternal(
+  const nsAString& aDeviceAddress, bool aConfirm,
+  BluetoothReplyRunnable* aRunnable)
+{
+  return true;
+}
+
+bool
+BluetoothServiceBluedroid::SetAuthorizationInternal(
+  const nsAString& aDeviceAddress, bool aAllow,
+  BluetoothReplyRunnable* aRunnable)
+{
+  return true;
+}
+
+nsresult
+BluetoothServiceBluedroid::PrepareAdapterInternal()
+{
+  return NS_OK;
+}
+
+void
+BluetoothServiceBluedroid::Connect(const nsAString& aDeviceAddress,
+                                   uint32_t aCod,
+                                   uint16_t aServiceUuid,
+                                   BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+bool
+BluetoothServiceBluedroid::IsConnected(uint16_t aProfileId)
+{
+  return true;
+}
+
+void
+BluetoothServiceBluedroid::Disconnect(
+  const nsAString& aDeviceAddress, uint16_t aServiceUuid,
+  BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::SendFile(const nsAString& aDeviceAddress,
+                                    BlobParent* aBlobParent,
+                                    BlobChild* aBlobChild,
+                                    BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::StopSendingFile(const nsAString& aDeviceAddress,
+                                           BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::ConfirmReceivingFile(
+  const nsAString& aDeviceAddress, bool aConfirm,
+  BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::ConnectSco(BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::DisconnectSco(BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::IsScoConnected(BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::SendMetaData(const nsAString& aTitle,
+                                        const nsAString& aArtist,
+                                        const nsAString& aAlbum,
+                                        int64_t aMediaNumber,
+                                        int64_t aTotalMediaCount,
+                                        int64_t aDuration,
+                                        BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::SendPlayStatus(
+  int64_t aDuration, int64_t aPosition,
+  const nsAString& aPlayStatus,
+  BluetoothReplyRunnable* aRunnable)
+{
+
+}
+
+void
+BluetoothServiceBluedroid::UpdatePlayStatus(
+  uint32_t aDuration, uint32_t aPosition, ControlPlayStatus aPlayStatus)
+{
+
+}
+
+nsresult
+BluetoothServiceBluedroid::SendSinkMessage(const nsAString& aDeviceAddresses,
+                                           const nsAString& aMessage)
+{
+  return NS_OK;
+}
+
+nsresult
+BluetoothServiceBluedroid::SendInputMessage(const nsAString& aDeviceAddresses,
+                                            const nsAString& aMessage)
+{
+  return NS_OK;
+}
+
+void
+BluetoothServiceBluedroid::AnswerWaitingCall(BluetoothReplyRunnable* aRunnable)
+{
+}
+
+void
+BluetoothServiceBluedroid::IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable)
+{
+}
+
+void
+BluetoothServiceBluedroid::ToggleCalls(BluetoothReplyRunnable* aRunnable)
+{
+}
+
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/BluetoothServiceBluedroid.h
@@ -0,0 +1,189 @@
+/* -*- 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_bluetooth_bluetoothservicebluedroid_h__
+#define mozilla_dom_bluetooth_bluetoothservicebluedroid_h__
+
+#include "BluetoothCommon.h"
+#include "BluetoothService.h"
+
+class DBusMessage;
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothServiceBluedroid : public BluetoothService
+{
+public:
+  virtual nsresult StartInternal();
+  virtual nsresult StopInternal();
+  virtual bool IsEnabledInternal();
+
+  virtual nsresult GetDefaultAdapterPathInternal(
+                                             BluetoothReplyRunnable* aRunnable);
+
+  virtual nsresult GetConnectedDevicePropertiesInternal(uint16_t aProfileId,
+                                             BluetoothReplyRunnable* aRunnable);
+
+  virtual nsresult GetPairedDevicePropertiesInternal(
+                                     const nsTArray<nsString>& aDeviceAddress,
+                                     BluetoothReplyRunnable* aRunnable);
+
+  virtual nsresult StartDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
+  virtual nsresult StopDiscoveryInternal(BluetoothReplyRunnable* aRunnable);
+
+  virtual nsresult
+  GetDevicePropertiesInternal(const BluetoothSignal& aSignal);
+
+  virtual nsresult
+  SetProperty(BluetoothObjectType aType,
+              const BluetoothNamedValue& aValue,
+              BluetoothReplyRunnable* aRunnable);
+
+  virtual bool
+  GetDevicePath(const nsAString& aAdapterPath,
+                const nsAString& aDeviceAddress,
+                nsAString& aDevicePath);
+
+  static bool
+  AddServiceRecords(const char* serviceName,
+                    unsigned long long uuidMsb,
+                    unsigned long long uuidLsb,
+                    int channel);
+
+  static bool
+  RemoveServiceRecords(const char* serviceName,
+                       unsigned long long uuidMsb,
+                       unsigned long long uuidLsb,
+                       int channel);
+
+  static bool
+  AddReservedServicesInternal(const nsTArray<uint32_t>& aServices,
+                              nsTArray<uint32_t>& aServiceHandlesContainer);
+
+  static bool
+  RemoveReservedServicesInternal(const nsTArray<uint32_t>& aServiceHandles);
+
+  virtual nsresult
+  GetScoSocket(const nsAString& aObjectPath,
+               bool aAuth,
+               bool aEncrypt,
+               mozilla::ipc::UnixSocketConsumer* aConsumer);
+
+  virtual nsresult
+  GetServiceChannel(const nsAString& aDeviceAddress,
+                    const nsAString& aServiceUuid,
+                    BluetoothProfileManagerBase* aManager);
+
+  virtual bool
+  UpdateSdpRecords(const nsAString& aDeviceAddress,
+                   BluetoothProfileManagerBase* aManager);
+
+  virtual nsresult
+  CreatePairedDeviceInternal(const nsAString& aDeviceAddress,
+                             int aTimeout,
+                             BluetoothReplyRunnable* aRunnable);
+
+  virtual nsresult
+  RemoveDeviceInternal(const nsAString& aDeviceObjectPath,
+                       BluetoothReplyRunnable* aRunnable);
+
+  virtual bool
+  SetPinCodeInternal(const nsAString& aDeviceAddress, const nsAString& aPinCode,
+                     BluetoothReplyRunnable* aRunnable);
+
+  virtual bool
+  SetPasskeyInternal(const nsAString& aDeviceAddress, uint32_t aPasskey,
+                     BluetoothReplyRunnable* aRunnable);
+
+  virtual bool
+  SetPairingConfirmationInternal(const nsAString& aDeviceAddress, bool aConfirm,
+                                 BluetoothReplyRunnable* aRunnable);
+
+  virtual bool
+  SetAuthorizationInternal(const nsAString& aDeviceAddress, bool aAllow,
+                           BluetoothReplyRunnable* aRunnable);
+
+  virtual nsresult
+  PrepareAdapterInternal();
+
+  virtual void
+  Connect(const nsAString& aDeviceAddress,
+          uint32_t aCod,
+          uint16_t aServiceUuid,
+          BluetoothReplyRunnable* aRunnable);
+
+  virtual bool
+  IsConnected(uint16_t aProfileId);
+
+  virtual void
+  Disconnect(const nsAString& aDeviceAddress, uint16_t aServiceUuid,
+             BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  SendFile(const nsAString& aDeviceAddress,
+           BlobParent* aBlobParent,
+           BlobChild* aBlobChild,
+           BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  StopSendingFile(const nsAString& aDeviceAddress,
+                  BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  ConfirmReceivingFile(const nsAString& aDeviceAddress, bool aConfirm,
+                       BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  ConnectSco(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  DisconnectSco(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  IsScoConnected(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  AnswerWaitingCall(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  IgnoreWaitingCall(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  ToggleCalls(BluetoothReplyRunnable* aRunnable);
+
+  virtual void
+  SendMetaData(const nsAString& aTitle,
+               const nsAString& aArtist,
+               const nsAString& aAlbum,
+               int64_t aMediaNumber,
+               int64_t aTotalMediaCount,
+               int64_t aDuration,
+               BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
+
+  virtual void
+  SendPlayStatus(int64_t aDuration,
+                 int64_t aPosition,
+                 const nsAString& aPlayStatus,
+                 BluetoothReplyRunnable* aRunnable) MOZ_OVERRIDE;
+
+  virtual void
+  UpdatePlayStatus(uint32_t aDuration,
+                   uint32_t aPosition,
+                   ControlPlayStatus aPlayStatus) MOZ_OVERRIDE;
+
+  virtual nsresult
+  SendSinkMessage(const nsAString& aDeviceAddresses,
+                  const nsAString& aMessage) MOZ_OVERRIDE;
+
+  virtual nsresult
+  SendInputMessage(const nsAString& aDeviceAddresses,
+                   const nsAString& aMessage) MOZ_OVERRIDE;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
+
--- a/dom/bluetooth/BluetoothUnixSocketConnector.cpp
+++ b/dom/bluetooth/BluetoothUnixSocketConnector.cpp
@@ -22,32 +22,34 @@
  */
 
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <errno.h>
 
 #include <sys/socket.h>
+#ifdef MOZ_B2G_BT_BLUEZ
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/rfcomm.h>
 #include <bluetooth/sco.h>
-
+#endif
 #include "BluetoothUnixSocketConnector.h"
 #include "nsThreadUtils.h"
 
 using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 static const int RFCOMM_SO_SNDBUF = 70 * 1024;  // 70 KB send buffer
 static const int L2CAP_SO_SNDBUF = 400 * 1024;  // 400 KB send buffer
 static const int L2CAP_SO_RCVBUF = 400 * 1024;  // 400 KB receive buffer
 static const int L2CAP_MAX_MTU = 65000;
 
+#ifdef MOZ_B2G_BT_BLUEZ
 static
 int get_bdaddr(const char *str, bdaddr_t *ba)
 {
   char *d = ((char*)ba) + 5, *endp;
   for (int i = 0; i < 6; i++) {
     *d-- = strtol(str, &endp, 16);
     MOZ_ASSERT(!(*endp != ':' && i != 5));
     str = endp + 1;
@@ -57,30 +59,33 @@ int get_bdaddr(const char *str, bdaddr_t
 
 static
 void get_bdaddr_as_string(const bdaddr_t *ba, char *str) {
     const uint8_t *b = (const uint8_t *)ba;
     sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
             b[5], b[4], b[3], b[2], b[1], b[0]);
 }
 
+#endif
+
 BluetoothUnixSocketConnector::BluetoothUnixSocketConnector(
   BluetoothSocketType aType,
   int aChannel,
   bool aAuth,
   bool aEncrypt) : mType(aType)
                  , mChannel(aChannel)
                  , mAuth(aAuth)
                  , mEncrypt(aEncrypt)
 {
 }
 
 bool
 BluetoothUnixSocketConnector::SetUp(int aFd)
 {
+#ifdef MOZ_B2G_BT_BLUEZ
   int lm = 0;
   int sndbuf, rcvbuf;
 
   /* kernel does not yet support LM for SCO */
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     lm |= mAuth ? RFCOMM_LM_AUTH : 0;
     lm |= mEncrypt ? RFCOMM_LM_ENCRYPT : 0;
@@ -152,26 +157,27 @@ BluetoothUnixSocketConnector::SetUp(int 
 
       rcvbuf = L2CAP_SO_RCVBUF;
       if (setsockopt(aFd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf))) {
         BT_WARNING("setsockopt(SO_RCVBUF) failed, throwing");
         return false;
       }
     }
   }
-
+#endif
   return true;
 }
 
 int
 BluetoothUnixSocketConnector::Create()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   int fd = -1;
 
+#ifdef MOZ_B2G_BT_BLUEZ
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
     break;
   case BluetoothSocketType::SCO:
     fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
     break;
   case BluetoothSocketType::L2CAP:
@@ -188,26 +194,27 @@ BluetoothUnixSocketConnector::Create()
     BT_WARNING("Could not open bluetooth socket!");
     return -1;
   }
 
   if (!SetUp(fd)) {
     BT_WARNING("Could not set up socket!");
     return -1;
   }
-
+#endif
   return fd;
 }
 
 bool
 BluetoothUnixSocketConnector::CreateAddr(bool aIsServer,
                                          socklen_t& aAddrSize,
                                          sockaddr_any& aAddr,
                                          const char* aAddress)
 {
+#ifdef MOZ_B2G_BT_BLUEZ
   // Set to BDADDR_ANY, if it's not a server, we'll reset.
   bdaddr_t bd_address_obj = {{0, 0, 0, 0, 0, 0}};
 
   if (!aIsServer && aAddress && strlen(aAddress) > 0) {
     if (get_bdaddr(aAddress, &bd_address_obj)) {
       BT_WARNING("Can't get bluetooth address!");
       return false;
     }
@@ -237,32 +244,35 @@ BluetoothUnixSocketConnector::CreateAddr
     aAddrSize = sizeof(addr_sco);
     aAddr.sco.sco_family = AF_BLUETOOTH;
     memcpy(&aAddr.sco.sco_bdaddr, &bd_address_obj, sizeof(bd_address_obj));
     break;
   default:
     BT_WARNING("Socket type unknown!");
     return false;
   }
+#endif
   return true;
 }
 
 void
 BluetoothUnixSocketConnector::GetSocketAddr(const sockaddr_any& aAddr,
                                             nsAString& aAddrStr)
 {
+#ifdef MOZ_B2G_BT_BLUEZ
   char addr[18];
   switch (mType) {
   case BluetoothSocketType::RFCOMM:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.rc.rc_bdaddr), addr);
     break;
   case BluetoothSocketType::SCO:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.sco.sco_bdaddr), addr);
     break;
   case BluetoothSocketType::L2CAP:
   case BluetoothSocketType::EL2CAP:
     get_bdaddr_as_string((bdaddr_t*)(&aAddr.l2.l2_bdaddr), addr);
     break;
   default:
     MOZ_CRASH("Socket should be either RFCOMM or SCO!");
   }
   aAddrStr.AssignASCII(addr);
+#endif
 }
--- a/dom/bluetooth/Makefile.in
+++ b/dom/bluetooth/Makefile.in
@@ -31,16 +31,24 @@ ifdef MOZ_ENABLE_DBUS
 VPATH += $(srcdir)/linux
 LOCAL_INCLUDES += $(MOZ_DBUS_CFLAGS)
 CFLAGS += $(MOZ_DBUS_GLIB_CFLAGS)
 CXXFLAGS += $(MOZ_DBUS_GLIB_CFLAGS) -DHAVE_PTHREADS
 DEFINES += -DMOZ_BLUETOOTH_DBUS
 endif
 endif
 
+ifdef MOZ_B2G_BT_BLUEZ
+DEFINES += -DMOZ_B2G_BT_BLUEZ
+endif
+
+ifdef MOZ_B2G_BT_BLUEDROID
+DEFINES += -DMOZ_B2G_BT_BLUEDROID
+endif
+
 # Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
 # subdirectory.
 LOCAL_INCLUDES += $(VPATH:%=-I%)
 
 endif # MOZ_B2G_BT
 
 include $(topsrcdir)/config/rules.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/dom/bluetooth/linux/BluetoothDBusService.h
+++ b/dom/bluetooth/linux/BluetoothDBusService.h
@@ -19,16 +19,19 @@ BEGIN_BLUETOOTH_NAMESPACE
 /**
  * BluetoothDBusService is the implementation of BluetoothService for DBus on
  * linux/android/B2G. Function comments are in BluetoothService.h
  */
 
 class BluetoothDBusService : public BluetoothService
 {
 public:
+  BluetoothDBusService();
+  ~BluetoothDBusService();
+
   bool IsReady();
 
   virtual nsresult StartInternal() MOZ_OVERRIDE;
 
   virtual nsresult StopInternal() MOZ_OVERRIDE;
 
   virtual bool IsEnabledInternal() MOZ_OVERRIDE;
 
@@ -163,21 +166,16 @@ public:
 
   virtual nsresult
   SendSinkMessage(const nsAString& aDeviceAddresses,
                   const nsAString& aMessage) MOZ_OVERRIDE;
 
   virtual nsresult
   SendInputMessage(const nsAString& aDeviceAddresses,
                    const nsAString& aMessage) MOZ_OVERRIDE;
-
-protected:
-  BluetoothDBusService();
-  ~BluetoothDBusService();
-
 private:
   /**
    * For DBus Control method of "UpdateNotification", event id should be
    * specified as following:
    * (Please see specification of AVRCP 1.3, Table 5.28 for more details.)
    */
   enum ControlEventId {
     EVENT_PLAYBACK_STATUS_CHANGED            = 0x01,
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -48,24 +48,29 @@ if CONFIG['MOZ_B2G_BT']:
     ]
 
     if CONFIG['MOZ_B2G_RIL']:
         CPP_SOURCES += [
             'BluetoothRilListener.cpp',
         ]
 
     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
-        CPP_SOURCES += [
-            'linux/BluetoothDBusService.cpp',
-            'gonk/BluetoothGonkService.cpp',
-        ]
+        if CONFIG['MOZ_B2G_BT_BLUEZ']:
+            CPP_SOURCES += [
+               'linux/BluetoothDBusService.cpp',
+               'gonk/BluetoothGonkService.cpp',
+            ]
+        if CONFIG['MOZ_B2G_BT_BLUEDROID']:
+            CPP_SOURCES += [
+                'BluetoothServiceBluedroid.cpp',
+            ]
     else:
         if CONFIG['MOZ_ENABLE_DBUS']:
             CPP_SOURCES += [
-                'linux/BluetoothDBusService.cpp',
+                 'linux/BluetoothDBusService.cpp',
             ]
 
 EXPORTS.mozilla.dom.bluetooth.ipc += [
     'ipc/BluetoothMessageUtils.h',
 ]
 
 EXPORTS.mozilla.dom.bluetooth += [
     'BluetoothCommon.h',
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -2,20 +2,20 @@
 /* vim: set sw=4 ts=8 et 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_tabs_TabParent_h
 #define mozilla_tabs_TabParent_h
 
+#include "mozilla/EventForwards.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/dom/PContentDialogParent.h"
 #include "mozilla/dom/TabContext.h"
-#include "mozilla/TouchEvents.h"
 #include "nsCOMPtr.h"
 #include "nsIAuthPromptProvider.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsIDialogParamBlock.h"
 #include "nsISecureBrowserUI.h"
 #include "nsITabParent.h"
 #include "Units.h"
 #include "js/TypeDecls.h"
--- a/dom/network/interfaces/nsIMobileConnectionProvider.idl
+++ b/dom/network/interfaces/nsIMobileConnectionProvider.idl
@@ -28,84 +28,60 @@ interface nsIMobileConnectionListener : 
                                     in unsigned long timeoutMs);
   void notifyOtaStatusChanged(in DOMString status);
 };
 
 /**
  * XPCOM component (in the content process) that provides the mobile
  * network information.
  */
-[scriptable, uuid(84278a49-0f05-4585-b3f4-c74882ae5719)]
+[scriptable, uuid(c66652e0-0628-11e3-8ffd-0800200c9a66)]
 interface nsIMobileConnectionProvider : nsISupports
 {
   /**
    * Called when a content process registers receiving unsolicited messages from
    * RadioInterfaceLayer in the chrome process. Only a content process that has
    * the 'mobileconnection' permission is allowed to register.
    */
-  void registerMobileConnectionMsg(in unsigned long clientId,
-                                   in nsIMobileConnectionListener listener);
-  void unregisterMobileConnectionMsg(in unsigned long clientId,
-                                     in nsIMobileConnectionListener listener);
-
-  nsIDOMMozMobileConnectionInfo getVoiceConnectionInfo(in unsigned long clientId);
-  nsIDOMMozMobileConnectionInfo getDataConnectionInfo(in unsigned long clientId);
-  DOMString getIccId(in unsigned long clientId);
-  DOMString getNetworkSelectionMode(in unsigned long clientId);
+  void registerMobileConnectionMsg(in nsIMobileConnectionListener listener);
+  void unregisterMobileConnectionMsg(in nsIMobileConnectionListener listener);
 
-  nsIDOMDOMRequest getNetworks(in unsigned long clientId,
-                               in nsIDOMWindow window);
-  nsIDOMDOMRequest selectNetwork(in unsigned long clientId,
-                                 in nsIDOMWindow window,
-                                 in nsIDOMMozMobileNetworkInfo network);
-  nsIDOMDOMRequest selectNetworkAutomatically(in unsigned long clientId,
-                                              in nsIDOMWindow window);
+  readonly attribute nsIDOMMozMobileConnectionInfo voiceConnectionInfo;
+  readonly attribute nsIDOMMozMobileConnectionInfo dataConnectionInfo;
+  readonly attribute DOMString networkSelectionMode;
 
-  nsIDOMDOMRequest setRoamingPreference(in unsigned long clientId,
-                                        in nsIDOMWindow window,
+  nsIDOMDOMRequest getNetworks(in nsIDOMWindow window);
+  nsIDOMDOMRequest selectNetwork(in nsIDOMWindow window, in nsIDOMMozMobileNetworkInfo network);
+  nsIDOMDOMRequest selectNetworkAutomatically(in nsIDOMWindow window);
+
+  nsIDOMDOMRequest setRoamingPreference(in nsIDOMWindow window,
                                         in DOMString mode);
-  nsIDOMDOMRequest getRoamingPreference(in unsigned long clientId,
-                                        in nsIDOMWindow window);
+  nsIDOMDOMRequest getRoamingPreference(in nsIDOMWindow window);
 
-  nsIDOMDOMRequest setVoicePrivacyMode(in unsigned long clientId,
-                                       in nsIDOMWindow window,
+  nsIDOMDOMRequest setVoicePrivacyMode(in nsIDOMWindow window,
                                        in bool enabled);
-  nsIDOMDOMRequest getVoicePrivacyMode(in unsigned long clientId,
-                                       in nsIDOMWindow window);
+  nsIDOMDOMRequest getVoicePrivacyMode(in nsIDOMWindow window);
 
-  nsIDOMDOMRequest sendMMI(in unsigned long clientId,
-                           in nsIDOMWindow window,
-                           in DOMString mmi);
-  nsIDOMDOMRequest cancelMMI(in unsigned long clientId,
-                             in nsIDOMWindow window);
+  nsIDOMDOMRequest sendMMI(in nsIDOMWindow window, in DOMString mmi);
+  nsIDOMDOMRequest cancelMMI(in nsIDOMWindow window);
 
-  nsIDOMDOMRequest getCallForwardingOption(in unsigned long clientId,
-                                           in nsIDOMWindow window,
+  nsIDOMDOMRequest getCallForwardingOption(in nsIDOMWindow   window,
                                            in unsigned short reason);
-  nsIDOMDOMRequest setCallForwardingOption(in unsigned long clientId,
-                                           in nsIDOMWindow window,
+  nsIDOMDOMRequest setCallForwardingOption(in nsIDOMWindow          window,
                                            in nsIDOMMozMobileCFInfo CFInfo);
 
-  nsIDOMDOMRequest getCallBarringOption(in unsigned long clientId,
-                                        in nsIDOMWindow window,
-                                        in jsval option);
-  nsIDOMDOMRequest setCallBarringOption(in unsigned long clientId,
-                                        in nsIDOMWindow window,
-                                        in jsval option);
-  nsIDOMDOMRequest changeCallBarringPassword(in unsigned long clientId,
-                                             in nsIDOMWindow window,
+  nsIDOMDOMRequest getCallBarringOption(in nsIDOMWindow window,
+                                        in jsval        option);
+  nsIDOMDOMRequest setCallBarringOption(in nsIDOMWindow window,
+                                        in jsval        option);
+  nsIDOMDOMRequest changeCallBarringPassword(in nsIDOMWindow window,
                                              in jsval info);
 
-  nsIDOMDOMRequest setCallWaitingOption(in unsigned long clientId,
-                                        in nsIDOMWindow window,
+  nsIDOMDOMRequest setCallWaitingOption(in nsIDOMWindow   window,
                                         in bool enabled);
-  nsIDOMDOMRequest getCallWaitingOption(in unsigned long clientId,
-                                        in nsIDOMWindow window);
+  nsIDOMDOMRequest getCallWaitingOption(in nsIDOMWindow   window);
 
-  nsIDOMDOMRequest setCallingLineIdRestriction(in unsigned long clientId,
-                                               in nsIDOMWindow window,
+  nsIDOMDOMRequest setCallingLineIdRestriction(in nsIDOMWindow   window,
                                                in unsigned short clirMode);
-  nsIDOMDOMRequest getCallingLineIdRestriction(in unsigned long clientId,
-                                               in nsIDOMWindow window);
+  nsIDOMDOMRequest getCallingLineIdRestriction(in nsIDOMWindow   window);
 
-  nsIDOMDOMRequest exitEmergencyCbMode(in unsigned long clientId,
-                                       in nsIDOMWindow window);
+  nsIDOMDOMRequest exitEmergencyCbMode(in nsIDOMWindow window);
 };
--- a/dom/network/src/MobileConnection.cpp
+++ b/dom/network/src/MobileConnection.cpp
@@ -78,19 +78,16 @@ NS_IMPL_EVENT_HANDLER(MobileConnection, 
 NS_IMPL_EVENT_HANDLER(MobileConnection, emergencycbmodechange)
 NS_IMPL_EVENT_HANDLER(MobileConnection, otastatuschange)
 
 MobileConnection::MobileConnection()
 {
   mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
   mWindow = nullptr;
 
-  // TODO: Bug 814629 - WebMobileConnection API: support multiple sim cards
-  mClientId = 0;
-
   // Not being able to acquire the provider isn't fatal since we check
   // for it explicitly below.
   if (!mProvider) {
     NS_WARNING("Could not acquire nsIMobileConnectionProvider!");
     return;
   }
 }
 
@@ -99,30 +96,30 @@ MobileConnection::Init(nsPIDOMWindow* aW
 {
   BindToOwner(aWindow);
 
   mWindow = do_GetWeakReference(aWindow);
   mListener = new Listener(this);
 
   if (!CheckPermission("mobilenetwork") &&
       CheckPermission("mobileconnection")) {
-    DebugOnly<nsresult> rv = mProvider->RegisterMobileConnectionMsg(mClientId, mListener);
+    DebugOnly<nsresult> rv = mProvider->RegisterMobileConnectionMsg(mListener);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                      "Failed registering mobile connection messages with provider");
 
     printf_stderr("MobileConnection initialized");
   }
 }
 
 void
 MobileConnection::Shutdown()
 {
   if (mProvider && mListener) {
     mListener->Disconnect();
-    mProvider->UnregisterMobileConnectionMsg(mClientId, mListener);
+    mProvider->UnregisterMobileConnectionMsg(mListener);
     mProvider = nullptr;
     mListener = nullptr;
   }
 }
 
 // nsIDOMMozMobileConnection
 
 NS_IMETHODIMP
@@ -171,347 +168,347 @@ MobileConnection::CheckPermission(const 
 NS_IMETHODIMP
 MobileConnection::GetVoice(nsIDOMMozMobileConnectionInfo** voice)
 {
   *voice = nullptr;
 
   if (!mProvider || !CheckPermission("mobileconnection")) {
     return NS_OK;
   }
-  return mProvider->GetVoiceConnectionInfo(mClientId, voice);
+  return mProvider->GetVoiceConnectionInfo(voice);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetData(nsIDOMMozMobileConnectionInfo** data)
 {
   *data = nullptr;
 
   if (!mProvider || !CheckPermission("mobileconnection")) {
     return NS_OK;
   }
-  return mProvider->GetDataConnectionInfo(mClientId, data);
+  return mProvider->GetDataConnectionInfo(data);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetNetworkSelectionMode(nsAString& networkSelectionMode)
 {
   networkSelectionMode.SetIsVoid(true);
 
   if (!mProvider || !CheckPermission("mobileconnection")) {
      return NS_OK;
   }
-  return mProvider->GetNetworkSelectionMode(mClientId, networkSelectionMode);
+  return mProvider->GetNetworkSelectionMode(networkSelectionMode);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetNetworks(nsIDOMDOMRequest** request)
 {
   *request = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->GetNetworks(mClientId, GetOwner(), request);
+  return mProvider->GetNetworks(GetOwner(), request);
 }
 
 NS_IMETHODIMP
 MobileConnection::SelectNetwork(nsIDOMMozMobileNetworkInfo* network, nsIDOMDOMRequest** request)
 {
   *request = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SelectNetwork(mClientId, GetOwner(), network, request);
+  return mProvider->SelectNetwork(GetOwner(), network, request);
 }
 
 NS_IMETHODIMP
 MobileConnection::SelectNetworkAutomatically(nsIDOMDOMRequest** request)
 {
   *request = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SelectNetworkAutomatically(mClientId, GetOwner(), request);
+  return mProvider->SelectNetworkAutomatically(GetOwner(), request);
 }
 
 NS_IMETHODIMP
 MobileConnection::SetRoamingPreference(const nsAString& aMode, nsIDOMDOMRequest** aDomRequest)
 {
   *aDomRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SetRoamingPreference(mClientId, GetOwner(), aMode, aDomRequest);
+  return mProvider->SetRoamingPreference(GetOwner(), aMode, aDomRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetRoamingPreference(nsIDOMDOMRequest** aDomRequest)
 {
   *aDomRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->GetRoamingPreference(mClientId, GetOwner(), aDomRequest);
+  return mProvider->GetRoamingPreference(GetOwner(), aDomRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::SetVoicePrivacyMode(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
 {
   *aDomRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SetVoicePrivacyMode(mClientId, GetOwner(), aEnabled, aDomRequest);
+  return mProvider->SetVoicePrivacyMode(GetOwner(), aEnabled, aDomRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetVoicePrivacyMode(nsIDOMDOMRequest** aDomRequest)
 {
   *aDomRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->GetVoicePrivacyMode(mClientId, GetOwner(), aDomRequest);
+  return mProvider->GetVoicePrivacyMode(GetOwner(), aDomRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::SendMMI(const nsAString& aMMIString,
                           nsIDOMDOMRequest** aRequest)
 {
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SendMMI(mClientId, GetOwner(), aMMIString, aRequest);
+  return mProvider->SendMMI(GetOwner(), aMMIString, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::CancelMMI(nsIDOMDOMRequest** aRequest)
 {
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->CancelMMI(mClientId, GetOwner(),aRequest);
+  return mProvider->CancelMMI(GetOwner(), aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetCallForwardingOption(uint16_t aReason,
                                           nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->GetCallForwardingOption(mClientId, GetOwner(), aReason, aRequest);
+  return mProvider->GetCallForwardingOption(GetOwner(), aReason, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::SetCallForwardingOption(nsIDOMMozMobileCFInfo* aCFInfo,
                                           nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SetCallForwardingOption(mClientId, GetOwner(), aCFInfo, aRequest);
+  return mProvider->SetCallForwardingOption(GetOwner(), aCFInfo, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetCallBarringOption(const JS::Value& aOption,
                                        nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->GetCallBarringOption(mClientId, GetOwner(), aOption, aRequest);
+  return mProvider->GetCallBarringOption(GetOwner(), aOption, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::SetCallBarringOption(const JS::Value& aOption,
                                        nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SetCallBarringOption(mClientId, GetOwner(), aOption, aRequest);
+  return mProvider->SetCallBarringOption(GetOwner(), aOption, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::ChangeCallBarringPassword(const JS::Value& aInfo,
                                             nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->ChangeCallBarringPassword(mClientId, GetOwner(), aInfo, aRequest);
+  return mProvider->ChangeCallBarringPassword(GetOwner(), aInfo, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetCallWaitingOption(nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->GetCallWaitingOption(mClientId, GetOwner(), aRequest);
+  return mProvider->GetCallWaitingOption(GetOwner(), aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::SetCallWaitingOption(bool aEnabled,
                                        nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SetCallWaitingOption(mClientId, GetOwner(), aEnabled, aRequest);
+  return mProvider->SetCallWaitingOption(GetOwner(), aEnabled, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::GetCallingLineIdRestriction(nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->GetCallingLineIdRestriction(mClientId, GetOwner(), aRequest);
+  return mProvider->GetCallingLineIdRestriction(GetOwner(), aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::SetCallingLineIdRestriction(unsigned short aClirMode,
                                               nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->SetCallingLineIdRestriction(mClientId, GetOwner(), aClirMode, aRequest);
+  return mProvider->SetCallingLineIdRestriction(GetOwner(), aClirMode, aRequest);
 }
 
 NS_IMETHODIMP
 MobileConnection::ExitEmergencyCbMode(nsIDOMDOMRequest** aRequest)
 {
   *aRequest = nullptr;
 
   if (!CheckPermission("mobileconnection")) {
     return NS_OK;
   }
 
   if (!mProvider) {
     return NS_ERROR_FAILURE;
   }
 
-  return mProvider->ExitEmergencyCbMode(mClientId, GetOwner(), aRequest);
+  return mProvider->ExitEmergencyCbMode(GetOwner(), aRequest);
 }
 
 // nsIMobileConnectionListener
 
 NS_IMETHODIMP
 MobileConnection::NotifyVoiceChanged()
 {
   if (!CheckPermission("mobileconnection")) {
--- a/dom/network/src/MobileConnection.h
+++ b/dom/network/src/MobileConnection.h
@@ -43,18 +43,16 @@ public:
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MobileConnection,
                                            nsDOMEventTargetHelper)
 
 private:
   nsCOMPtr<nsIMobileConnectionProvider> mProvider;
   nsRefPtr<Listener> mListener;
   nsWeakPtr mWindow;
 
-  uint32_t mClientId;
-
   bool CheckPermission(const char* type);
 };
 
 } // namespace network
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_network_MobileConnection_h
--- a/dom/phonenumberutils/PhoneNumberUtils.jsm
+++ b/dom/phonenumberutils/PhoneNumberUtils.jsm
@@ -39,18 +39,17 @@ this.PhoneNumberUtils = {
   _mcc: '724',
 
   getCountryName: function getCountryName() {
     let mcc;
     let countryName;
 
 #ifdef MOZ_B2G_RIL
     // Get network mcc
-    // TODO: Bug 926740 - PhoneNumberUtils for multisim
-    let voice = mobileConnection.getVoiceConnectionInfo(0);
+    let voice = mobileConnection.voiceConnectionInfo;
     if (voice && voice.network && voice.network.mcc) {
       mcc = voice.network.mcc;
     }
 
     // Get SIM mcc
     let iccInfo = icc.iccInfo;
     if (!mcc && iccInfo && iccInfo.mcc) {
       mcc = iccInfo.mcc;
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -83,23 +83,23 @@ const RIL_IPC_MSG_NAMES = [
   "RIL:CardLockResult",
   "RIL:CardLockRetryCount",
   "RIL:USSDReceived",
   "RIL:SendMMI",
   "RIL:CancelMMI",
   "RIL:StkCommand",
   "RIL:StkSessionEnd",
   "RIL:DataError",
-  "RIL:SetCallForwardingOptions",
-  "RIL:GetCallForwardingOptions",
-  "RIL:SetCallBarringOptions",
-  "RIL:GetCallBarringOptions",
+  "RIL:SetCallForwardingOption",
+  "RIL:GetCallForwardingOption",
+  "RIL:SetCallBarringOption",
+  "RIL:GetCallBarringOption",
   "RIL:ChangeCallBarringPassword",
-  "RIL:SetCallWaitingOptions",
-  "RIL:GetCallWaitingOptions",
+  "RIL:SetCallWaitingOption",
+  "RIL:GetCallWaitingOption",
   "RIL:SetCallingLineIdRestriction",
   "RIL:GetCallingLineIdRestriction",
   "RIL:CellBroadcastReceived",
   "RIL:CfStateChanged",
   "RIL:IccOpenChannel",
   "RIL:IccCloseChannel",
   "RIL:IccExchangeAPDU",
   "RIL:ReadIccContacts",
@@ -379,23 +379,23 @@ CellBroadcastEtwsInfo.prototype = {
 
   // nsIDOMMozCellBroadcastEtwsInfo
 
   warningType: null,
   emergencyUserAlert: null,
   popup: null
 };
 
-function CallBarringOptions(options) {
-  this.program = options.program;
-  this.enabled = options.enabled;
-  this.password = options.password;
-  this.serviceClass = options.serviceClass;
+function CallBarringOption(option) {
+  this.program = option.program;
+  this.enabled = option.enabled;
+  this.password = option.password;
+  this.serviceClass = option.serviceClass;
 }
-CallBarringOptions.prototype = {
+CallBarringOption.prototype = {
   __exposedProps__ : {program: 'r',
                       enabled: 'r',
                       password: 'r',
                       serviceClass: 'r'}
 };
 
 function DOMMMIResult(result) {
   this.serviceCode = result.serviceCode;
@@ -444,40 +444,27 @@ IccCardLockError.prototype = {
   __init: function(lockType, errorMsg, retryCount) {
     this.__DOM_IMPL__.init(errorMsg);
     this.lockType = lockType;
     this.retryCount = retryCount;
   },
 };
 
 function RILContentHelper() {
-
-  this.numClients = gNumRadioInterfaces;
-  debug("Number of clients: " + this.numClients);
-
-  this.rilContexts = [];
-  for (let clientId = 0; clientId < this.numClients; clientId++) {
-    this.rilContexts[clientId] = {
-      cardState:            RIL.GECKO_CARDSTATE_UNKNOWN,
-      networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
-      iccInfo:              null,
-      voiceConnectionInfo:  new MobileConnectionInfo(),
-      dataConnectionInfo:   new MobileConnectionInfo()
-    };
-  }
+  this.rilContext = {
+    cardState:            RIL.GECKO_CARDSTATE_UNKNOWN,
+    networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
+    iccInfo:              null,
+    voiceConnectionInfo:  new MobileConnectionInfo(),
+    dataConnectionInfo:   new MobileConnectionInfo()
+  };
   this.voicemailInfo = new VoicemailInfo();
 
   this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
   this._windowsMap = [];
-  this._selectingNetworks = [];
-  this._mobileConnectionListeners = [];
-  this._cellBroadcastListeners = [];
-  this._voicemailListeners = [];
-  this._iccListeners = [];
-
   Services.obs.addObserver(this, "xpcom-shutdown", false);
 }
 
 RILContentHelper.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionProvider,
                                          Ci.nsICellBroadcastProvider,
@@ -533,138 +520,123 @@ RILContentHelper.prototype = {
     this.updateInfo(srcNetwork, network);
   },
 
   /**
    * We need to consider below cases when update iccInfo:
    * 1. Should clear iccInfo to null if there is no card detected.
    * 2. Need to create corresponding object based on iccType.
    */
-  updateIccInfo: function updateIccInfo(clientId, newInfo) {
-    let rilContext = this.rilContexts[clientId];
-
+  updateIccInfo: function updateIccInfo(newInfo) {
     // Card is not detected, clear iccInfo to null.
     if (!newInfo || !newInfo.iccType) {
-      rilContext.iccInfo = null;
+      this.rilContext.iccInfo = null;
       return;
     }
 
     // If iccInfo is null, new corresponding object based on iccType.
-    if (!rilContext.iccInfo) {
+    if (!this.rilContext.iccInfo) {
       if (newInfo.iccType === "ruim" || newInfo.iccType === "csim") {
-        rilContext.iccInfo = new CdmaIccInfo();
+        this.rilContext.iccInfo = new CdmaIccInfo();
       } else {
-        rilContext.iccInfo = new GsmIccInfo();
+        this.rilContext.iccInfo = new GsmIccInfo();
       }
     }
 
-    this.updateInfo(newInfo, rilContext.iccInfo);
+    this.updateInfo(newInfo, this.rilContext.iccInfo);
   },
 
   _windowsMap: null,
 
-  rilContexts: null,
+  rilContext: null,
 
-  getRilContext: function getRilContext(clientId) {
-    // Update ril contexts by sending IPC message to chrome only when the first
+  getRilContext: function getRilContext() {
+    // Update ril context by sending IPC message to chrome only when the first
     // time we require it. The information will be updated by following info
     // changed messages.
-    this.getRilContext = function getRilContext(clientId) {
-      return this.rilContexts[clientId];
+    this.getRilContext = function getRilContext() {
+      return this.rilContext;
     };
 
-    for (let cId = 0; cId < this.numClients; cId++) {
-      let rilContext =
-        cpmm.sendSyncMessage("RIL:GetRilContext", {clientId: cId})[0];
-      if (!rilContext) {
-        debug("Received null rilContext from chrome process.");
-        continue;
-      }
-      this.rilContexts[cId].cardState = rilContext.cardState;
-      this.rilContexts[cId].networkSelectionMode = rilContext.networkSelectionMode;
-      this.updateIccInfo(cId, rilContext.iccInfo);
-      this.updateConnectionInfo(rilContext.voice, this.rilContexts[cId].voiceConnectionInfo);
-      this.updateConnectionInfo(rilContext.data, this.rilContexts[cId].dataConnectionInfo);
+    let rilContext =
+      cpmm.sendSyncMessage("RIL:GetRilContext", {clientId: 0})[0];
+    if (!rilContext) {
+      debug("Received null rilContext from chrome process.");
+      return;
     }
+    this.rilContext.cardState = rilContext.cardState;
+    this.rilContext.networkSelectionMode = rilContext.networkSelectionMode;
+    this.updateIccInfo(rilContext.iccInfo);
+    this.updateConnectionInfo(rilContext.voice, this.rilContext.voiceConnectionInfo);
+    this.updateConnectionInfo(rilContext.data, this.rilContext.dataConnectionInfo);
 
-    return this.rilContexts[clientId];
-  },
-
-  /**
-   * nsIIccProvider
-   */
-
-  get iccInfo() {
-    //TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
-    let context = this.getRilContext(0);
-    return context && context.iccInfo;
-  },
-
-  get cardState() {
-    //TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
-    let context = this.getRilContext(0);
-    return context && context.cardState;
+    return this.rilContext;
   },
 
   /**
    * nsIMobileConnectionProvider
    */
 
-  getVoiceConnectionInfo: function getVoiceConnectionInfo(clientId) {
-    let context = this.getRilContext(clientId);
+  get iccInfo() {
+    let context = this.getRilContext();
+    return context && context.iccInfo;
+  },
+
+  get voiceConnectionInfo() {
+    let context = this.getRilContext();
     return context && context.voiceConnectionInfo;
   },
 
-  getDataConnectionInfo: function getDataConnectionInfo(clientId) {
-    let context = this.getRilContext(clientId);
+  get dataConnectionInfo() {
+    let context = this.getRilContext();
     return context && context.dataConnectionInfo;
   },
 
-  getIccId: function getIccId(clientId) {
-    let context = this.getRilContext(clientId);
-    return context && context.iccInfo.iccid;
+  get cardState() {
+    let context = this.getRilContext();
+    return context && context.cardState;
   },
 
-  getNetworkSelectionMode: function getNetworkSelectionMode(clientId) {
-    let context = this.getRilContext(clientId);
+  get networkSelectionMode() {
+    let context = this.getRilContext();
     return context && context.networkSelectionMode;
   },
 
   /**
-   * The networks that are currently trying to be selected (or "automatic").
-   * This helps ensure that only one network per client is selected at a time.
+   * The network that is currently trying to be selected (or "automatic").
+   * This helps ensure that only one network is selected at a time.
    */
-  _selectingNetworks: null,
+  _selectingNetwork: null,
 
-  getNetworks: function getNetworks(clientId, window) {
+  getNetworks: function getNetworks(window) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId
       }
     });
     return request;
   },
 
-  selectNetwork: function selectNetwork(clientId, window, network) {
+  selectNetwork: function selectNetwork(window, network) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
-    if (this._selectingNetworks[clientId]) {
-      throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
+    if (this._selectingNetwork) {
+      throw new Error("Already selecting a network: " + this._selectingNetwork);
     }
 
     if (!network) {
       throw new Error("Invalid network provided: " + network);
     }
 
     if (isNaN(parseInt(network.mnc, 10))) {
       throw new Error("Invalid network MNC: " + network.mnc);
@@ -672,143 +644,143 @@ RILContentHelper.prototype = {
 
     if (isNaN(parseInt(network.mcc, 10))) {
       throw new Error("Invalid network MCC: " + network.mcc);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
-    if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL &&
-        this.rilContexts[clientId].voiceConnectionInfo.network === network) {
+    if (this.rilContext.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL &&
+        this.rilContext.voiceConnectionInfo.network === network) {
 
       // Already manually selected this network, so schedule
       // onsuccess to be fired on the next tick
       this.dispatchFireRequestSuccess(requestId, null);
       return request;
     }
 
-    this._selectingNetworks[clientId] = network;
+    this._selectingNetwork = network;
 
     cpmm.sendAsyncMessage("RIL:SelectNetwork", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId,
         mnc: network.mnc,
         mcc: network.mcc
       }
     });
 
     return request;
   },
 
-  selectNetworkAutomatically: function selectNetworkAutomatically(clientId, window) {
+  selectNetworkAutomatically: function selectNetworkAutomatically(window) {
 
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
-    if (this._selectingNetworks[clientId]) {
-      throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
+    if (this._selectingNetwork) {
+      throw new Error("Already selecting a network: " + this._selectingNetwork);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
-    if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
+    if (this.rilContext.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
       // Already using automatic selection mode, so schedule
       // onsuccess to be be fired on the next tick
       this.dispatchFireRequestSuccess(requestId, null);
       return request;
     }
 
-    this._selectingNetworks[clientId] = "automatic";
+    this._selectingNetwork = "automatic";
     cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId
       }
     });
     return request;
   },
 
-  setRoamingPreference: function setRoamingPreference(clientId, window, mode) {
+  setRoamingPreference: function setRoamingPreference(window, mode) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     if (!mode) {
       this.dispatchFireRequestError(requestId,
                                     RIL.GECKO_ERROR_INVALID_PARAMETER);
       return request;
     }
 
     cpmm.sendAsyncMessage("RIL:SetRoamingPreference", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId,
         mode: mode
       }
     });
     return request;
   },
 
-  getRoamingPreference: function getRoamingPreference(clientId, window) {
+  getRoamingPreference: function getRoamingPreference(window) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:GetRoamingPreference", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId
       }
     });
     return request;
   },
 
-  setVoicePrivacyMode: function setVoicePrivacyMode(clientId, window, enabled) {
+  setVoicePrivacyMode: function setVoicePrivacyMode(window, enabled) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:SetVoicePrivacyMode", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId,
         enabled: enabled
       }
     });
     return request;
   },
 
-  getVoicePrivacyMode: function getVoicePrivacyMode(clientId, window) {
+  getVoicePrivacyMode: function getVoicePrivacyMode(window) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:GetVoicePrivacyMode", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId
       }
     });
     return request;
   },
 
   getCardLockState: function getCardLockState(window, lockType) {
@@ -874,48 +846,48 @@ RILContentHelper.prototype = {
       data: {
         lockType: lockType,
         requestId: requestId
       }
     });
     return request;
   },
 
-  sendMMI: function sendMMI(clientId, window, mmi) {
+  sendMMI: function sendMMI(window, mmi) {
     debug("Sending MMI " + mmi);
     if (!window) {
       throw Components.Exception("Can't get window object",
                                  Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
     // We need to save the global window to get the proper MMIError
     // constructor once we get the reply from the parent process.
     this._windowsMap[requestId] = window;
 
     cpmm.sendAsyncMessage("RIL:SendMMI", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         mmi: mmi,
         requestId: requestId
       }
     });
     return request;
   },
 
-  cancelMMI: function cancelMMI(clientId, window) {
+  cancelMMI: function cancelMMI(window) {
     debug("Cancel MMI");
     if (!window) {
       throw Components.Exception("Can't get window object",
                                  Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
     cpmm.sendAsyncMessage("RIL:CancelMMI", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId
       }
     });
     return request;
   },
 
   sendStkResponse: function sendStkResponse(window, command, response) {
@@ -1099,128 +1071,128 @@ RILContentHelper.prototype = {
         contact: iccContact,
         pin2: pin2
       }
     });
 
     return request;
   },
 
-  getCallForwardingOption: function getCallForwardingOption(clientId, window, reason) {
+  getCallForwardingOption: function getCallForwardingOption(window, reason) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     if (!this._isValidCFReason(reason)){
       this.dispatchFireRequestError(requestId,
                                     RIL.GECKO_ERROR_INVALID_PARAMETER);
       return request;
     }
 
-    cpmm.sendAsyncMessage("RIL:GetCallForwardingOptions", {
-      clientId: clientId,
+    cpmm.sendAsyncMessage("RIL:GetCallForwardingOption", {
+      clientId: 0,
       data: {
         requestId: requestId,
         reason: reason
       }
     });
 
     return request;
   },
 
-  setCallForwardingOption: function setCallForwardingOption(clientId, window, cfInfo) {
+  setCallForwardingOption: function setCallForwardingOption(window, cfInfo) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     if (!cfInfo ||
         !this._isValidCFReason(cfInfo.reason) ||
         !this._isValidCFAction(cfInfo.action)){
       this.dispatchFireRequestError(requestId,
                                     RIL.GECKO_ERROR_INVALID_PARAMETER);
       return request;
     }
 
-    cpmm.sendAsyncMessage("RIL:SetCallForwardingOptions", {
-      clientId: clientId,
+    cpmm.sendAsyncMessage("RIL:SetCallForwardingOption", {
+      clientId: 0,
       data: {
         requestId: requestId,
         active: cfInfo.active,
         action: cfInfo.action,
         reason: cfInfo.reason,
         number: cfInfo.number,
         timeSeconds: cfInfo.timeSeconds
       }
     });
 
     return request;
   },
 
-  getCallBarringOption: function getCallBarringOption(clientId, window, option) {
+  getCallBarringOption: function getCallBarringOption(window, option) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     if (DEBUG) debug("getCallBarringOption: " + JSON.stringify(option));
-    if (!this._isValidCallBarringOptions(option)) {
+    if (!this._isValidCallBarringOption(option)) {
       this.dispatchFireRequestError(requestId,
                                     RIL.GECKO_ERROR_INVALID_PARAMETER);
       return request;
     }
 
-    cpmm.sendAsyncMessage("RIL:GetCallBarringOptions", {
-      clientId: clientId,
+    cpmm.sendAsyncMessage("RIL:GetCallBarringOption", {
+      clientId: 0,
       data: {
         requestId: requestId,
         program: option.program,
         password: option.password,
         serviceClass: option.serviceClass
       }
     });
     return request;
   },
 
-  setCallBarringOption: function setCallBarringOption(clientId, window, option) {
+  setCallBarringOption: function setCallBarringOption(window, option) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     if (DEBUG) debug("setCallBarringOption: " + JSON.stringify(option));
-    if (!this._isValidCallBarringOptions(option, true)) {
+    if (!this._isValidCallBarringOption(option, true)) {
       this.dispatchFireRequestError(requestId,
                                     RIL.GECKO_ERROR_INVALID_PARAMETER);
       return request;
     }
 
-    cpmm.sendAsyncMessage("RIL:SetCallBarringOptions", {
-      clientId: clientId,
+    cpmm.sendAsyncMessage("RIL:SetCallBarringOption", {
+      clientId: 0,
       data: {
         requestId: requestId,
         program: option.program,
         enabled: option.enabled,
         password: option.password,
         serviceClass: option.serviceClass
       }
     });
     return request;
   },
 
-  changeCallBarringPassword: function changeCallBarringPassword(clientId, window, info) {
+  changeCallBarringPassword: function changeCallBarringPassword(window, info) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     // Checking valid PIN for supplementary services. See TS.22.004 clause 5.2.
@@ -1228,109 +1200,109 @@ RILContentHelper.prototype = {
         info.newPin == null || !info.newPin.match(/^\d{4}$/)) {
       this.dispatchFireRequestError(requestId, "InvalidPassword");
       return request;
     }
 
     if (DEBUG) debug("changeCallBarringPassword: " + JSON.stringify(info));
     info.requestId = requestId;
     cpmm.sendAsyncMessage("RIL:ChangeCallBarringPassword", {
-      clientId: clientId,
+      clientId: 0,
       data: info
     });
 
     return request;
   },
 
-  getCallWaitingOption: function getCallWaitingOption(clientId, window) {
+  getCallWaitingOption: function getCallWaitingOption(window) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
-    cpmm.sendAsyncMessage("RIL:GetCallWaitingOptions", {
-      clientId: clientId,
+    cpmm.sendAsyncMessage("RIL:GetCallWaitingOption", {
+      clientId: 0,
       data: {
         requestId: requestId
       }
     });
 
     return request;
   },
 
-  setCallWaitingOption: function setCallWaitingOption(clientId, window, enabled) {
+  setCallWaitingOption: function setCallWaitingOption(window, enabled) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
-    cpmm.sendAsyncMessage("RIL:SetCallWaitingOptions", {
-      clientId: clientId,
+    cpmm.sendAsyncMessage("RIL:SetCallWaitingOption", {
+      clientId: 0,
       data: {
         requestId: requestId,
         enabled: enabled
       }
     });
 
     return request;
   },
 
-  getCallingLineIdRestriction: function getCallingLineIdRestriction(clientId, window) {
+  getCallingLineIdRestriction: function getCallingLineIdRestriction(window) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:GetCallingLineIdRestriction", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId
       }
     });
 
     return request;
   },
 
   setCallingLineIdRestriction:
-    function setCallingLineIdRestriction(clientId, window, clirMode) {
+    function setCallingLineIdRestriction(window, clirMode) {
 
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:SetCallingLineIdRestriction", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId,
         clirMode: clirMode
       }
     });
 
     return request;
   },
 
-  exitEmergencyCbMode: function exitEmergencyCbMode(clientId, window) {
+  exitEmergencyCbMode: function exitEmergencyCbMode(window) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     let request = Services.DOMRequest.createRequest(window);
     let requestId = this.getRequestId(request);
 
     cpmm.sendAsyncMessage("RIL:ExitEmergencyCbMode", {
-      clientId: clientId,
+      clientId: 0,
       data: {
         requestId: requestId,
       }
     });
 
     return request;
   },
 
@@ -1357,93 +1329,81 @@ RILContentHelper.prototype = {
   },
   get voicemailNumber() {
     return this.getVoicemailInfo().number;
   },
   get voicemailDisplayName() {
     return this.getVoicemailInfo().displayName;
   },
 
-  registerListener: function registerListener(listenerType, clientId, listener) {
-    if (!this[listenerType]) {
-      return;
-    }
-    let listeners = this[listenerType][clientId];
+  registerListener: function registerListener(listenerType, listener) {
+    let listeners = this[listenerType];
     if (!listeners) {
-      listeners = this[listenerType][clientId] = [];
+      listeners = this[listenerType] = [];
     }
 
     if (listeners.indexOf(listener) != -1) {
       throw new Error("Already registered this listener!");
     }
 
     listeners.push(listener);
     if (DEBUG) debug("Registered " + listenerType + " listener: " + listener);
   },
 
-  unregisterListener: function unregisterListener(listenerType, clientId, listener) {
-    if (!this[listenerType]) {
-      return;
-    }
-    let listeners = this[listenerType][clientId];
+  unregisterListener: function unregisterListener(listenerType, listener) {
+    let listeners = this[listenerType];
     if (!listeners) {
       return;
     }
 
     let index = listeners.indexOf(listener);
     if (index != -1) {
       listeners.splice(index, 1);
       if (DEBUG) debug("Unregistered listener: " + listener);
     }
   },
 
-  registerMobileConnectionMsg: function registerMobileConnectionMsg(clientId, listener) {
+  registerMobileConnectionMsg: function registerMobileConnectionMsg(listener) {
     debug("Registering for mobile connection related messages");
-    this.registerListener("_mobileConnectionListeners", clientId, listener);
+    this.registerListener("_mobileConnectionListeners", listener);
     cpmm.sendAsyncMessage("RIL:RegisterMobileConnectionMsg");
   },
 
-  unregisterMobileConnectionMsg: function unregisteMobileConnectionMsg(clientId, listener) {
-    this.unregisterListener("_mobileConnectionListeners", clientId, listener);
+  unregisterMobileConnectionMsg: function unregisteMobileConnectionMsg(listener) {
+    this.unregisterListener("_mobileConnectionListeners", listener);
   },
 
   registerVoicemailMsg: function registerVoicemailMsg(listener) {
     debug("Registering for voicemail-related messages");
-    //TODO: Bug 814634 - WebVoicemail API: support multiple sim cards.
-    this.registerListener("_voicemailListeners", 0, listener);
+    this.registerListener("_voicemailListeners", listener);
     cpmm.sendAsyncMessage("RIL:RegisterVoicemailMsg");
   },
 
   unregisterVoicemailMsg: function unregisteVoicemailMsg(listener) {
-    //TODO: Bug 814634 - WebVoicemail API: support multiple sim cards.
-    this.unregisterListener("_voicemailListeners", 0, listener);
+    this.unregisterListener("_voicemailListeners", listener);
   },
 
   registerCellBroadcastMsg: function registerCellBroadcastMsg(listener) {
     debug("Registering for Cell Broadcast related messages");
-    //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
-    this.registerListener("_cellBroadcastListeners", 0, listener);
+    this.registerListener("_cellBroadcastListeners", listener);
     cpmm.sendAsyncMessage("RIL:RegisterCellBroadcastMsg");
   },
 
   unregisterCellBroadcastMsg: function unregisterCellBroadcastMsg(listener) {
-    //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
-    this.unregisterListener("_cellBroadcastListeners", 0, listener);
+    this.unregisterListener("_cellBroadcastListeners", listener);
   },
 
   registerIccMsg: function registerIccMsg(listener) {
     debug("Registering for ICC related messages");
-    //TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
-    this.registerListener("_iccListeners", 0, listener);
+    this.registerListener("_iccListeners", listener);
     cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
   },
 
   unregisterIccMsg: function unregisterIccMsg(listener) {
-    //TODO: Bug 814637 - WebIccManager API: support multiple sim cards.
-    this.unregisterListener("_iccListeners", 0, listener);
+    this.unregisterListener("_iccListeners", listener);
   },
 
   // nsIObserver
 
   observe: function observe(subject, topic, data) {
     if (topic == "xpcom-shutdown") {
       this.destroyDOMRequestHelper();
       Services.obs.removeObserver(this, "xpcom-shutdown");
@@ -1513,72 +1473,64 @@ RILContentHelper.prototype = {
     Services.DOMRequest.fireDetailedError(request, detailedError);
   },
 
   receiveMessage: function receiveMessage(msg) {
     let request;
     debug("Received message '" + msg.name + "': " + JSON.stringify(msg.json));
 
     let data = msg.json.data;
-    let clientId = msg.json.clientId;
     switch (msg.name) {
       case "RIL:CardStateChanged":
-        if (this.rilContexts[clientId].cardState != data.cardState) {
-          this.rilContexts[clientId].cardState = data.cardState;
-          this._deliverEvent(clientId,
-                             "_iccListeners",
+        if (this.rilContext.cardState != data.cardState) {
+          this.rilContext.cardState = data.cardState;
+          this._deliverEvent("_iccListeners",
                              "notifyCardStateChanged",
                              null);
         }
         break;
       case "RIL:IccInfoChanged":
-        this.updateIccInfo(clientId, data);
-        this._deliverEvent(clientId,
-                           "_iccListeners",
-                           "notifyIccInfoChanged",
-                           null);
+        this.updateIccInfo(data);
+        this._deliverEvent("_iccListeners", "notifyIccInfoChanged", null);
         break;
       case "RIL:VoiceInfoChanged":
         this.updateConnectionInfo(data,
-                                  this.rilContexts[clientId].voiceConnectionInfo);
-        this._deliverEvent(clientId,
-                           "_mobileConnectionListeners",
+                                  this.rilContext.voiceConnectionInfo);
+        this._deliverEvent("_mobileConnectionListeners",
                            "notifyVoiceChanged",
                            null);
         break;
       case "RIL:DataInfoChanged":
         this.updateConnectionInfo(data,
-                                  this.rilContexts[clientId].dataConnectionInfo);
-        this._deliverEvent(clientId,
-                           "_mobileConnectionListeners",
+                                  this.rilContext.dataConnectionInfo);
+        this._deliverEvent("_mobileConnectionListeners",
                            "notifyDataChanged",
                            null);
         break;
       case "RIL:OtaStatusChanged":
-        this._deliverEvent(clientId,
-                           "_mobileConnectionListeners",
+        this._deliverEvent("_mobileConnectionListeners",
                            "notifyOtaStatusChanged",
                            [data]);
         break;
       case "RIL:GetAvailableNetworks":
         this.handleGetAvailableNetworks(data);
         break;
       case "RIL:NetworkSelectionModeChanged":
-        this.rilContexts[clientId].networkSelectionMode = data.mode;
+        this.rilContext.networkSelectionMode = data.mode;
         break;
       case "RIL:SelectNetwork":
-        this.handleSelectNetwork(clientId, data,
+        this.handleSelectNetwork(data,
                                  RIL.GECKO_NETWORK_SELECTION_MANUAL);
         break;
       case "RIL:SelectNetworkAuto":
-        this.handleSelectNetwork(clientId, data,
+        this.handleSelectNetwork(data,
                                  RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
         break;
       case "RIL:VoicemailNotification":
-        this.handleVoicemailNotification(clientId, data);
+        this.handleVoicemailNotification(data);
         break;
       case "RIL:VoicemailInfoChanged":
         this.updateInfo(data, this.voicemailInfo);
         break;
       case "RIL:CardLockResult": {
         let requestId = data.requestId;
         let requestWindow = this._windowsMap[requestId];
         delete this._windowsMap[requestId];
@@ -1603,31 +1555,30 @@ RILContentHelper.prototype = {
         if (data.success) {
           let result = new MobileIccCardLockRetryCount(data);
           this.fireRequestSuccess(data.requestId, result);
         } else {
           this.fireRequestError(data.requestId, data.errorMsg);
         }
         break;
       case "RIL:USSDReceived":
-        this._deliverEvent(clientId,
-                           "_mobileConnectionListeners",
+        this._deliverEvent("_mobileConnectionListeners",
                            "notifyUssdReceived",
                            [data.message, data.sessionEnded]);
         break;
       case "RIL:SendMMI":
       case "RIL:CancelMMI":
         this.handleSendCancelMMI(data);
         break;
       case "RIL:StkCommand":
-        this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
+        this._deliverEvent("_iccListeners", "notifyStkCommand",
                            [JSON.stringify(data)]);
         break;
       case "RIL:StkSessionEnd":
-        this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
+        this._deliverEvent("_iccListeners", "notifyStkSessionEnd", null);
         break;
       case "RIL:IccOpenChannel":
         this.handleSimpleRequest(data.requestId, data.errorMsg,
                                  data.channel);
         break;
       case "RIL:IccCloseChannel":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
@@ -1636,77 +1587,74 @@ RILContentHelper.prototype = {
         break;
       case "RIL:ReadIccContacts":
         this.handleReadIccContacts(data);
         break;
       case "RIL:UpdateIccContact":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
       case "RIL:DataError":
-        this.updateConnectionInfo(data, this.rilContexts[clientId].dataConnectionInfo);
-        this._deliverEvent(clientId, "_mobileConnectionListeners", "notifyDataError",
+        this.updateConnectionInfo(data, this.rilContext.dataConnectionInfo);
+        this._deliverEvent("_mobileConnectionListeners", "notifyDataError",
                            [data.errorMsg]);
         break;
-      case "RIL:GetCallForwardingOptions":
-        this.handleGetCallForwardingOptions(data);
+      case "RIL:GetCallForwardingOption":
+        this.handleGetCallForwardingOption(data);
         break;
-      case "RIL:SetCallForwardingOptions":
+      case "RIL:SetCallForwardingOption":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
-      case "RIL:GetCallBarringOptions":
-        this.handleGetCallBarringOptions(data);
+      case "RIL:GetCallBarringOption":
+        this.handleGetCallBarringOption(data);
         break;
-      case "RIL:SetCallBarringOptions":
+      case "RIL:SetCallBarringOption":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
       case "RIL:ChangeCallBarringPassword":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
-      case "RIL:GetCallWaitingOptions":
+      case "RIL:GetCallWaitingOption":
         this.handleSimpleRequest(data.requestId, data.errorMsg,
                                  data.enabled);
         break;
-      case "RIL:SetCallWaitingOptions":
+      case "RIL:SetCallWaitingOption":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
       case "RIL:CfStateChanged":
-        this._deliverEvent(clientId,
-                           "_mobileConnectionListeners",
+        this._deliverEvent("_mobileConnectionListeners",
                            "notifyCFStateChange",
                            [data.success, data.action,
                             data.reason, data.number,
                             data.timeSeconds, data.serviceClass]);
         break;
       case "RIL:GetCallingLineIdRestriction":
         this.handleGetCallingLineIdRestriction(data);
         break;
       case "RIL:SetCallingLineIdRestriction":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
       case "RIL:CellBroadcastReceived": {
         let message = new CellBroadcastMessage(data);
-        this._deliverEvent(clientId,
-                           "_cellBroadcastListeners",
+        this._deliverEvent("_cellBroadcastListeners",
                            "notifyMessageReceived",
                            [message]);
         break;
       }
       case "RIL:SetRoamingPreference":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
       case "RIL:GetRoamingPreference":
         this.handleSimpleRequest(data.requestId, data.errorMsg,
                                  data.mode);
         break;
       case "RIL:ExitEmergencyCbMode":
         this.handleExitEmergencyCbMode(data);
         break;
       case "RIL:EmergencyCbModeChanged":
-        this._deliverEvent(clientId,
-                           "_mobileConnectionListeners",
+        this._deliverEvent("_mobileConnectionListeners",
                            "notifyEmergencyCbModeChanged",
                            [data.active, data.timeoutMs]);
         break;
       case "RIL:SetVoicePrivacyMode":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
       case "RIL:GetVoicePrivacyMode":
         this.handleSimpleRequest(data.requestId, data.errorMsg,
@@ -1737,19 +1685,19 @@ RILContentHelper.prototype = {
       let info = new MobileNetworkInfo();
       this.updateInfo(network, info);
       networks[i] = info;
     }
 
     this.fireRequestSuccess(message.requestId, networks);
   },
 
-  handleSelectNetwork: function handleSelectNetwork(clientId, message, mode) {
-    this._selectingNetworks[clientId] = null;
-    this.rilContexts[clientId].networkSelectionMode = mode;
+  handleSelectNetwork: function handleSelectNetwork(message, mode) {
+    this._selectingNetwork = null;
+    this.rilContext.networkSelectionMode = mode;
 
     if (message.errorMsg) {
       this.fireRequestError(message.requestId, message.errorMsg);
     } else {
       this.fireRequestSuccess(message.requestId, null);
     }
   },
 
@@ -1788,18 +1736,17 @@ RILContentHelper.prototype = {
       contact.id = message.iccid + c.recordId;
       return contact;
     });
 
     this.fireRequestSuccess(message.requestId,
                             ObjectWrapper.wrap(result, window));
   },
 
-  handleVoicemailNotification: function handleVoicemailNotification(clientId, message) {
-    // TODO: Bug 818352 - B2G Multi-SIM: voicemail - add subscription id in nsIRILContentHelper
+  handleVoicemailNotification: function handleVoicemailNotification(message) {
     let changed = false;
     if (!this.voicemailStatus) {
       this.voicemailStatus = new VoicemailStatus();
     }
 
     if (this.voicemailStatus.hasMessages != message.active) {
       changed = true;
       this.voicemailStatus.hasMessages = message.active;
@@ -1819,48 +1766,47 @@ RILContentHelper.prototype = {
     }
 
     if (this.voicemailStatus.returnMessage != message.returnMessage) {
       changed = true;
       this.voicemailStatus.returnMessage = message.returnMessage;
     }
 
     if (changed) {
-      this._deliverEvent(clientId,
-                         "_voicemailListeners",
+      this._deliverEvent("_voicemailListeners",
                          "notifyStatusChanged",
                          [this.voicemailStatus]);
     }
   },
 
   _cfRulesToMobileCfInfo: function _cfRulesToMobileCfInfo(rules) {
     for (let i = 0; i < rules.length; i++) {
       let rule = rules[i];
       let info = new MobileCFInfo();
       this.updateInfo(rule, info);
       rules[i] = info;
     }
   },
 
-  handleGetCallForwardingOptions: function handleGetCallForwardingOptions(message) {
+  handleGetCallForwardingOption: function handleGetCallForwardingOption(message) {
     if (message.errorMsg) {
       this.fireRequestError(message.requestId, message.errorMsg);
       return;
     }
 
     this._cfRulesToMobileCfInfo(message.rules);
     this.fireRequestSuccess(message.requestId, message.rules);
   },
 
-  handleGetCallBarringOptions: function handleGetCallBarringOptions(message) {
+  handleGetCallBarringOption: function handleGetCallBarringOption(message) {
     if (!message.success) {
       this.fireRequestError(message.requestId, message.errorMsg);
     } else {
-      let options = new CallBarringOptions(message);
-      this.fireRequestSuccess(message.requestId, options);
+      let option = new CallBarringOption(message);
+      this.fireRequestSuccess(message.requestId, option);
     }
   },
 
   handleGetCallingLineIdRestriction:
     function handleGetCallingLineIdRestriction(message) {
     if (message.errorMsg) {
       this.fireRequestError(message.requestId, message.errorMsg);
       return;
@@ -1926,21 +1872,18 @@ RILContentHelper.prototype = {
       let mmiError = new requestWindow.DOMMMIError(result.serviceCode,
                                                    message.errorMsg,
                                                    null,
                                                    result.additionalInformation);
       Services.DOMRequest.fireDetailedError(request, mmiError);
     }
   },
 
-  _deliverEvent: function _deliverEvent(clientId, listenerType, name, args) {
-    if (!this[listenerType]) {
-      return;
-    }
-    let thisListeners = this[listenerType][clientId];
+  _deliverEvent: function _deliverEvent(listenerType, name, args) {
+    let thisListeners = this[listenerType];
     if (!thisListeners) {
       return;
     }
 
     let listeners = thisListeners.slice();
     for (let listener of listeners) {
       if (thisListeners.indexOf(listener) == -1) {
         continue;
@@ -2001,28 +1944,28 @@ RILContentHelper.prototype = {
       case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_INCOMING_ROAMING:
         return true;
       default:
         return false;
     }
   },
 
   /**
-   * Helper for guarding us against invalid options for call barring.
+   * Helper for guarding us against invalid option for call barring.
    */
-  _isValidCallBarringOptions:
-      function _isValidCallBarringOptions(options, usedForSetting) {
-    if (!options ||
-        options.serviceClass == null ||
-        !this._isValidCallBarringProgram(options.program)) {
+  _isValidCallBarringOption:
+      function _isValidCallBarringOption(option, usedForSetting) {
+    if (!option ||
+        option.serviceClass == null ||
+        !this._isValidCallBarringProgram(option.program)) {
       return false;
     }
 
-    // For setting callbarring options, |enabled| and |password| are required.
-    if (usedForSetting && (options.enabled == null || options.password == null)) {
+    // For setting callbarring option, |enabled| and |password| are required.
+    if (usedForSetting && (option.enabled == null || option.password == null)) {
       return false;
     }
 
     return true;
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper,
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -85,23 +85,23 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES
   "RIL:GetNumRadioInterfaces",
   "RIL:GetRilContext",
   "RIL:GetAvailableNetworks",
   "RIL:SelectNetwork",
   "RIL:SelectNetworkAuto",
   "RIL:SendMMI",
   "RIL:CancelMMI",
   "RIL:RegisterMobileConnectionMsg",
-  "RIL:SetCallForwardingOptions",
-  "RIL:GetCallForwardingOptions",
-  "RIL:SetCallBarringOptions",
-  "RIL:GetCallBarringOptions",
+  "RIL:SetCallForwardingOption",
+  "RIL:GetCallForwardingOption",
+  "RIL:SetCallBarringOption",
+  "RIL:GetCallBarringOption",
   "RIL:ChangeCallBarringPassword",
-  "RIL:SetCallWaitingOptions",
-  "RIL:GetCallWaitingOptions",
+  "RIL:SetCallWaitingOption",
+  "RIL:GetCallWaitingOption",
   "RIL:SetCallingLineIdRestriction",
   "RIL:GetCallingLineIdRestriction",
   "RIL:SetRoamingPreference",
   "RIL:GetRoamingPreference",
   "RIL:ExitEmergencyCbMode",
   "RIL:SetVoicePrivacyMode",
   "RIL:GetVoicePrivacyMode"
 ];
@@ -930,35 +930,35 @@ RadioInterface.prototype = {
         this.workerMessenger.sendWithIPCMessage(msg, "iccExchangeAPDU");
         break;
       case "RIL:ReadIccContacts":
         this.workerMessenger.sendWithIPCMessage(msg, "readICCContacts");
         break;
       case "RIL:UpdateIccContact":
         this.workerMessenger.sendWithIPCMessage(msg, "updateICCContact");
         break;
-      case "RIL:SetCallForwardingOptions":
-        this.setCallForwardingOptions(msg.target, msg.json.data);
+      case "RIL:SetCallForwardingOption":
+        this.setCallForwardingOption(msg.target, msg.json.data);
         break;
-      case "RIL:GetCallForwardingOptions":
+      case "RIL:GetCallForwardingOption":
         this.workerMessenger.sendWithIPCMessage(msg, "queryCallForwardStatus");
         break;
-      case "RIL:SetCallBarringOptions":
+      case "RIL:SetCallBarringOption":
         this.workerMessenger.sendWithIPCMessage(msg, "setCallBarring");
         break;
-      case "RIL:GetCallBarringOptions":
+      case "RIL:GetCallBarringOption":
         this.workerMessenger.sendWithIPCMessage(msg, "queryCallBarringStatus");
         break;
       case "RIL:ChangeCallBarringPassword":
         this.workerMessenger.sendWithIPCMessage(msg, "changeCallBarringPassword");
         break;
-      case "RIL:SetCallWaitingOptions":
+      case "RIL:SetCallWaitingOption":
         this.workerMessenger.sendWithIPCMessage(msg, "setCallWaiting");
         break;
-      case "RIL:GetCallWaitingOptions":
+      case "RIL:GetCallWaitingOption":
         this.workerMessenger.sendWithIPCMessage(msg, "queryCallWaiting");
         break;
       case "RIL:SetCallingLineIdRestriction":
         this.setCallingLineIdRestriction(msg.target, msg.json.data);
         break;
       case "RIL:GetCallingLineIdRestriction":
         this.workerMessenger.sendWithIPCMessage(msg, "getCLIR");
         break;
@@ -2401,22 +2401,22 @@ RadioInterface.prototype = {
       target.sendAsyncMessage("RIL:SendMMI", {
         clientId: this.clientId,
         data: response
       });
       return false;
     }).bind(this));
   },
 
-  setCallForwardingOptions: function setCallForwardingOptions(target, message) {
-    if (DEBUG) this.debug("setCallForwardingOptions: " + JSON.stringify(message));
+  setCallForwardingOption: function setCallForwardingOption(target, message) {
+    if (DEBUG) this.debug("setCallForwardingOption: " + JSON.stringify(message));
     message.serviceClass = RIL.ICC_SERVICE_CLASS_VOICE;
     this.workerMessenger.send("setCallForward", message, (function(response) {
       this._sendCfStateChanged(response);
-      target.sendAsyncMessage("RIL:SetCallForwardingOptions", {
+      target.sendAsyncMessage("RIL:SetCallForwardingOption", {
         clientId: this.clientId,
         data: response
       });
       return false;
     }).bind(this));
   },
 
   setCallingLineIdRestriction: function setCallingLineIdRestriction(target,
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -109,21 +109,21 @@ partial interface HTMLMediaElement {
   readonly attribute boolean mozAudioCaptured;
 
   // Mozilla extension: extra stream metadata information, used as part
   // of MozAudioAvailable events and the mozWriteAudio() method.  The
   // mozFrameBufferLength method allows for the size of the framebuffer
   // used within MozAudioAvailable events to be changed.  The new size must
   // be between 512 and 16384.  The default size, for a  media element with
   // audio is (mozChannels * 1024).
-  [GetterThrows]
+  [Pref="media.audio_data.enabled", GetterThrows]
   readonly attribute unsigned long mozChannels;
-  [GetterThrows]
+  [Pref="media.audio_data.enabled", GetterThrows]
   readonly attribute unsigned long mozSampleRate;
-  [Throws]
+  [Pref="media.audio_data.enabled", Throws]
            attribute unsigned long mozFrameBufferLength;
 
   // Mozilla extension: return embedded metadata from the stream as a
   // JSObject with key:value pairs for each tag. This can be used by
   // player interfaces to display the song title, artist, etc.
   [Throws]
   object? mozGetMetadata();
 
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -3,16 +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/. */
 
 #include <string.h>
 
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/Base64.h"
+#include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Selection.h"
 #include "mozilla/Util.h"
 #include "nsAString.h"
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
--- a/ipc/moz.build
+++ b/ipc/moz.build
@@ -9,17 +9,17 @@ DIRS += [
     'glue',
     'ipdl',
     'testshell',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     DIRS += ['ril']
 
-if CONFIG['MOZ_B2G_BT']:
+if CONFIG['MOZ_B2G_BT_BLUEZ']:
     DIRS += ['dbus']
 
 if CONFIG['MOZ_B2G_RIL'] or CONFIG['MOZ_B2G_BT']:
     DIRS += ['unixsocket', 'keystore']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DIRS += ['netd']
 
--- a/ipc/unixsocket/UnixSocket.h
+++ b/ipc/unixsocket/UnixSocket.h
@@ -7,17 +7,17 @@
 #ifndef mozilla_ipc_UnixSocket_h
 #define mozilla_ipc_UnixSocket_h
 
 
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
 #include <netinet/in.h>
-#ifdef MOZ_B2G_BT
+#ifdef MOZ_B2G_BT_BLUEZ
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/sco.h>
 #include <bluetooth/l2cap.h>
 #include <bluetooth/rfcomm.h>
 #endif
 #include <stdlib.h>
 #include "nsString.h"
 #include "nsAutoPtr.h"
@@ -26,17 +26,17 @@
 namespace mozilla {
 namespace ipc {
 
 union sockaddr_any {
   sockaddr_storage storage; // address-family only
   sockaddr_un un;
   sockaddr_in in;
   sockaddr_in6 in6;
-#ifdef MOZ_B2G_BT
+#ifdef MOZ_B2G_BT_BLUEZ
   sockaddr_sco sco;
   sockaddr_rc rc;
   sockaddr_l2 l2;
 #endif
   // ... others
 };
 
 class UnixSocketRawData
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -20,16 +20,47 @@
 #include "jspubtd.h"
 
 #include "js/HashTable.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 
 class nsISupports;      // Needed for ObjectPrivateVisitor.
 
+namespace JS {
+
+struct TabSizes
+{
+    enum Kind {
+        Objects,
+        Strings,
+        Private,
+        Other
+    };
+
+    TabSizes() { mozilla::PodZero(this); }
+
+    void add(Kind kind, size_t n) {
+        switch (kind) {
+            case Objects: objects  += n; break;
+            case Strings: strings  += n; break;
+            case Private: private_ += n; break;
+            case Other:   other    += n; break;
+            default:      MOZ_CRASH("bad TabSizes kind");
+        }
+    }
+
+    size_t objects;
+    size_t strings;
+    size_t private_;
+    size_t other;
+};
+
+} // namespace JS
+
 namespace js {
 
 // In memory reporting, we have concept of "sundries", line items which are too
 // small to be worth reporting individually.  Under some circumstances, a memory
 // reporter gets tossed into the sundries bucket if it's smaller than
 // MemoryReportingSundriesThreshold() bytes.
 //
 // We need to define this value here, rather than in the code which actually
@@ -52,42 +83,43 @@ struct InefficientNonFlatteningStringHas
 // without updating all the required methods.  So we define a single macro list
 // in each class to name the fields (and notable characteristics of them), and
 // then use the following macros to transform those lists into the required
 // methods.
 //
 // In some classes, one or more of the macro arguments aren't used.  We use '_'
 // for those.
 //
-#define DECL_SIZE(gc, mSize)                      size_t mSize;
-#define ZERO_SIZE(gc, mSize)                      mSize(0),
-#define COPY_OTHER_SIZE(gc, mSize)                mSize(other.mSize),
-#define ADD_OTHER_SIZE(gc, mSize)                 mSize += other.mSize;
-#define ADD_SIZE_TO_N_IF_LIVE_GC_THING(gc, mSize) n += (gc) ? mSize : 0;
+#define DECL_SIZE(kind, gc, mSize)                      size_t mSize;
+#define ZERO_SIZE(kind, gc, mSize)                      mSize(0),
+#define COPY_OTHER_SIZE(kind, gc, mSize)                mSize(other.mSize),
+#define ADD_OTHER_SIZE(kind, gc, mSize)                 mSize += other.mSize;
+#define ADD_SIZE_TO_N_IF_LIVE_GC_THING(kind, gc, mSize) n += (js::gc == js::IsLiveGCThing) ? mSize : 0;
+#define ADD_TO_TAB_SIZES(kind, gc, mSize)               sizes->add(JS::TabSizes::kind, mSize);
 
 // Used to annotate which size_t fields measure live GC things and which don't.
 enum {
     NotLiveGCThing = false,
     IsLiveGCThing = true
 };
 
 struct ZoneStatsPod
 {
 #define FOR_EACH_SIZE(macro) \
-    macro(NotLiveGCThing, gcHeapArenaAdmin) \
-    macro(NotLiveGCThing, unusedGCThings) \
-    macro(IsLiveGCThing,  lazyScriptsGCHeap) \
-    macro(NotLiveGCThing, lazyScriptsMallocHeap) \
-    macro(IsLiveGCThing,  ionCodesGCHeap) \
-    macro(IsLiveGCThing,  typeObjectsGCHeap) \
-    macro(NotLiveGCThing, typeObjectsMallocHeap) \
-    macro(NotLiveGCThing, typePool) \
-    macro(IsLiveGCThing,  stringsShortGCHeap) \
-    macro(IsLiveGCThing,  stringsNormalGCHeap) \
-    macro(NotLiveGCThing, stringsNormalMallocHeap)
+    macro(Other,   NotLiveGCThing, gcHeapArenaAdmin) \
+    macro(Other,   NotLiveGCThing, unusedGCThings) \
+    macro(Other,   IsLiveGCThing,  lazyScriptsGCHeap) \
+    macro(Other,   NotLiveGCThing, lazyScriptsMallocHeap) \
+    macro(Other,   IsLiveGCThing,  ionCodesGCHeap) \
+    macro(Other,   IsLiveGCThing,  typeObjectsGCHeap) \
+    macro(Other,   NotLiveGCThing, typeObjectsMallocHeap) \
+    macro(Other,   NotLiveGCThing, typePool) \
+    macro(Strings, IsLiveGCThing,  stringsShortGCHeap) \
+    macro(Strings, IsLiveGCThing,  stringsNormalGCHeap) \
+    macro(Strings, NotLiveGCThing, stringsNormalMallocHeap)
 
     ZoneStatsPod()
       : FOR_EACH_SIZE(ZERO_SIZE)
         extra()
     {}
 
     void add(const ZoneStatsPod &other) {
         FOR_EACH_SIZE(ADD_OTHER_SIZE)
@@ -96,71 +128,80 @@ struct ZoneStatsPod
 
     size_t sizeOfLiveGCThings() const {
         size_t n = 0;
         FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
         // Do nothing with |extra|.
         return n;
     }
 
+    void addToTabSizes(JS::TabSizes *sizes) const {
+        FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
+        // Do nothing with |extra|.
+    }
+
     FOR_EACH_SIZE(DECL_SIZE)
     void *extra;    // This field can be used by embedders.
 
 #undef FOR_EACH_SIZE
 };
 
 } // namespace js
 
 namespace JS {
 
 // Data for tracking memory usage of things hanging off objects.
 struct ObjectsExtraSizes
 {
 #define FOR_EACH_SIZE(macro) \
-    macro(js::NotLiveGCThing, mallocHeapSlots) \
-    macro(js::NotLiveGCThing, mallocHeapElementsNonAsmJS) \
-    macro(js::NotLiveGCThing, mallocHeapElementsAsmJS) \
-    macro(js::NotLiveGCThing, nonHeapElementsAsmJS) \
-    macro(js::NotLiveGCThing, nonHeapCodeAsmJS) \
-    macro(js::NotLiveGCThing, mallocHeapAsmJSModuleData) \
-    macro(js::NotLiveGCThing, mallocHeapArgumentsData) \
-    macro(js::NotLiveGCThing, mallocHeapRegExpStatics) \
-    macro(js::NotLiveGCThing, mallocHeapPropertyIteratorData) \
-    macro(js::NotLiveGCThing, mallocHeapCtypesData)
+    macro(Objects, NotLiveGCThing, mallocHeapSlots) \
+    macro(Objects, NotLiveGCThing, mallocHeapElementsNonAsmJS) \
+    macro(Objects, NotLiveGCThing, mallocHeapElementsAsmJS) \
+    macro(Objects, NotLiveGCThing, nonHeapElementsAsmJS) \
+    macro(Objects, NotLiveGCThing, nonHeapCodeAsmJS) \
+    macro(Objects, NotLiveGCThing, mallocHeapAsmJSModuleData) \
+    macro(Objects, NotLiveGCThing, mallocHeapArgumentsData) \
+    macro(Objects, NotLiveGCThing, mallocHeapRegExpStatics) \
+    macro(Objects, NotLiveGCThing, mallocHeapPropertyIteratorData) \
+    macro(Objects, NotLiveGCThing, mallocHeapCtypesData)
 
     ObjectsExtraSizes()
       : FOR_EACH_SIZE(ZERO_SIZE)
         dummy()
     {}
 
     void add(const ObjectsExtraSizes &other) {
         FOR_EACH_SIZE(ADD_OTHER_SIZE)
     }
 
     size_t sizeOfLiveGCThings() const {
         size_t n = 0;
         FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
         return n;
     }
 
+    void addToTabSizes(TabSizes *sizes) const {
+        FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
+    }
+
     FOR_EACH_SIZE(DECL_SIZE)
     int dummy;  // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
 
 #undef FOR_EACH_SIZE
 };
 
 // Data for tracking JIT-code memory usage.
 struct CodeSizes
 {
 #define FOR_EACH_SIZE(macro) \
-    macro(_, ion) \
-    macro(_, baseline) \
-    macro(_, regexp) \
-    macro(_, other) \
-    macro(_, unused)
+    macro(_, _, ion) \
+    macro(_, _, baseline) \
+    macro(_, _, regexp) \
+    macro(_, _, other) \
+    macro(_, _, unused)
 
     CodeSizes()
       : FOR_EACH_SIZE(ZERO_SIZE)
         dummy()
     {}
 
     FOR_EACH_SIZE(DECL_SIZE)
     int dummy;  // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
@@ -251,27 +292,27 @@ struct NotableStringInfo : public String
     char *buffer;
 };
 
 // These measurements relate directly to the JSRuntime, and not to zones and
 // compartments within it.
 struct RuntimeSizes
 {
 #define FOR_EACH_SIZE(macro) \
-    macro(_, object) \
-    macro(_, atomsTable) \
-    macro(_, contexts) \
-    macro(_, dtoa) \
-    macro(_, temporary) \
-    macro(_, regexpData) \
-    macro(_, interpreterStack) \
-    macro(_, gcMarker) \
-    macro(_, mathCache) \
-    macro(_, scriptData) \
-    macro(_, scriptSources)
+    macro(_, _, object) \
+    macro(_, _, atomsTable) \
+    macro(_, _, contexts) \
+    macro(_, _, dtoa) \
+    macro(_, _, temporary) \
+    macro(_, _, regexpData) \
+    macro(_, _, interpreterStack) \
+    macro(_, _, gcMarker) \
+    macro(_, _, mathCache) \
+    macro(_, _, scriptData) \
+    macro(_, _, scriptSources)
 
     RuntimeSizes()
       : FOR_EACH_SIZE(ZERO_SIZE)
         code()
     {}
 
     FOR_EACH_SIZE(DECL_SIZE)
     CodeSizes code;
@@ -330,45 +371,45 @@ struct ZoneStats : js::ZoneStatsPod
 
     StringsHashMap strings;
     js::Vector<NotableStringInfo, 0, js::SystemAllocPolicy> notableStrings;
 };
 
 struct CompartmentStats
 {
 #define FOR_EACH_SIZE(macro) \
-    macro(js::IsLiveGCThing,  objectsGCHeapOrdinary) \
-    macro(js::IsLiveGCThing,  objectsGCHeapFunction) \
-    macro(js::IsLiveGCThing,  objectsGCHeapDenseArray) \
-    macro(js::IsLiveGCThing,  objectsGCHeapSlowArray) \
-    macro(js::IsLiveGCThing,  objectsGCHeapCrossCompartmentWrapper) \
-    macro(js::NotLiveGCThing, objectsPrivate) \
-    macro(js::IsLiveGCThing,  shapesGCHeapTreeGlobalParented) \
-    macro(js::IsLiveGCThing,  shapesGCHeapTreeNonGlobalParented) \
-    macro(js::IsLiveGCThing,  shapesGCHeapDict) \
-    macro(js::IsLiveGCThing,  shapesGCHeapBase) \
-    macro(js::NotLiveGCThing, shapesMallocHeapTreeTables) \
-    macro(js::NotLiveGCThing, shapesMallocHeapDictTables) \
-    macro(js::NotLiveGCThing, shapesMallocHeapTreeShapeKids) \
-    macro(js::NotLiveGCThing, shapesMallocHeapCompartmentTables) \
-    macro(js::IsLiveGCThing,  scriptsGCHeap) \
-    macro(js::NotLiveGCThing, scriptsMallocHeapData) \
-    macro(js::NotLiveGCThing, baselineData) \
-    macro(js::NotLiveGCThing, baselineStubsFallback) \
-    macro(js::NotLiveGCThing, baselineStubsOptimized) \
-    macro(js::NotLiveGCThing, ionData) \
-    macro(js::NotLiveGCThing, typeInferenceTypeScripts) \
-    macro(js::NotLiveGCThing, typeInferencePendingArrays) \
-    macro(js::NotLiveGCThing, typeInferenceAllocationSiteTables) \
-    macro(js::NotLiveGCThing, typeInferenceArrayTypeTables) \
-    macro(js::NotLiveGCThing, typeInferenceObjectTypeTables) \
-    macro(js::NotLiveGCThing, compartmentObject) \
-    macro(js::NotLiveGCThing, crossCompartmentWrappersTable) \
-    macro(js::NotLiveGCThing, regexpCompartment) \
-    macro(js::NotLiveGCThing, debuggeesSet)
+    macro(Objects, IsLiveGCThing,  objectsGCHeapOrdinary) \
+    macro(Objects, IsLiveGCThing,  objectsGCHeapFunction) \
+    macro(Objects, IsLiveGCThing,  objectsGCHeapDenseArray) \
+    macro(Objects, IsLiveGCThing,  objectsGCHeapSlowArray) \
+    macro(Objects, IsLiveGCThing,  objectsGCHeapCrossCompartmentWrapper) \
+    macro(Private, NotLiveGCThing, objectsPrivate) \
+    macro(Other,   IsLiveGCThing,  shapesGCHeapTreeGlobalParented) \
+    macro(Other,   IsLiveGCThing,  shapesGCHeapTreeNonGlobalParented) \
+    macro(Other,   IsLiveGCThing,  shapesGCHeapDict) \
+    macro(Other,   IsLiveGCThing,  shapesGCHeapBase) \
+    macro(Other,   NotLiveGCThing, shapesMallocHeapTreeTables) \
+    macro(Other,   NotLiveGCThing, shapesMallocHeapDictTables) \
+    macro(Other,   NotLiveGCThing, shapesMallocHeapTreeShapeKids) \
+    macro(Other,   NotLiveGCThing, shapesMallocHeapCompartmentTables) \
+    macro(Other,   IsLiveGCThing,  scriptsGCHeap) \
+    macro(Other,   NotLiveGCThing, scriptsMallocHeapData) \
+    macro(Other,   NotLiveGCThing, baselineData) \
+    macro(Other,   NotLiveGCThing, baselineStubsFallback) \
+    macro(Other,   NotLiveGCThing, baselineStubsOptimized) \
+    macro(Other,   NotLiveGCThing, ionData) \
+    macro(Other,   NotLiveGCThing, typeInferenceTypeScripts) \
+    macro(Other,   NotLiveGCThing, typeInferencePendingArrays) \
+    macro(Other,   NotLiveGCThing, typeInferenceAllocationSiteTables) \
+    macro(Other,   NotLiveGCThing, typeInferenceArrayTypeTables) \
+    macro(Other,   NotLiveGCThing, typeInferenceObjectTypeTables) \
+    macro(Other,   NotLiveGCThing, compartmentObject) \
+    macro(Other,   NotLiveGCThing, crossCompartmentWrappersTable) \
+    macro(Other,   NotLiveGCThing, regexpCompartment) \
+    macro(Other,   NotLiveGCThing, debuggeesSet)
 
     CompartmentStats()
       : FOR_EACH_SIZE(ZERO_SIZE)
         objectsExtra(),
         extra()
     {}
 
     CompartmentStats(const CompartmentStats &other)
@@ -386,32 +427,38 @@ struct CompartmentStats
     size_t sizeOfLiveGCThings() const {
         size_t n = 0;
         FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
         n += objectsExtra.sizeOfLiveGCThings();
         // Do nothing with |extra|.
         return n;
     }
 
+    void addToTabSizes(TabSizes *sizes) const {
+        FOR_EACH_SIZE(ADD_TO_TAB_SIZES);
+        objectsExtra.addToTabSizes(sizes);
+        // Do nothing with |extra|.
+    }
+
     FOR_EACH_SIZE(DECL_SIZE)
     ObjectsExtraSizes  objectsExtra;
     void               *extra;  // This field can be used by embedders.
 
 #undef FOR_EACH_SIZE
 };
 
 struct RuntimeStats
 {
 #define FOR_EACH_SIZE(macro) \
-    macro(_, gcHeapChunkTotal) \
-    macro(_, gcHeapDecommittedArenas) \
-    macro(_, gcHeapUnusedChunks) \
-    macro(_, gcHeapUnusedArenas) \
-    macro(_, gcHeapChunkAdmin) \
-    macro(_, gcHeapGCThings) \
+    macro(_, _, gcHeapChunkTotal) \
+    macro(_, _, gcHeapDecommittedArenas) \
+    macro(_, _, gcHeapUnusedChunks) \
+    macro(_, _, gcHeapUnusedArenas) \
+    macro(_, _, gcHeapChunkAdmin) \
+    macro(_, _, gcHeapGCThings) \
 
     RuntimeStats(mozilla::MallocSizeOf mallocSizeOf)
       : FOR_EACH_SIZE(ZERO_SIZE)
         runtime(),
         cTotals(),
         zTotals(),
         compartmentStatsVector(),
         zoneStatsVector(),
@@ -483,11 +530,22 @@ extern JS_PUBLIC_API(size_t)
 SystemCompartmentCount(JSRuntime *rt);
 
 extern JS_PUBLIC_API(size_t)
 UserCompartmentCount(JSRuntime *rt);
 
 extern JS_PUBLIC_API(size_t)
 PeakSizeOfTemporary(const JSRuntime *rt);
 
+extern JS_PUBLIC_API(bool)
+AddSizeOfTab(JSRuntime *rt, JSObject *obj, mozilla::MallocSizeOf mallocSizeOf,
+             ObjectPrivateVisitor *opv, TabSizes *sizes);
+
 } // namespace JS
 
+#undef DECL_SIZE
+#undef ZERO_SIZE
+#undef COPY_OTHER_SIZE
+#undef ADD_OTHER_SIZE
+#undef ADD_SIZE_TO_N_IF_LIVE_GC_THING
+#undef ADD_TO_TAB_SIZES
+
 #endif /* js_MemoryMetrics_h */
--- a/js/src/gc/Iteration.cpp
+++ b/js/src/gc/Iteration.cpp
@@ -21,43 +21,66 @@ void
 js::TraceRuntime(JSTracer *trc)
 {
     JS_ASSERT(!IS_GC_MARKING_TRACER(trc));
 
     AutoPrepareForTracing prep(trc->runtime);
     MarkRuntime(trc);
 }
 
+static void
+IterateCompartmentsArenasCells(JSRuntime *rt, Zone *zone, void *data,
+                               JSIterateCompartmentCallback compartmentCallback,
+                               IterateArenaCallback arenaCallback,
+                               IterateCellCallback cellCallback)
+{
+    for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
+        (*compartmentCallback)(rt, data, comp);
+
+    for (size_t thingKind = 0; thingKind != FINALIZE_LIMIT; thingKind++) {
+        JSGCTraceKind traceKind = MapAllocToTraceKind(AllocKind(thingKind));
+        size_t thingSize = Arena::thingSize(AllocKind(thingKind));
+
+        for (ArenaIter aiter(zone, AllocKind(thingKind)); !aiter.done(); aiter.next()) {
+            ArenaHeader *aheader = aiter.get();
+            (*arenaCallback)(rt, data, aheader->getArena(), traceKind, thingSize);
+            for (CellIterUnderGC iter(aheader); !iter.done(); iter.next())
+                (*cellCallback)(rt, data, iter.getCell(), traceKind, thingSize);
+        }
+    }
+}
+
 void
 js::IterateZonesCompartmentsArenasCells(JSRuntime *rt, void *data,
                                         IterateZoneCallback zoneCallback,
                                         JSIterateCompartmentCallback compartmentCallback,
                                         IterateArenaCallback arenaCallback,
                                         IterateCellCallback cellCallback)
 {
     AutoPrepareForTracing prop(rt);
 
     for (ZonesIter zone(rt); !zone.done(); zone.next()) {
         (*zoneCallback)(rt, data, zone);
-
-        for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
-            (*compartmentCallback)(rt, data, comp);
-
-        for (size_t thingKind = 0; thingKind != FINALIZE_LIMIT; thingKind++) {
-            JSGCTraceKind traceKind = MapAllocToTraceKind(AllocKind(thingKind));
-            size_t thingSize = Arena::thingSize(AllocKind(thingKind));
+        IterateCompartmentsArenasCells(rt, zone, data,
+                                       compartmentCallback, arenaCallback, cellCallback);
+    }
+}
 
-            for (ArenaIter aiter(zone, AllocKind(thingKind)); !aiter.done(); aiter.next()) {
-                ArenaHeader *aheader = aiter.get();
-                (*arenaCallback)(rt, data, aheader->getArena(), traceKind, thingSize);
-                for (CellIterUnderGC iter(aheader); !iter.done(); iter.next())
-                    (*cellCallback)(rt, data, iter.getCell(), traceKind, thingSize);
-            }
-        }
-    }
+void
+js::IterateZoneCompartmentsArenasCells(JSRuntime *rt, Zone *zone, void *data,
+                                       IterateZoneCallback zoneCallback,
+                                       JSIterateCompartmentCallback compartmentCallback,
+                                       IterateArenaCallback arenaCallback,
+                                       IterateCellCallback cellCallback)
+{
+    AutoPrepareForTracing prop(rt);
+
+    (*zoneCallback)(rt, data, zone);
+    IterateCompartmentsArenasCells(rt, zone, data,
+                                   compartmentCallback, arenaCallback, cellCallback);
 }
 
 void
 js::IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback)
 {
     AutoPrepareForTracing prep(rt);
 
     for (js::GCChunkSet::Range r = rt->gcChunkSet.all(); !r.empty(); r.popFront())
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1269,28 +1269,39 @@ MarkStackRangeConservatively(JSTracer *t
 typedef void (*IterateChunkCallback)(JSRuntime *rt, void *data, gc::Chunk *chunk);
 typedef void (*IterateZoneCallback)(JSRuntime *rt, void *data, JS::Zone *zone);
 typedef void (*IterateArenaCallback)(JSRuntime *rt, void *data, gc::Arena *arena,
                                      JSGCTraceKind traceKind, size_t thingSize);
 typedef void (*IterateCellCallback)(JSRuntime *rt, void *data, void *thing,
                                     JSGCTraceKind traceKind, size_t thingSize);
 
 /*
- * This function calls |compartmentCallback| on every compartment,
- * |arenaCallback| on every in-use arena, and |cellCallback| on every in-use
- * cell in the GC heap.
+ * This function calls |zoneCallback| on every zone, |compartmentCallback| on
+ * every compartment, |arenaCallback| on every in-use arena, and |cellCallback|
+ * on every in-use cell in the GC heap.
  */
 extern void
 IterateZonesCompartmentsArenasCells(JSRuntime *rt, void *data,
                                     IterateZoneCallback zoneCallback,
                                     JSIterateCompartmentCallback compartmentCallback,
                                     IterateArenaCallback arenaCallback,
                                     IterateCellCallback cellCallback);
 
 /*
+ * This function is like IterateZonesCompartmentsArenasCells, but does it for a
+ * single zone.
+ */
+extern void
+IterateZoneCompartmentsArenasCells(JSRuntime *rt, Zone *zone, void *data,
+                                   IterateZoneCallback zoneCallback,
+                                   JSIterateCompartmentCallback compartmentCallback,
+                                   IterateArenaCallback arenaCallback,
+                                   IterateCellCallback cellCallback);
+
+/*
  * Invoke chunkCallback on every in-use chunk.
  */
 extern void
 IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback);
 
 typedef void (*IterateScriptCallback)(JSRuntime *rt, void *data, JSScript *script);
 
 /*
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -38,16 +38,17 @@
 #include "frontend/BytecodeCompiler.h"
 #include "gc/Marking.h"
 #include "jit/AsmJSModule.h"
 #include "jit/BaselineJIT.h"
 #include "js/MemoryMetrics.h"
 #include "js/OldDebugAPI.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/Interpreter.h"
+#include "vm/ProxyObject.h"
 #include "vm/RegExpStaticsObject.h"
 #include "vm/Shape.h"
 
 #include "jsatominlines.h"
 #include "jsboolinlines.h"
 #include "jscntxtinlines.h"
 #include "jscompartmentinlines.h"
 
@@ -5675,18 +5676,34 @@ JSObject::addSizeOfExcludingThis(mozilla
             sizes->mallocHeapElementsAsmJS += mallocSizeOf(elements);
 #endif
         } else {
             sizes->mallocHeapElementsNonAsmJS += mallocSizeOf(elements);
         }
     }
 
     // Other things may be measured in the future if DMD indicates it is worthwhile.
-    // Note that sizes->private_ is measured elsewhere.
-    if (is<ArgumentsObject>()) {
+    if (is<JSFunction>() ||
+        is<JSObject>() ||
+        is<ArrayObject>() ||
+        is<CallObject>() ||
+        is<RegExpObject>() ||
+        is<ProxyObject>())
+    {
+        // Do nothing.  But this function is hot, and we win by getting the
+        // common cases out of the way early.  Some stats on the most common
+        // classes, as measured during a vanilla browser session:
+        // - (53.7%, 53.7%): Function
+        // - (18.0%, 71.7%): Object
+        // - (16.9%, 88.6%): Array
+        // - ( 3.9%, 92.5%): Call
+        // - ( 2.8%, 95.3%): RegExp
+        // - ( 1.0%, 96.4%): Proxy
+
+    } else if (is<ArgumentsObject>()) {
         sizes->mallocHeapArgumentsData += as<ArgumentsObject>().sizeOfMisc(mallocSizeOf);
     } else if (is<RegExpStaticsObject>()) {
         sizes->mallocHeapRegExpStatics += as<RegExpStaticsObject>().sizeOfData(mallocSizeOf);
     } else if (is<PropertyIteratorObject>()) {
         sizes->mallocHeapPropertyIteratorData += as<PropertyIteratorObject>().sizeOfMisc(mallocSizeOf);
 #ifdef JS_ION
     } else if (is<AsmJSModuleObject>()) {
         as<AsmJSModuleObject>().addSizeOfMisc(mallocSizeOf, &sizes->nonHeapCodeAsmJS,
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -373,17 +373,17 @@ class JSObject : public js::ObjectImpl
      * The number of allocated slots is not stored explicitly, and changes to
      * the slots must track changes in the slot span.
      */
     static bool growSlots(js::ThreadSafeContext *cx, js::HandleObject obj, uint32_t oldCount,
                           uint32_t newCount);
     static void shrinkSlots(js::ThreadSafeContext *cx, js::HandleObject obj, uint32_t oldCount,
                             uint32_t newCount);
 
-    bool hasDynamicSlots() const { return slots != nullptr; }
+    bool hasDynamicSlots() const { return !!slots; }
 
   protected:
     static inline bool updateSlotsForSpan(js::ThreadSafeContext *cx,
                                           js::HandleObject obj, size_t oldSpan, size_t newSpan);
 
   public:
     /*
      * Trigger the write barrier on a range of slots that will no longer be
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -18,18 +18,19 @@
 #include "jit/Ion.h"
 #include "vm/ArrayObject.h"
 #include "vm/Runtime.h"
 #include "vm/Shape.h"
 #include "vm/String.h"
 #include "vm/WrapperObject.h"
 
 using mozilla::DebugOnly;
+using mozilla::MallocSizeOf;
+using mozilla::MoveRef;
 using mozilla::OldMove;
-using mozilla::MoveRef;
 using mozilla::PodEqual;
 
 using namespace js;
 
 using JS::RuntimeStats;
 using JS::ObjectPrivateVisitor;
 using JS::ZoneStats;
 using JS::CompartmentStats;
@@ -263,23 +264,20 @@ StatsCellCallback(JSRuntime *rt, void *d
             cStats->objectsGCHeapDenseArray += thingSize;
         else if (obj->is<CrossCompartmentWrapperObject>())
             cStats->objectsGCHeapCrossCompartmentWrapper += thingSize;
         else
             cStats->objectsGCHeapOrdinary += thingSize;
 
         obj->addSizeOfExcludingThis(rtStats->mallocSizeOf_, &cStats->objectsExtra);
 
-        // JSObject::sizeOfExcludingThis() doesn't measure objectsPrivate,
-        // so we do it here.
         if (ObjectPrivateVisitor *opv = closure->opv) {
             nsISupports *iface;
-            if (opv->getISupports_(obj, &iface) && iface) {
+            if (opv->getISupports_(obj, &iface) && iface)
                 cStats->objectsPrivate += opv->sizeOfIncludingThis(iface);
-            }
         }
         break;
       }
 
       case JSTRACE_STRING: {
         JSString *str = static_cast<JSString *>(thing);
 
         size_t strCharsSize = str->sizeOfExcludingThis(rtStats->mallocSizeOf_);
@@ -333,17 +331,16 @@ StatsCellCallback(JSRuntime *rt, void *d
         cStats->shapesGCHeapBase += thingSize;
         break;
       }
 
       case JSTRACE_SCRIPT: {
         JSScript *script = static_cast<JSScript *>(thing);
         CompartmentStats *cStats = GetCompartmentStats(script->compartment());
         cStats->scriptsGCHeap += thingSize;
-
         cStats->scriptsMallocHeapData += script->sizeOfData(rtStats->mallocSizeOf_);
         cStats->typeInferenceTypeScripts += script->sizeOfTypeScript(rtStats->mallocSizeOf_);
 #ifdef JS_ION
         jit::AddSizeOfBaselineData(script, rtStats->mallocSizeOf_, &cStats->baselineData,
                                    &cStats->baselineStubsFallback);
         cStats->ionData += jit::SizeOfIonData(script, rtStats->mallocSizeOf_);
 #endif
 
@@ -441,24 +438,22 @@ JS::CollectRuntimeStats(JSRuntime *rt, R
 
     IterateChunks(rt, &rtStats->gcHeapDecommittedArenas,
                   DecommittedArenasChunkCallback);
 
     // Take the per-compartment measurements.
     StatsClosure closure(rtStats, opv);
     if (!closure.init())
         return false;
-    rtStats->runtime.scriptSources = 0;
     IterateZonesCompartmentsArenasCells(rt, &closure, StatsZoneCallback, StatsCompartmentCallback,
                                         StatsArenaCallback, StatsCellCallback);
 
     // Take the "explicit/js/runtime/" measurements.
     rt->addSizeOfIncludingThis(rtStats->mallocSizeOf_, &rtStats->runtime);
 
-    rtStats->gcHeapGCThings = 0;
     for (size_t i = 0; i < rtStats->zoneStatsVector.length(); i++) {
         ZoneStats &zStats = rtStats->zoneStatsVector[i];
 
         rtStats->zTotals.add(zStats);
 
         // Move any strings which take up more than the sundries threshold
         // (counting all of their copies together) into notableStrings.
         FindNotableStrings(zStats);
@@ -526,8 +521,67 @@ JS::UserCompartmentCount(JSRuntime *rt)
 }
 
 JS_PUBLIC_API(size_t)
 JS::PeakSizeOfTemporary(const JSRuntime *rt)
 {
     return rt->tempLifoAlloc.peakSizeOfExcludingThis();
 }
 
+namespace JS {
+
+JS_PUBLIC_API(bool)
+AddSizeOfTab(JSRuntime *rt, JSObject *obj, MallocSizeOf mallocSizeOf, ObjectPrivateVisitor *opv,
+             TabSizes *sizes)
+{
+    class SimpleJSRuntimeStats : public JS::RuntimeStats
+    {
+      public:
+        SimpleJSRuntimeStats(MallocSizeOf mallocSizeOf)
+          : JS::RuntimeStats(mallocSizeOf)
+        {}
+
+        virtual void initExtraZoneStats(JS::Zone *zone, JS::ZoneStats *zStats)
+            MOZ_OVERRIDE
+        {}
+
+        virtual void initExtraCompartmentStats(
+            JSCompartment *c, JS::CompartmentStats *cStats) MOZ_OVERRIDE
+        {}
+    };
+
+    SimpleJSRuntimeStats rtStats(mallocSizeOf);
+
+    JS::Zone *zone = GetObjectZone(obj);
+
+    if (!rtStats.compartmentStatsVector.reserve(zone->compartments.length()))
+        return false;
+
+    if (!rtStats.zoneStatsVector.reserve(1))
+        return false;
+
+    // Take the per-compartment measurements.
+    StatsClosure closure(&rtStats, opv);
+    if (!closure.init())
+        return false;
+    IterateZoneCompartmentsArenasCells(rt, zone, &closure, StatsZoneCallback,
+                                       StatsCompartmentCallback, StatsArenaCallback,
+                                       StatsCellCallback);
+
+    JS_ASSERT(rtStats.zoneStatsVector.length() == 1);
+    rtStats.zTotals.add(rtStats.zoneStatsVector[0]);
+
+    for (size_t i = 0; i < rtStats.compartmentStatsVector.length(); i++) {
+        CompartmentStats &cStats = rtStats.compartmentStatsVector[i];
+        rtStats.cTotals.add(cStats);
+    }
+
+    for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
+        comp->compartmentStats = NULL;
+
+    rtStats.zTotals.addToTabSizes(sizes);
+    rtStats.cTotals.addToTabSizes(sizes);
+
+    return true;
+}
+
+} // namespace JS
+
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2411,17 +2411,17 @@ SizeOfTreeIncludingThis(nsINode *tree)
 class OrphanReporter : public JS::ObjectPrivateVisitor
 {
   public:
     OrphanReporter(GetISupportsFun aGetISupports)
       : JS::ObjectPrivateVisitor(aGetISupports)
     {
     }
 
-    virtual size_t sizeOfIncludingThis(nsISupports *aSupports) {
+    virtual size_t sizeOfIncludingThis(nsISupports *aSupports) MOZ_OVERRIDE {
         size_t n = 0;
         nsCOMPtr<nsINode> node = do_QueryInterface(aSupports);
         // https://bugzilla.mozilla.org/show_bug.cgi?id=773533#c11 explains
         // that we have to skip XBL elements because they violate certain
         // assumptions.  Yuk.
         if (node && !node->IsInDoc() &&
             !(node->IsElement() && node->AsElement()->IsInNamespace(kNameSpaceID_XBL)))
         {
@@ -2669,16 +2669,35 @@ JSReporter::CollectReports(WindowPaths *
 
     REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect"),
                  KIND_HEAP, xpconnect,
                  "Memory used by XPConnect.");
 
     return NS_OK;
 }
 
+static nsresult
+JSSizeOfTab(JSObject *obj, size_t *jsObjectsSize, size_t *jsStringsSize,
+            size_t *jsPrivateSize, size_t *jsOtherSize)
+{
+    JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->Runtime();
+
+    TabSizes sizes;
+    OrphanReporter orphanReporter(XPCConvert::GetISupportsFromJSObject);
+    NS_ENSURE_TRUE(JS::AddSizeOfTab(rt, obj, moz_malloc_size_of,
+                                    &orphanReporter, &sizes),
+                   NS_ERROR_OUT_OF_MEMORY);
+
+    *jsObjectsSize = sizes.objects;
+    *jsStringsSize = sizes.strings;
+    *jsPrivateSize = sizes.private_;
+    *jsOtherSize   = sizes.other;
+    return NS_OK;
+}
+
 } // namespace xpc
 
 #ifdef MOZ_CRASHREPORTER
 static bool
 DiagnosticMemoryCallback(void *ptr, size_t size)
 {
     return CrashReporter::RegisterAppMemory(ptr, size) == NS_OK;
 }
@@ -3035,16 +3054,17 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
 
     // Register memory reporters and distinguished amount functions.
     NS_RegisterMemoryReporter(new JSMainRuntimeCompartmentsReporter);
     NS_RegisterMemoryReporter(new JSMainRuntimeTemporaryPeakReporter());
     RegisterJSMainRuntimeGCHeapDistinguishedAmount(JSMainRuntimeGCHeapDistinguishedAmount);
     RegisterJSMainRuntimeTemporaryPeakDistinguishedAmount(JSMainRuntimeTemporaryPeakDistinguishedAmount);
     RegisterJSMainRuntimeCompartmentsSystemDistinguishedAmount(JSMainRuntimeCompartmentsSystemDistinguishedAmount);
     RegisterJSMainRuntimeCompartmentsUserDistinguishedAmount(JSMainRuntimeCompartmentsUserDistinguishedAmount);
+    mozilla::RegisterJSSizeOfTab(JSSizeOfTab);
 
     // Install a JavaScript 'debugger' keyword handler in debug builds only
 #ifdef DEBUG
     if (!JS_GetGlobalDebugHooks(runtime)->debuggerHandler)
         xpc_InstallJSDebuggerKeywordHandler(runtime);
 #endif
 }
 
--- a/layout/base/nsArenaMemoryStats.h
+++ b/layout/base/nsArenaMemoryStats.h
@@ -1,20 +1,81 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=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 nsArenaMemoryStats_h
 #define nsArenaMemoryStats_h
 
+#include "mozilla/Assertions.h"
+#include "mozilla/PodOperations.h"
+
+class nsTabSizes {
+public:
+  enum Kind {
+      DOM,        // DOM stuff.
+      Style,      // Style stuff.
+      Other       // Everything else.
+  };
+
+  nsTabSizes() { mozilla::PodZero(this); }
+
+  void add(Kind kind, size_t n)
+  {
+    switch (kind) {
+      case DOM:   mDom   += n; break;
+      case Style: mStyle += n; break;
+      case Other: mOther += n; break;
+      default:    MOZ_CRASH("bad nsTabSizes kind");
+    }
+  }
+
+  size_t mDom;
+  size_t mStyle;
+  size_t mOther;
+};
+
 #define FRAME_ID_STAT_FIELD(classname) mArena##classname
 
 struct nsArenaMemoryStats {
-#define FRAME_ID(classname) size_t FRAME_ID_STAT_FIELD(classname);
-#include "nsFrameIdList.h"
-#undef FRAME_ID
-  size_t mLineBoxes;
-  size_t mRuleNodes;
-  size_t mStyleContexts;
-  size_t mOther;
+#define FOR_EACH_SIZE(macro) \
+  macro(Other, mLineBoxes) \
+  macro(Style, mRuleNodes) \
+  macro(Style, mStyleContexts) \
+  macro(Other, mOther)
+
+  nsArenaMemoryStats()
+    :
+      #define ZERO_SIZE(kind, mSize) mSize(0),
+      FOR_EACH_SIZE(ZERO_SIZE)
+      #undef ZERO_SIZE
+      #define FRAME_ID(classname) FRAME_ID_STAT_FIELD(classname)(),
+      #include "nsFrameIdList.h"
+      #undef FRAME_ID
+      dummy()
+  {}
+
+  void addToTabSizes(nsTabSizes *sizes) const
+  {
+    #define ADD_TO_TAB_SIZES(kind, mSize) sizes->add(nsTabSizes::kind, mSize);
+    FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
+    #undef ADD_TO_TAB_SIZES
+    #define FRAME_ID(classname) \
+      sizes->add(nsTabSizes::Other, FRAME_ID_STAT_FIELD(classname));
+    #include "nsFrameIdList.h"
+    #undef FRAME_ID
+  }
+
+  #define DECL_SIZE(kind, mSize) size_t mSize;
+  FOR_EACH_SIZE(DECL_SIZE)
+  #undef DECL_SIZE
+  #define FRAME_ID(classname) size_t FRAME_ID_STAT_FIELD(classname);
+  #include "nsFrameIdList.h"
+  #undef FRAME_ID
+  int dummy;  // present just to absorb the trailing comma from FRAME_ID in the
+              // constructor
+
+#undef FOR_EACH_SIZE
 };
 
 #endif // nsArenaMemoryStats_h
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6086,18 +6086,17 @@ PresShell::HandleEvent(nsIFrame* aFrame,
     }
   }
 
   if (aEvent->eventStructType == NS_KEY_EVENT &&
       mDocument && mDocument->EventHandlingSuppressed()) {
     if (aEvent->message == NS_KEY_DOWN) {
       mNoDelayedKeyEvents = true;
     } else if (!mNoDelayedKeyEvents) {
-      nsDelayedEvent* event =
-        new nsDelayedKeyEvent(aEvent->AsKeyboardEvent());
+      DelayedEvent* event = new DelayedKeyEvent(aEvent->AsKeyboardEvent());
       if (!mDelayedEvents.AppendElement(event)) {
         delete event;
       }
     }
     return NS_OK;
   }
 
   nsIFrame* frame = aFrame;
@@ -6308,17 +6307,17 @@ PresShell::HandleEvent(nsIFrame* aFrame,
 
     // Suppress mouse event if it's being targeted at an element inside
     // a document which needs events suppressed
     if (aEvent->eventStructType == NS_MOUSE_EVENT &&
         frame->PresContext()->Document()->EventHandlingSuppressed()) {
       if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
         mNoDelayedMouseEvents = true;
       } else if (!mNoDelayedMouseEvents && aEvent->message == NS_MOUSE_BUTTON_UP) {
-        nsDelayedEvent* event = new nsDelayedMouseEvent(aEvent->AsMouseEvent());
+        DelayedEvent* event = new DelayedMouseEvent(aEvent->AsMouseEvent());
         if (!mDelayedEvents.AppendElement(event)) {
           delete event;
         }
       }
 
       return NS_OK;
     }
 
@@ -6841,18 +6840,18 @@ PresShell::HandleEventInternal(WidgetEve
         return NS_OK;
       }
       if (mouseEvent->IsShift()) {
         aEvent->mFlags.mOnlyChromeDispatch = true;
         aEvent->mFlags.mRetargetToNonNativeAnonymous = true;
       }
     }
 
-    nsAutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
-                                                          aEvent, mDocument);
+    AutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
+                                                        aEvent, mDocument);
 
     if (aEvent->mFlags.mIsTrusted && aEvent->message == NS_MOUSE_MOVE) {
       nsIPresShell::AllowMouseCapture(
         nsEventStateManager::GetActiveEventStateManager() == manager);
     }
 
     nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
 
@@ -7601,19 +7600,19 @@ PresShell::FireOrClearDelayedEvents(bool
     mDelayedEvents.Clear();
     return;
   }
 
   if (mDocument) {
     nsCOMPtr<nsIDocument> doc = mDocument;
     while (!mIsDestroying && mDelayedEvents.Length() &&
            !doc->EventHandlingSuppressed()) {
-      nsAutoPtr<nsDelayedEvent> ev(mDelayedEvents[0].forget());
+      nsAutoPtr<DelayedEvent> ev(mDelayedEvents[0].forget());
       mDelayedEvents.RemoveElementAt(0);
-      ev->Dispatch(this);
+      ev->Dispatch();
     }
     if (!doc->EventHandlingSuppressed()) {
       mDelayedEvents.Clear();
     }
   }
 }
 
 static void
@@ -8314,16 +8313,66 @@ nsIPresShell::RemovePostRefreshObserver(
   presContext->RefreshDriver()->RemovePostRefreshObserver(aObserver);
   return true;
 }
 
 //------------------------------------------------------
 // End of protected and private methods on the PresShell
 //------------------------------------------------------
 
+//------------------------------------------------------------------
+//-- Delayed event Classes Impls
+//------------------------------------------------------------------
+
+PresShell::DelayedInputEvent::DelayedInputEvent() :
+  DelayedEvent(),
+  mEvent(nullptr)
+{
+}
+
+PresShell::DelayedInputEvent::~DelayedInputEvent()
+{
+  delete mEvent;
+}
+
+void
+PresShell::DelayedInputEvent::Dispatch()
+{
+  if (!mEvent || !mEvent->widget) {
+    return;
+  }
+  nsCOMPtr<nsIWidget> widget = mEvent->widget;
+  nsEventStatus status;
+  widget->DispatchEvent(mEvent, status);
+}
+
+PresShell::DelayedMouseEvent::DelayedMouseEvent(WidgetMouseEvent* aEvent) :
+  DelayedInputEvent()
+{
+  WidgetMouseEvent* mouseEvent =
+    new WidgetMouseEvent(aEvent->mFlags.mIsTrusted,
+                         aEvent->message,
+                         aEvent->widget,
+                         aEvent->reason,
+                         aEvent->context);
+  mouseEvent->AssignMouseEventData(*aEvent, false);
+  mEvent = mouseEvent;
+}
+
+PresShell::DelayedKeyEvent::DelayedKeyEvent(WidgetKeyboardEvent* aEvent) :
+  DelayedInputEvent()
+{
+  WidgetKeyboardEvent* keyEvent =
+    new WidgetKeyboardEvent(aEvent->mFlags.mIsTrusted,
+                            aEvent->message,
+                            aEvent->widget);
+  keyEvent->AssignKeyEventData(*aEvent, false);
+  mEvent = keyEvent;
+}
+
 // Start of DEBUG only code
 
 #ifdef DEBUG
 
 static void
 LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg)
 {
   nsAutoString n1, n2;
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -29,19 +29,18 @@
 #include "nsCRT.h"
 #include "nsAutoPtr.h"
 #include "nsIWidget.h"
 #include "nsStyleSet.h"
 #include "nsFrameSelection.h"
 #include "nsContentUtils.h" // For AddScriptBlocker().
 #include "nsRefreshDriver.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/EventForwards.h"
 #include "mozilla/MemoryReporting.h"
-#include "mozilla/MouseEvents.h"
-#include "mozilla/TextEvents.h"
 
 class nsRange;
 class nsIDragService;
 class nsCSSStyleSheet;
 
 struct RangePaintInfo;
 struct nsCallbackEventRequest;
 #ifdef MOZ_REFLOW_PERF
@@ -542,77 +541,45 @@ protected:
     nsresult rv = NS_OK;
     if (GetCurrentEventFrame()) {
       rv = HandleEventInternal(aEvent, aStatus);
     }
     PopCurrentEventInfo();
     return rv;
   }
 
-  class nsDelayedEvent
-  {
-  public:
-    virtual ~nsDelayedEvent() {};
-    virtual void Dispatch(PresShell* aShell) {}
-  };
-
-  class nsDelayedInputEvent : public nsDelayedEvent
+  class DelayedEvent
   {
   public:
-    virtual void Dispatch(PresShell* aShell)
-    {
-      if (mEvent && mEvent->widget) {
-        nsCOMPtr<nsIWidget> w = mEvent->widget;
-        nsEventStatus status;
-        w->DispatchEvent(mEvent, status);
-      }
-    }
+    virtual ~DelayedEvent() { }
+    virtual void Dispatch() { }
+  };
+
+  class DelayedInputEvent : public DelayedEvent
+  {
+  public:
+    virtual void Dispatch() MOZ_OVERRIDE;
 
   protected:
-    nsDelayedInputEvent()
-    : nsDelayedEvent(), mEvent(nullptr) {}
-
-    virtual ~nsDelayedInputEvent()
-    {
-      delete mEvent;
-    }
+    DelayedInputEvent();
+    virtual ~DelayedInputEvent();
 
     mozilla::WidgetInputEvent* mEvent;
   };
 
-  class nsDelayedMouseEvent : public nsDelayedInputEvent
+  class DelayedMouseEvent : public DelayedInputEvent
   {
   public:
-    nsDelayedMouseEvent(mozilla::WidgetMouseEvent* aEvent) :
-      nsDelayedInputEvent()
-    {
-      mozilla::WidgetMouseEvent* mouseEvent =
-        new mozilla::WidgetMouseEvent(aEvent->mFlags.mIsTrusted,
-                                      aEvent->message,
-                                      aEvent->widget,
-                                      aEvent->reason,
-                                      aEvent->context);
-      mouseEvent->AssignMouseEventData(*aEvent, false);
-      mEvent = mouseEvent;
-    }
+    DelayedMouseEvent(mozilla::WidgetMouseEvent* aEvent);
   };
 
-  class nsDelayedKeyEvent : public nsDelayedInputEvent
+  class DelayedKeyEvent : public DelayedInputEvent
   {
   public:
-    nsDelayedKeyEvent(mozilla::WidgetKeyboardEvent* aEvent) :
-      nsDelayedInputEvent()
-    {
-      mozilla::WidgetKeyboardEvent* keyEvent =
-        new mozilla::WidgetKeyboardEvent(aEvent->mFlags.mIsTrusted,
-                                         aEvent->message,
-                                         aEvent->widget);
-      keyEvent->AssignKeyEventData(*aEvent, false);
-      mEvent = keyEvent;
-    }
+    DelayedKeyEvent(mozilla::WidgetKeyboardEvent* aEvent);
   };
 
   // Check if aEvent is a mouse event and record the mouse location for later
   // synth mouse moves.
   void RecordMouseLocation(mozilla::WidgetGUIEvent* aEvent);
   class nsSynthMouseMoveEvent MOZ_FINAL : public nsARefreshObserver {
   public:
     nsSynthMouseMoveEvent(PresShell* aPresShell, bool aFromScroll)
@@ -754,17 +721,17 @@ protected:
 
   // Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after
   // we finish reflowing mCurrentReflowRoot.
   nsTHashtable<nsPtrHashKey<nsIFrame> > mFramesToDirty;
 
   // Reflow roots that need to be reflowed.
   nsTArray<nsIFrame*>       mDirtyRoots;
 
-  nsTArray<nsAutoPtr<nsDelayedEvent> > mDelayedEvents;
+  nsTArray<nsAutoPtr<DelayedEvent> > mDelayedEvents;
   nsRevocableEventPtr<nsRunnableMethod<PresShell> > mResizeEvent;
   nsCOMPtr<nsITimer>        mAsyncResizeEventTimer;
 private:
   nsIFrame*                 mCurrentEventFrame;
   nsCOMPtr<nsIContent>      mCurrentEventContent;
   nsTArray<nsIFrame*>       mCurrentEventFrameStack;
   nsCOMArray<nsIContent>    mCurrentEventContentStack;
 protected:
--- a/layout/generic/Selection.h
+++ b/layout/generic/Selection.h
@@ -9,17 +9,17 @@
 
 #include "nsIWeakReference.h"
 
 #include "nsISelection.h"
 #include "nsISelectionController.h"
 #include "nsISelectionPrivate.h"
 #include "nsRange.h"
 #include "nsThreadUtils.h"
-#include "mozilla/TextEvents.h"
+#include "mozilla/TextRange.h"
 
 struct CachedOffsetForFrame;
 class nsAutoScrollTimer;
 class nsIContentIterator;
 class nsIFrame;
 class nsFrameSelection;
 struct SelectionDetails;
 
--- a/layout/generic/nsFrameSelection.h
+++ b/layout/generic/nsFrameSelection.h
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsFrameSelection_h___
 #define nsFrameSelection_h___
 
 #include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/Selection.h"
-#include "mozilla/TextEvents.h"
+#include "mozilla/TextRange.h"
 #include "nsIFrame.h"
 #include "nsIContent.h"
 #include "nsISelectionController.h"
 #include "nsITableCellLayout.h"
 #include "nsIDOMElement.h"
 #include "nsRange.h"
 
 class nsTableOuterFrame;
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -140,17 +140,16 @@ extern "C" {
   extern void DisposeGWorld(GWorldPtr offscreenGWorld)
     __attribute__((weak_import));
   #endif /* __QDOFFSCREEN__ */
 }
 
 #endif /* #if defined(XP_MACOSX) && !defined(__LP64__) */
 
 using namespace mozilla;
-using namespace mozilla::plugins;
 using namespace mozilla::layers;
 
 class PluginBackgroundSink : public ReadbackSink {
 public:
   PluginBackgroundSink(nsObjectFrame* aFrame, uint64_t aStartSequenceNumber)
     : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
   ~PluginBackgroundSink()
   {
@@ -1786,17 +1785,17 @@ nsObjectFrame::PaintPlugin(nsDisplayList
       nsPoint origin;
 
       gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
       if (nativeDraw.IsDoublePass()) {
         // OOP plugin specific: let the shim know before we paint if we are doing a
         // double pass render. If this plugin isn't oop, the register window message
         // will be ignored.
         NPEvent pluginEvent;
-        pluginEvent.event = DoublePassRenderingEvent();
+        pluginEvent.event = plugins::DoublePassRenderingEvent();
         pluginEvent.wParam = 0;
         pluginEvent.lParam = 0;
         if (pluginEvent.event)
           inst->HandleEvent(&pluginEvent, nullptr);
       }
       do {
         HDC hdc = nativeDraw.BeginNativeDrawing();
         if (!hdc)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2415,18 +2415,19 @@ private:
   nsStyleCoord mFilterParameter; // coord, percent, factor, angle
   union {
     nsIURI* mURL;
     nsCSSShadowArray* mDropShadow;
   };
 };
 
 template<>
-struct nsTArray_CopyElements<nsStyleFilter>
-  : public nsTArray_CopyWithConstructors<nsStyleFilter> {};
+struct nsTArray_CopyChooser<nsStyleFilter> {
+  typedef nsTArray_CopyWithConstructors<nsStyleFilter> Type;
+};
 
 struct nsStyleSVGReset {
   nsStyleSVGReset();
   nsStyleSVGReset(const nsStyleSVGReset& aSource);
   ~nsStyleSVGReset();
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->AllocateFromShell(sz);
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -14,16 +14,17 @@
 #include "nsINameSpaceManager.h"
 #include "nsViewManager.h"
 #include "nsWidgetsCID.h"
 #include "nsMenuFrame.h"
 #include "nsMenuBarFrame.h"
 #include "nsPopupSetFrame.h"
 #include "nsEventDispatcher.h"
 #include "nsPIDOMWindow.h"
+#include "nsIDOMKeyEvent.h"
 #include "nsIDOMScreen.h"
 #include "nsIPresShell.h"
 #include "nsFrameManager.h"
 #include "nsIDocument.h"
 #include "nsRect.h"
 #include "nsIComponentManager.h"
 #include "nsBoxLayoutState.h"
 #include "nsIScrollableFrame.h"
@@ -1645,17 +1646,17 @@ nsMenuPopupFrame::FindMenuWithShortcut(n
   bool isMenu = parentContent &&
                   !parentContent->NodeInfo()->Equals(nsGkAtoms::menulist, kNameSpaceID_XUL);
 
   static DOMTimeStamp lastKeyTime = 0;
   DOMTimeStamp keyTime;
   aKeyEvent->GetTimeStamp(&keyTime);
 
   if (charCode == 0) {
-    if (keyCode == NS_VK_BACK) {
+    if (keyCode == nsIDOMKeyEvent::DOM_VK_BACK_SPACE) {
       if (!isMenu && !mIncrementalString.IsEmpty()) {
         mIncrementalString.SetLength(mIncrementalString.Length() - 1);
         return nullptr;
       }
       else {
 #ifdef XP_WIN
         nsCOMPtr<nsISound> soundInterface = do_CreateInstance("@mozilla.org/sound;1");
         if (soundInterface)
--- a/layout/xul/base/src/nsXULPopupManager.cpp
+++ b/layout/xul/base/src/nsXULPopupManager.cpp
@@ -1841,17 +1841,18 @@ nsXULPopupManager::HandleKeyboardNavigat
   if (item)
     itemFrame = item->Frame();
   else if (mActiveMenuBar)
     itemFrame = mActiveMenuBar;
   else
     return false;
 
   nsNavigationDirection theDirection;
-  NS_ASSERTION(aKeyCode >= NS_VK_END && aKeyCode <= NS_VK_DOWN, "Illegal key code");
+  NS_ASSERTION(aKeyCode >= nsIDOMKeyEvent::DOM_VK_END &&
+                 aKeyCode <= nsIDOMKeyEvent::DOM_VK_DOWN, "Illegal key code");
   theDirection = NS_DIRECTION_FROM_KEY_CODE(itemFrame, aKeyCode);
 
   // if a popup is open, first check for navigation within the popup
   if (item && HandleKeyboardNavigationInPopup(item, theDirection))
     return true;
 
   // no popup handled the key, so check the active menubar, if any
   if (mActiveMenuBar) {
@@ -2349,18 +2350,18 @@ nsXULMenuCommandEvent::Run()
     nsPresContext* presContext = menuFrame->PresContext();
     nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
     nsRefPtr<nsViewManager> kungFuDeathGrip = shell->GetViewManager();
 
     // Deselect ourselves.
     if (mCloseMenuMode != CloseMenuMode_None)
       menuFrame->SelectMenu(false);
 
-    nsAutoHandlingUserInputStatePusher userInpStatePusher(mUserInput, nullptr,
-                                                          shell->GetDocument());
+    AutoHandlingUserInputStatePusher userInpStatePusher(mUserInput, nullptr,
+                                                        shell->GetDocument());
     nsContentUtils::DispatchXULCommand(mMenu, mIsTrusted, nullptr, shell,
                                        mControl, mAlt, mShift, mMeta);
   }
 
   if (popup && mCloseMenuMode != CloseMenuMode_None)
     pm->HidePopup(popup, mCloseMenuMode == CloseMenuMode_Auto, true, false);
 
   return NS_OK;
--- a/modules/libmar/tool/mar.c
+++ b/modules/libmar/tool/mar.c
@@ -149,17 +149,17 @@ int main(int argc, char **argv) {
       argc -= 2;
     } 
 #if defined(XP_WIN) && !defined(MAR_NSS) && !defined(NO_SIGN_VERIFY)
     /* -D DERFilePath, also matches -D[index] DERFilePath
        We allow an index for verifying to be symmetric
        with the import and export command line arguments. */
     else if (argv[1][0] == '-' &&
              argv[1][1] == 'D' &&
-             (argv[1][2] == '0' + certCount || argv[1][2] == '\0')) {
+             (argv[1][2] == (char)('0' + certCount) || argv[1][2] == '\0')) {
       if (certCount >= MAX_SIGNATURES) {
         print_usage();
         return -1;
       }
       DERFilePaths[certCount++] = argv[2];
       argv += 2;
       argc -= 2;
     }
--- a/testing/mochitest/runtestsremote.py
+++ b/testing/mochitest/runtestsremote.py
@@ -610,20 +610,19 @@ def main():
             log.info("Running tests %d-%d/%d", start+1, end, len(tests))
 
         deviceRoot = dm.getDeviceRoot()      
         dm.removeFile(os.path.join(deviceRoot, "fennec_ids.txt"))
         fennec_ids = os.path.abspath("fennec_ids.txt")
         if not os.path.exists(fennec_ids) and options.robocopIds:
             fennec_ids = options.robocopIds
         dm.pushFile(fennec_ids, os.path.join(deviceRoot, "fennec_ids.txt"))
-        options.extraPrefs.append('robocop.logfile="%s/robocop.log"' % deviceRoot)
         options.extraPrefs.append('browser.search.suggest.enabled=true')
         options.extraPrefs.append('browser.search.suggest.prompted=true')
-        options.extraPrefs.append('layout.css.devPixelsPerPx="1.0"')
+        options.extraPrefs.append('layout.css.devPixelsPerPx=1.0')
         options.extraPrefs.append('browser.chrome.dynamictoolbar=false')
 
         if (options.dm_trans == 'adb' and options.robocopApk):
             dm._checkCmd(["install", "-r", options.robocopApk])
 
         retVal = None
         for test in robocop_tests:
             if options.testPath and options.testPath != test['name']:
--- a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul
+++ b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul
@@ -150,16 +150,31 @@
       // and this file hasn't been updated appropriately.
       dummy = mgr[amounts[i]];
       ok(dummy !== undefined,
          "accessed an unknown distinguished amount: " + amounts[i]);
     } catch (ex) {
     }
   }
 
+  // Run sizeOfTab() to make sure it doesn't crash.  We can't check the result
+  // values because they're non-deterministic.
+  let jsObjectsSize = {};
+  let jsStringsSize = {};
+  let jsOtherSize = {};
+  let domSize = {};
+  let styleSize = {};
+  let otherSize = {};
+  let totalSize = {};
+  let jsMilliseconds = {};
+  let nonJSMilliseconds = {};
+  mgr.sizeOfTab(window, jsObjectsSize, jsStringsSize, jsOtherSize,
+                domSize, styleSize, otherSize, totalSize,
+                jsMilliseconds, nonJSMilliseconds);
+
   let e = mgr.enumerateReporters();
   while (e.hasMoreElements()) {
     let r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
     r.collectReports(handleReport, null);
 
     // Access |name| to make sure it doesn't crash or assert.
     dummy = r.name;
   }
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -235,25 +235,19 @@
                         <tr>
                             <td class="statLabel">&stats.volume;</td> <td class="statValue"><span class="statVolume"/></td>
                         </tr>
                         <tr>
                             <!-- Localization note: readyState is a HTML5 API MediaElement-specific attribute and should not be localized. -->
                             <td class="statLabel">readyState</td> <td class="statValue"><span class="statReadyState"/></td>
                         </tr>
                         <tr>
-                            <td class="statLabel">&stats.channels;</td> <td class="statValue"><span class="statChannels"/></td>
-                        </tr>
-                        <tr>
                           <!-- Localization note: networkState is a HTML5 API MediaElement-specific attribute and should not be localized. -->
                           <td class="statLabel">networkState</td> <td class="statValue"><span class="statNetState"/></td>
                         </tr>
-                        <tr>
-                          <td class="statLabel">&stats.sampleRate;</td> <td class="statValue"><span class="statSampleRate"/></td>
-                        </tr>
                         <tr style="height: 1em;"/>
 
                         <tr>
                             <td class="statLabel">&stats.framesParsed;</td>
                             <td class="statValue"><span class="statFramesParsed"/></td>
                         </tr>
                         <tr>
                             <td class="statLabel">&stats.framesDecoded;</td>
@@ -1213,19 +1207,16 @@
                     s.framesDecoded.textContent = v.mozDecodedFrames;
                     s.framesPresented.textContent = v.mozPresentedFrames;
                     s.framesPainted.textContent = v.mozPaintedFrames;
 
                     let volume = Math.round(v.volume * 100) + "%";
                     if (v.muted)
                         volume += " (muted)";
                     s.volume.textContent = volume;
-
-                    s.channels.textContent = v.mozChannels;
-                    s.sampRate.textContent = (v.mozSampleRate / 1000).toFixed(3) + " kHz";
                 },
 
                 keyHandler : function(event) {
                     // Ignore keys when content might be providing its own.
                     if (!this.video.hasAttribute("controls"))
                         return;
 
                     var keystroke = "";
@@ -1405,18 +1396,16 @@
                     this.clickToPlay        = document.getAnonymousElementByAttribute(binding, "class", "clickToPlay");
                     this.fullscreenButton   = document.getAnonymousElementByAttribute(binding, "class", "fullscreenButton");
 
                     this.statsTable       = document.getAnonymousElementByAttribute(binding, "class", "statsTable");
                     this.stats.filename   = document.getAnonymousElementByAttribute(binding, "class", "statFilename");
                     this.stats.size       = document.getAnonymousElementByAttribute(binding, "class", "statSize");
                     this.stats.activity   = document.getAnonymousElementByAttribute(binding, "class", "statActivity");
                     this.stats.volume     = document.getAnonymousElementByAttribute(binding, "class", "statVolume");
-                    this.stats.channels   = document.getAnonymousElementByAttribute(binding, "class", "statChannels");
-                    this.stats.sampRate   = document.getAnonymousElementByAttribute(binding, "class", "statSampleRate");
                     this.stats.readyState = document.getAnonymousElementByAttribute(binding, "class", "statReadyState");
                     this.stats.netState   = document.getAnonymousElementByAttribute(binding, "class", "statNetState");
                     this.stats.framesParsed    = document.getAnonymousElementByAttribute(binding, "class", "statFramesParsed");
                     this.stats.framesDecoded   = document.getAnonymousElementByAttribute(binding, "class", "statFramesDecoded");
                     this.stats.framesPresented = document.getAnonymousElementByAttribute(binding, "class", "statFramesPresented");
                     this.stats.framesPainted   = document.getAnonymousElementByAttribute(binding, "class", "statFramesPainted");
 
                     this.setupInitialState();
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -84,17 +84,17 @@ STATIC_LIBS += \
 ifdef MOZ_CONTENT_SANDBOX #{
 STATIC_LIBS += sandbox_s
 endif #}
 
 ifdef MOZ_B2G_RIL #{
 STATIC_LIBS += mozril_s
 endif #}
 
-ifdef MOZ_B2G_BT #{
+ifdef MOZ_B2G_BT_BLUEZ #{
 STATIC_LIBS += mozdbus_s
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 OS_LIBS += -ldbus
 endif
 endif #}
 
 ifneq ($(strip $(MOZ_B2G_RIL)$(MOZ_B2G_BT)),) #{
 STATIC_LIBS += mozipcunixsocket_s mozkeystore_s
--- a/toolkit/locales/en-US/chrome/global/videocontrols.dtd
+++ b/toolkit/locales/en-US/chrome/global/videocontrols.dtd
@@ -12,18 +12,16 @@
 <!ENTITY stats.media "Media">
 <!ENTITY stats.size "Size">
 <!ENTITY stats.activity "Activity">
 <!ENTITY stats.activityPaused "Paused">
 <!ENTITY stats.activityPlaying "Playing">
 <!ENTITY stats.activityEnded "Ended">
 <!ENTITY stats.activitySeeking "(seeking)">
 <!ENTITY stats.volume "Volume">
-<!ENTITY stats.channels "Channels">
-<!ENTITY stats.sampleRate "Sample Rate">
 <!ENTITY stats.framesParsed "Frames parsed">
 <!ENTITY stats.framesDecoded "Frames decoded">
 <!ENTITY stats.framesPresented "Frames presented">
 <!ENTITY stats.framesPainted "Frames painted">
 
 <!ENTITY error.aborted "Video loading stopped.">
 <!ENTITY error.network "Video playback aborted due to a network error.">
 <!ENTITY error.decode "Video can't be played because the file is corrupt.">
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -615,22 +615,24 @@ SyncProfile* NewSyncProfile()
 
 SyncProfile* TableTicker::GetBacktrace()
 {
   SyncProfile* profile = NewSyncProfile();
 
   TickSample sample;
   sample.threadProfile = profile;
 
+#if defined(HAVE_NATIVE_UNWIND)
 #if defined(XP_WIN) || defined(LINUX)
   tickcontext_t context;
   sample.PopulateContext(&context);
 #elif defined(XP_MACOSX)
   sample.PopulateContext(nullptr);
 #endif
+#endif
 
   sample.isSamplingCurrentThread = true;
   sample.timestamp = mozilla::TimeStamp::Now();
 
   if (!HasUnwinderThread()) {
     profile->BeginUnwind();
   }
 
--- a/view/public/nsView.h
+++ b/view/public/nsView.h
@@ -6,16 +6,17 @@
 #ifndef nsView_h__
 #define nsView_h__
 
 #include "nsCoord.h"
 #include "nsRect.h"
 #include "nsPoint.h"
 #include "nsRegion.h"
 #include "nsCRT.h"
+#include "nsWidgetInitData.h" // for nsWindowType
 #include "nsIWidgetListener.h"
 #include "mozilla/EventForwards.h"
 
 class nsViewManager;
 class nsIWidget;
 class nsIFrame;
 
 // Enumerated type to indicate the visibility of a layer.
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -22,16 +22,17 @@
 #include "mozilla/StartupTimeline.h"
 #include "GeckoProfiler.h"
 #include "nsRefreshDriver.h"
 #include "mozilla/Preferences.h"
 #include "nsContentUtils.h" // for nsAutoScriptBlocker
 #include "nsLayoutUtils.h"
 #include "Layers.h"
 #include "gfxPlatform.h"
+#include "nsIDocument.h"
 
 /**
    XXX TODO XXX
 
    DeCOMify newly private methods
    Optimize view storage
 */
 
--- a/widget/EventForwards.h
+++ b/widget/EventForwards.h
@@ -59,16 +59,18 @@ namespace mozilla {
 #undef NS_EVENT_CLASS
 #undef NS_ROOT_EVENT_CLASS
 
 // BasicEvents.h
 struct EventFlags;
 
 // TextEvents.h
 struct AlternativeCharCode;
+
+// TextRange.h
 struct TextRangeStyle;
 struct TextRange;
 
 typedef TextRange* TextRangeArray;
 
 } // namespace mozilla
 
 #endif // mozilla_EventForwards_h__
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -6,23 +6,22 @@
 #ifndef mozilla_TextEvents_h__
 #define mozilla_TextEvents_h__
 
 #include <stdint.h>
 
 #include "mozilla/Assertions.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventForwards.h" // for KeyNameIndex, temporarily
-#include "nsColor.h"
+#include "mozilla/TextRange.h"
 #include "nsCOMPtr.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsITransferable.h"
 #include "nsRect.h"
 #include "nsStringGlue.h"
-#include "nsStyleConsts.h"
 #include "nsTArray.h"
 
 /******************************************************************************
  * virtual keycode values
  ******************************************************************************/
 
 #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) NS_##aDOMKeyName = aDOMKeyCode
 
@@ -145,158 +144,16 @@ public:
     // Don't copy mNativeKeyEvent because it may be referred after its instance
     // is destroyed.
     mNativeKeyEvent = nullptr;
     mUniqueId = aEvent.mUniqueId;
   }
 };
 
 /******************************************************************************
- * mozilla::TextRangeStyle
- ******************************************************************************/
-
-struct TextRangeStyle
-{
-  enum {
-    LINESTYLE_NONE   = NS_STYLE_TEXT_DECORATION_STYLE_NONE,
-    LINESTYLE_SOLID  = NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
-    LINESTYLE_DOTTED = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED,
-    LINESTYLE_DASHED = NS_STYLE_TEXT_DECORATION_STYLE_DASHED,
-    LINESTYLE_DOUBLE = NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE,
-    LINESTYLE_WAVY   = NS_STYLE_TEXT_DECORATION_STYLE_WAVY
-  };
-
-  enum {
-    DEFINED_NONE             = 0x00,
-    DEFINED_LINESTYLE        = 0x01,
-    DEFINED_FOREGROUND_COLOR = 0x02,
-    DEFINED_BACKGROUND_COLOR = 0x04,
-    DEFINED_UNDERLINE_COLOR  = 0x08
-  };
-
-  // Initialize all members, because TextRange instances may be compared by
-  // memcomp.
-  TextRangeStyle()
-  {
-    Clear();
-  }
-
-  void Clear()
-  {
-    mDefinedStyles = DEFINED_NONE;
-    mLineStyle = LINESTYLE_NONE;
-    mIsBoldLine = false;
-    mForegroundColor = mBackgroundColor = mUnderlineColor = NS_RGBA(0, 0, 0, 0);
-  }
-
-  bool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
-
-  bool IsLineStyleDefined() const
-  {
-    return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
-  }
-
-  bool IsForegroundColorDefined() const
-  {
-    return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
-  }
-
-  bool IsBackgroundColorDefined() const
-  {
-    return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
-  }
-
-  bool IsUnderlineColorDefined() const
-  {
-    return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
-  }
-
-  bool IsNoChangeStyle() const
-  {
-    return !IsForegroundColorDefined() && !IsBackgroundColorDefined() &&
-           IsLineStyleDefined() && mLineStyle == LINESTYLE_NONE;
-  }
-
-  bool Equals(const TextRangeStyle& aOther)
-  {
-    if (mDefinedStyles != aOther.mDefinedStyles)
-      return false;
-    if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
-                                 !mIsBoldLine != !aOther.mIsBoldLine))
-      return false;
-    if (IsForegroundColorDefined() &&
-        (mForegroundColor != aOther.mForegroundColor))
-      return false;
-    if (IsBackgroundColorDefined() &&
-        (mBackgroundColor != aOther.mBackgroundColor))
-      return false;
-    if (IsUnderlineColorDefined() &&
-        (mUnderlineColor != aOther.mUnderlineColor))
-      return false;
-    return true;
-  }
-
-  bool operator !=(const TextRangeStyle &aOther)
-  {
-    return !Equals(aOther);
-  }
-
-  bool operator ==(const TextRangeStyle &aOther)
-  {
-    return Equals(aOther);
-  }
-
-  uint8_t mDefinedStyles;
-  uint8_t mLineStyle;        // DEFINED_LINESTYLE
-
-  bool mIsBoldLine;  // DEFINED_LINESTYLE
-
-  nscolor mForegroundColor;  // DEFINED_FOREGROUND_COLOR
-  nscolor mBackgroundColor;  // DEFINED_BACKGROUND_COLOR
-  nscolor mUnderlineColor;   // DEFINED_UNDERLINE_COLOR
-};
-
-/******************************************************************************
- * mozilla::TextRange
- ******************************************************************************/
-
-// Sync with nsIPrivateTextRange.h when you change these constants.
-#define NS_TEXTRANGE_CARETPOSITION         0x01
-#define NS_TEXTRANGE_RAWINPUT              0x02
-#define NS_TEXTRANGE_SELECTEDRAWTEXT       0x03
-#define NS_TEXTRANGE_CONVERTEDTEXT         0x04
-#define NS_TEXTRANGE_SELECTEDCONVERTEDTEXT 0x05
-
-struct TextRange
-{
-  TextRange() :
-    mStartOffset(0), mEndOffset(0), mRangeType(0)
-  {
-  }
-
-  uint32_t mStartOffset;
-  // XXX Storing end offset makes the initializing code very complicated.
-  //     We should replace it with mLength.
-  uint32_t mEndOffset;
-  uint32_t mRangeType;
-
-  TextRangeStyle mRangeStyle;
-
-  uint32_t Length() const { return mEndOffset - mStartOffset; }
-};
-
-/******************************************************************************
- * mozilla::TextRangeArray
- *
- * XXX This should be replaced with nsTArray<TextRange>.
- ******************************************************************************/
-
-typedef TextRange* TextRangeArray;
-
-/******************************************************************************
  * mozilla::WidgetTextEvent
  *
  * XXX WidgetTextEvent is fired with compositionupdate event almost every time.
  *     This wastes performance and the cost of mantaining each platform's
  *     implementation.  Therefore, we should merge WidgetTextEvent and
  *     WidgetCompositionEvent.  Then, DOM compositionupdate should be fired
  *     from TextComposition automatically.
  ******************************************************************************/
new file mode 100644
--- /dev/null
+++ b/widget/TextRange.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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_TextRage_h_
+#define mozilla_TextRage_h_
+
+#include <stdint.h>
+
+#include "nsColor.h"
+#include "nsStyleConsts.h"
+
+namespace mozilla {
+
+/******************************************************************************
+ * mozilla::TextRangeStyle
+ ******************************************************************************/
+
+struct TextRangeStyle
+{
+  enum
+  {
+    LINESTYLE_NONE   = NS_STYLE_TEXT_DECORATION_STYLE_NONE,
+    LINESTYLE_SOLID  = NS_STYLE_TEXT_DECORATION_STYLE_SOLID,
+    LINESTYLE_DOTTED = NS_STYLE_TEXT_DECORATION_STYLE_DOTTED,
+    LINESTYLE_DASHED = NS_STYLE_TEXT_DECORATION_STYLE_DASHED,
+    LINESTYLE_DOUBLE = NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE,
+    LINESTYLE_WAVY   = NS_STYLE_TEXT_DECORATION_STYLE_WAVY
+  };
+
+  enum
+  {
+    DEFINED_NONE             = 0x00,
+    DEFINED_LINESTYLE        = 0x01,
+    DEFINED_FOREGROUND_COLOR = 0x02,
+    DEFINED_BACKGROUND_COLOR = 0x04,
+    DEFINED_UNDERLINE_COLOR  = 0x08
+  };
+
+  // Initialize all members, because TextRange instances may be compared by
+  // memcomp.
+  TextRangeStyle()
+  {
+    Clear();
+  }
+
+  void Clear()
+  {
+    mDefinedStyles = DEFINED_NONE;
+    mLineStyle = LINESTYLE_NONE;
+    mIsBoldLine = false;
+    mForegroundColor = mBackgroundColor = mUnderlineColor = NS_RGBA(0, 0, 0, 0);
+  }
+
+  bool IsDefined() const { return mDefinedStyles != DEFINED_NONE; }
+
+  bool IsLineStyleDefined() const
+  {
+    return (mDefinedStyles & DEFINED_LINESTYLE) != 0;
+  }
+
+  bool IsForegroundColorDefined() const
+  {
+    return (mDefinedStyles & DEFINED_FOREGROUND_COLOR) != 0;
+  }
+
+  bool IsBackgroundColorDefined() const
+  {
+    return (mDefinedStyles & DEFINED_BACKGROUND_COLOR) != 0;
+  }
+
+  bool IsUnderlineColorDefined() const
+  {
+    return (mDefinedStyles & DEFINED_UNDERLINE_COLOR) != 0;
+  }
+
+  bool IsNoChangeStyle() const
+  {
+    return !IsForegroundColorDefined() && !IsBackgroundColorDefined() &&
+           IsLineStyleDefined() && mLineStyle == LINESTYLE_NONE;
+  }
+
+  bool Equals(const TextRangeStyle& aOther)
+  {
+    if (mDefinedStyles != aOther.mDefinedStyles)
+      return false;
+    if (IsLineStyleDefined() && (mLineStyle != aOther.mLineStyle ||
+                                 !mIsBoldLine != !aOther.mIsBoldLine))
+      return false;
+    if (IsForegroundColorDefined() &&
+        (mForegroundColor != aOther.mForegroundColor))
+      return false;
+    if (IsBackgroundColorDefined() &&
+        (mBackgroundColor != aOther.mBackgroundColor))
+      return false;
+    if (IsUnderlineColorDefined() &&
+        (mUnderlineColor != aOther.mUnderlineColor))
+      return false;
+    return true;
+  }
+
+  bool operator !=(const TextRangeStyle &aOther)
+  {
+    return !Equals(aOther);
+  }
+
+  bool operator ==(const TextRangeStyle &aOther)
+  {
+    return Equals(aOther);
+  }
+
+  uint8_t mDefinedStyles;
+  uint8_t mLineStyle;        // DEFINED_LINESTYLE
+
+  bool mIsBoldLine;  // DEFINED_LINESTYLE
+
+  nscolor mForegroundColor;  // DEFINED_FOREGROUND_COLOR
+  nscolor mBackgroundColor;  // DEFINED_BACKGROUND_COLOR
+  nscolor mUnderlineColor;   // DEFINED_UNDERLINE_COLOR
+};
+
+/******************************************************************************
+ * mozilla::TextRange
+ ******************************************************************************/
+
+// Sync with nsIPrivateTextRange.h when you change these constants.
+#define NS_TEXTRANGE_CARETPOSITION         0x01
+#define NS_TEXTRANGE_RAWINPUT              0x02
+#define NS_TEXTRANGE_SELECTEDRAWTEXT       0x03
+#define NS_TEXTRANGE_CONVERTEDTEXT         0x04
+#define NS_TEXTRANGE_SELECTEDCONVERTEDTEXT 0x05
+
+struct TextRange
+{
+  TextRange() :
+    mStartOffset(0), mEndOffset(0), mRangeType(0)
+  {
+  }
+
+  uint32_t mStartOffset;
+  // XXX Storing end offset makes the initializing code very complicated.
+  //     We should replace it with mLength.
+  uint32_t mEndOffset;
+  uint32_t mRangeType;
+
+  TextRangeStyle mRangeStyle;
+
+  uint32_t Length() const { return mEndOffset - mStartOffset; }
+};
+
+/******************************************************************************
+ * mozilla::TextRangeArray
+ *
+ * XXX This should be replaced with nsTArray<TextRange>.
+ ******************************************************************************/
+
+typedef TextRange* TextRangeArray;
+
+} // namespace mozilla
+
+#endif // mozilla_TextRage_h_
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -6,18 +6,19 @@
 #ifndef NSWINDOW_H_
 #define NSWINDOW_H_
 
 #include "nsBaseWidget.h"
 #include "gfxPoint.h"
 #include "nsIIdleServiceInternal.h"
 #include "nsTArray.h"
 #include "AndroidJavaWrappers.h"
+#include "mozilla/EventForwards.h"
 #include "mozilla/StaticPtr.h"
-#include "mozilla/TextEvents.h"
+#include "mozilla/TextRange.h"
 
 class gfxASurface;
 
 struct ANPEvent;
 
 namespace mozilla {
     class AndroidGeckoEvent;
 
--- a/widget/gtk/nsDragService.cpp
+++ b/widget/gtk/nsDragService.cpp
@@ -17,16 +17,17 @@
 #include "prlog.h"
 #include "nsTArray.h"
 #include "nsPrimitiveHelpers.h"
 #include "prtime.h"
 #include "prthread.h"
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 #include "nsCRT.h"
+#include "mozilla/BasicEvents.h"
 #include "mozilla/Services.h"
 
 #include "gfxASurface.h"
 #include "gfxXlibSurface.h"
 #include "gfxContext.h"
 #include "nsImageToPixbuf.h"
 #include "nsPresContext.h"
 #include "nsIContent.h"
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -25,17 +25,17 @@
 
 #ifdef MOZ_X11
 #include <gdk/gdkx.h>
 #endif /* MOZ_X11 */
 
 #ifdef ACCESSIBILITY
 #include "mozilla/a11y/Accessible.h"
 #endif
-#include "mozilla/MouseEvents.h"
+#include "mozilla/EventForwards.h"
 
 #include "nsGtkIMModule.h"
 
 #undef LOG
 #ifdef MOZ_LOGGING
 
 // make sure that logging is enabled before including prlog.h
 #define FORCE_PR_LOG
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -113,16 +113,17 @@ EXPORTS.mozilla += [
     'BasicEvents.h',
     'ContentEvents.h',
     'EventClassList.h',
     'EventForwards.h',
     'LookAndFeel.h',
     'MiscEvents.h',
     'MouseEvents.h',
     'TextEvents.h',
+    'TextRange.h',
     'TouchEvents.h',
     'WidgetUtils.h',
 ]
 
 if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
     EXPORTS.mozilla += [
         'WidgetTraceEvent.h',
     ]
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -1,22 +1,24 @@
 /* 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 nsIWidgetListener_h__
 #define nsIWidgetListener_h__
 
-#include "nscore.h"
-#include "nsIXULWindow.h"
-#include "nsRegion.h"
-#include "mozilla/BasicEvents.h"
+#include <stdint.h>
+
+#include "mozilla/EventForwards.h"
 
 class nsView;
+class nsIntRegion;
 class nsIPresShell;
+class nsIWidget;
+class nsIXULWindow;
 
 /**
  * sizemode is an adjunct to widget size
  */
 enum nsSizeMode
 {
   nsSizeMode_Normal = 0,
   nsSizeMode_Minimized,
@@ -38,107 +40,106 @@ class nsIWidgetListener
 {
 public:
 
   /**
    * If this listener is for an nsIXULWindow, return it. If this is null, then
    * this is likely a listener for a view, which can be determined using
    * GetView. If both methods return null, this will be an nsWebBrowser.
    */
-  virtual nsIXULWindow* GetXULWindow() { return nullptr; }
+  virtual nsIXULWindow* GetXULWindow();
 
   /**
    * If this listener is for an nsView, return it.
    */
-  virtual nsView* GetView() { return nullptr; }
+  virtual nsView* GetView();
 
   /**
    * Return the presshell for this widget listener.
    */
-  virtual nsIPresShell* GetPresShell() { return nullptr; }
+  virtual nsIPresShell* GetPresShell();
 
   /**
    * Called when a window is moved to location (x, y). Returns true if the
    * notification was handled. Coordinates are outer window screen coordinates.
    */
-  virtual bool WindowMoved(nsIWidget* aWidget, int32_t aX, int32_t aY) { return false; }
+  virtual bool WindowMoved(nsIWidget* aWidget, int32_t aX, int32_t aY);
 
   /**
    * Called when a window is resized to (width, height). Returns true if the
    * notification was handled. Coordinates are outer window screen coordinates.
    */
-  virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) { return false; }
+  virtual bool WindowResized(nsIWidget* aWidget,
+                             int32_t aWidth, int32_t aHeight);
 
   /**
    * Called when the size mode (minimized, maximized, fullscreen) is changed.
    */
-  virtual void SizeModeChanged(nsSizeMode sizeMode) { }
+  virtual void SizeModeChanged(nsSizeMode aSizeMode);
 
   /**
    * Called when the z-order of the window is changed. Returns true if the
    * notification was handled. aPlacement indicates the new z order. If
    * placement is nsWindowZRelative, then aRequestBelow should be the
    * window to place below. On return, aActualBelow will be set to the
    * window actually behind. This generally only applies to Windows.
    */
-  virtual bool ZLevelChanged(bool aImmediate, nsWindowZ *aPlacement,
-                             nsIWidget* aRequestBelow, nsIWidget** aActualBelow) { return false; }
+  virtual bool ZLevelChanged(bool aImmediate, nsWindowZ* aPlacement,
+                             nsIWidget* aRequestBelow,
+                             nsIWidget** aActualBelow);
 
   /**
    * Called when the window is activated and focused.
    */
-  virtual void WindowActivated() { }
+  virtual void WindowActivated();
 
   /**
    * Called when the window is deactivated and no longer focused.
    */
-  virtual void WindowDeactivated() { }
+  virtual void WindowDeactivated();
 
   /**
    * Called when the show/hide toolbar button on the Mac titlebar is pressed.
    */
-  virtual void OSToolbarButtonPressed() { }
+  virtual void OSToolbarButtonPressed();
 
   /**
    * Called when a request is made to close the window. Returns true if the
    * notification was handled. Returns true if the notification was handled.
    */
-  virtual bool RequestWindowClose(nsIWidget* aWidget) { return false; }
+  virtual bool RequestWindowClose(nsIWidget* aWidget);
 
   /*
    * Indicate that a paint is about to occur on this window. This is called
    * at a time when it's OK to change the geometry of this widget or of
    * other widgets. Must be called before every call to PaintWindow.
    */
-  virtual void WillPaintWindow(nsIWidget* aWidget) { }
+  virtual void WillPaintWindow(nsIWidget* aWidget);
 
   /**
    * Paint the specified region of the window. Returns true if the
    * notification was handled.
    * This is called at a time when it is not OK to change the geometry of
    * this widget or of other widgets.
    */
-  virtual bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion) { return false; }
+  virtual bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion);
 
   /**
    * Indicates that a paint occurred.
    * This is called at a time when it is OK to change the geometry of
    * this widget or of other widgets.
    * Must be called after every call to PaintWindow.
    */
-  virtual void DidPaintWindow() { }
+  virtual void DidPaintWindow();
 
   /**
    * Request that layout schedules a repaint on the next refresh driver tick.
    */
-  virtual void RequestRepaint() { }
+  virtual void RequestRepaint();
 
   /**
    * Handle an event.
    */
   virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent,
-                                    bool aUseAttachedEvents)
-  {
-    return nsEventStatus_eIgnore;
-  }
+                                    bool aUseAttachedEvents);
 };
 
 #endif
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -2803,16 +2803,24 @@ nsWindow::GetDPI()
     if (heightInches < 0.25) {
         // Something's broken, but we'd better not crash.
         return 96.0f;
     }
 
     return float(rootWindow->height()/heightInches);
 }
 
+nsEventStatus
+nsWindow::DispatchEvent(WidgetGUIEvent* aEvent)
+{
+    nsEventStatus status;
+    DispatchEvent(aEvent, status);
+    return status;
+}
+
 void
 nsWindow::DispatchActivateEvent(void)
 {
     if (mWidgetListener)
       mWidgetListener->WindowActivated();
 }
 
 void
@@ -3165,8 +3173,42 @@ nsWindow::GetGLFrameBufferFormat()
 {
     if (mLayerManager &&
         mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
         return MozQGLWidgetWrapper::isRGBAContext() ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
     }
     return LOCAL_GL_NONE;
 }
 
+void
+nsWindow::ProcessMotionEvent()
+{
+    if (mPinchEvent.needDispatch) {
+        double distance = DistanceBetweenPoints(mPinchEvent.centerPoint,
+                                                mPinchEvent.touchPoint);
+        distance *= 2;
+        mPinchEvent.delta = distance - mPinchEvent.prevDistance;
+        nsIntPoint centerPoint(mPinchEvent.centerPoint.x(),
+                               mPinchEvent.centerPoint.y());
+        DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY_UPDATE,
+                             0, mPinchEvent.delta, centerPoint);
+        mPinchEvent.prevDistance = distance;
+    }
+    if (mMoveEvent.needDispatch) {
+        WidgetMouseEvent event(true, NS_MOUSE_MOVE, this,
+                               WidgetMouseEvent::eReal);
+
+        event.refPoint.x = nscoord(mMoveEvent.pos.x());
+        event.refPoint.y = nscoord(mMoveEvent.pos.y());
+
+        event.InitBasicModifiers(mMoveEvent.modifiers & Qt::ControlModifier,
+                                 mMoveEvent.modifiers & Qt::AltModifier,
+                                 mMoveEvent.modifiers & Qt::ShiftModifier,
+                                 mMoveEvent.modifiers & Qt::MetaModifier);
+        event.clickCount      = 0;
+
+        DispatchEvent(&event);
+        mMoveEvent.needDispatch = false;
+    }
+
+    mTimerStarted = false;
+}
+
--- a/widget/qt/nsWindow.h
+++ b/widget/qt/nsWindow.h
@@ -11,17 +11,17 @@
 #include <QKeyEvent>
 #include <QGestureEvent>
 #include <qgraphicswidget.h>
 #include <QTime>
 
 #include "nsAutoPtr.h"
 
 #include "nsBaseWidget.h"
-#include "mozilla/MouseEvents.h"
+#include "mozilla/EventForwards.h"
 
 #include "nsWeakReference.h"
 
 #include "nsGkAtoms.h"
 #include "nsIIdleServiceInternal.h"
 #include "nsIRunnable.h"
 #include "nsThreadUtils.h"
 
@@ -178,22 +178,17 @@ public:
     // event handling code
 
     void DispatchActivateEvent(void);
     void DispatchDeactivateEvent(void);
     void DispatchActivateEventOnTopLevelWindow(void);
     void DispatchDeactivateEventOnTopLevelWindow(void);
     void DispatchResizeEvent(nsIntRect &aRect, nsEventStatus &aStatus);
 
-    nsEventStatus DispatchEvent(mozilla::WidgetGUIEvent* aEvent)
-    {
-        nsEventStatus status;
-        DispatchEvent(aEvent, status);
-        return status;
-    }
+    nsEventStatus DispatchEvent(mozilla::WidgetGUIEvent* aEvent);
 
     // Some of the nsIWidget methods
     virtual bool IsEnabled() const;
 
     // called when we are destroyed
     void OnDestroy(void);
 
     // called to check and see if a widget's dimensions are sane
@@ -373,45 +368,17 @@ private:
         *flag &= ~mask;
     }
     int32_t mQCursor;
 
     // Call this function when the users activity is the direct cause of an
     // event (like a keypress or mouse click).
     void UserActivity();
 
-    inline void ProcessMotionEvent() {
-        if (mPinchEvent.needDispatch) {
-            double distance = DistanceBetweenPoints(mPinchEvent.centerPoint, mPinchEvent.touchPoint);
-            distance *= 2;
-            mPinchEvent.delta = distance - mPinchEvent.prevDistance;
-            nsIntPoint centerPoint(mPinchEvent.centerPoint.x(), mPinchEvent.centerPoint.y());
-            DispatchGestureEvent(NS_SIMPLE_GESTURE_MAGNIFY_UPDATE,
-                                 0, mPinchEvent.delta, centerPoint);
-            mPinchEvent.prevDistance = distance;
-        }
-        if (mMoveEvent.needDispatch) {
-            WidgetMouseEvent event(true, NS_MOUSE_MOVE, this,
-                                   WidgetMouseEvent::eReal);
-
-            event.refPoint.x = nscoord(mMoveEvent.pos.x());
-            event.refPoint.y = nscoord(mMoveEvent.pos.y());
-
-            event.InitBasicModifiers(mMoveEvent.modifiers & Qt::ControlModifier,
-                                     mMoveEvent.modifiers & Qt::AltModifier,
-                                     mMoveEvent.modifiers & Qt::ShiftModifier,
-                                     mMoveEvent.modifiers & Qt::MetaModifier);
-            event.clickCount      = 0;
-
-            DispatchEvent(&event);
-            mMoveEvent.needDispatch = false;
-        }
-
-        mTimerStarted = false;
-    }
+    inline void ProcessMotionEvent();
 
     void DispatchMotionToMainThread() {
         if (!mTimerStarted) {
             nsCOMPtr<nsIRunnable> event =
                 NS_NewRunnableMethod(this, &nsWindow::ProcessMotionEvent);
             NS_DispatchToMainThread(event);
             mTimerStarted = true;
         }
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -90,16 +90,48 @@ public:
   PRUnichar GetCompositeChar(PRUnichar aBaseChar) const;
 };
 
 
 /*****************************************************************************
  * mozilla::widget::ModifierKeyState
  *****************************************************************************/
 
+ModifierKeyState::ModifierKeyState()
+{
+  Update();
+}
+
+ModifierKeyState::ModifierKeyState(bool aIsShiftDown,
+                                   bool aIsControlDown,
+                                   bool aIsAltDown)
+{
+  Update();
+  Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT | MODIFIER_ALTGRAPH);
+  Modifiers modifiers = 0;
+  if (aIsShiftDown) {
+    modifiers |= MODIFIER_SHIFT;
+  }
+  if (aIsControlDown) {
+    modifiers |= MODIFIER_CONTROL;
+  }
+  if (aIsAltDown) {
+    modifiers |= MODIFIER_ALT;
+  }
+  if (modifiers) {
+    Set(modifiers);
+  }
+}
+
+ModifierKeyState::ModifierKeyState(Modifiers aModifiers) :
+  mModifiers(aModifiers)
+{
+  EnsureAltGr();
+}
+
 void
 ModifierKeyState::Update()
 {
   mModifiers = 0;
   if (IS_VK_DOWN(VK_SHIFT)) {
     mModifiers |= MODIFIER_SHIFT;
   }
   if (IS_VK_DOWN(VK_CONTROL)) {
@@ -120,16 +152,32 @@ ModifierKeyState::Update()
   if (::GetKeyState(VK_SCROLL) & 1) {
     mModifiers |= MODIFIER_SCROLLLOCK;
   }
 
   EnsureAltGr();
 }
 
 void
+ModifierKeyState::Unset(Modifiers aRemovingModifiers)
+{
+  mModifiers &= ~aRemovingModifiers;
+  // Note that we don't need to unset AltGr flag here automatically.
+  // For nsEditor, we need to remove Alt and Control flags but AltGr isn't
+  // checked in nsEditor, so, it can be kept.
+}
+
+void
+ModifierKeyState::Set(Modifiers aAddingModifiers)
+{
+  mModifiers |= aAddingModifiers;
+  EnsureAltGr();
+}
+
+void
 ModifierKeyState::InitInputEvent(WidgetInputEvent& aInputEvent) const
 {
   aInputEvent.modifiers = mModifiers;
 
   switch(aInputEvent.eventStructType) {
     case NS_MOUSE_EVENT:
     case NS_MOUSE_SCROLL_EVENT:
     case NS_WHEEL_EVENT:
@@ -165,16 +213,82 @@ ModifierKeyState::InitMouseEvent(WidgetI
   if (::GetKeyState(VK_XBUTTON1) < 0) {
     mouseEvent.buttons |= WidgetMouseEvent::e4thButtonFlag;
   }
   if (::GetKeyState(VK_XBUTTON2) < 0) {
     mouseEvent.buttons |= WidgetMouseEvent::e5thButtonFlag;
   }
 }
 
+bool
+ModifierKeyState::IsShift() const
+{
+  return (mModifiers & MODIFIER_SHIFT) != 0;
+}
+
+bool
+ModifierKeyState::IsControl() const
+{
+  return (mModifiers & MODIFIER_CONTROL) != 0;
+}
+
+bool
+ModifierKeyState::IsAlt() const
+{
+  return (mModifiers & MODIFIER_ALT) != 0;
+}
+
+bool
+ModifierKeyState::IsAltGr() const
+{
+  return IsControl() && IsAlt();
+}
+
+bool
+ModifierKeyState::IsWin() const
+{
+  return (mModifiers & MODIFIER_OS) != 0;
+}
+
+bool
+ModifierKeyState::IsCapsLocked() const
+{
+  return (mModifiers & MODIFIER_CAPSLOCK) != 0;
+}
+
+bool
+ModifierKeyState::IsNumLocked() const
+{
+  return (mModifiers & MODIFIER_NUMLOCK) != 0;
+}
+
+bool
+ModifierKeyState::IsScrollLocked() const
+{
+  return (mModifiers & MODIFIER_SCROLLLOCK) != 0;
+}
+
+Modifiers
+ModifierKeyState::GetModifiers() const
+{
+  return mModifiers;
+}
+
+void
+ModifierKeyState::EnsureAltGr()
+{
+  // If both Control key and Alt key are pressed, it means AltGr is pressed.
+  // Ideally, we should check whether the current keyboard layout has AltGr
+  // or not.  However, setting AltGr flags for keyboard which doesn't have
+  // AltGr must not be serious bug.  So, it should be OK for now.
+  if (IsAltGr()) {
+    mModifiers |= MODIFIER_ALTGRAPH;
+  }
+}
+
 /*****************************************************************************
  * mozilla::widget::UniCharsAndModifiers
  *****************************************************************************/
 
 void
 UniCharsAndModifiers::Append(PRUnichar aUniChar, Modifiers aModifiers)
 {
   MOZ_ASSERT(mLength < 5);
@@ -231,16 +345,60 @@ UniCharsAndModifiers::operator+(const Un
   result += aOther;
   return result;
 }
 
 /*****************************************************************************
  * mozilla::widget::VirtualKey
  *****************************************************************************/
 
+// static
+VirtualKey::ShiftState
+VirtualKey::ModifiersToShiftState(Modifiers aModifiers)
+{
+  ShiftState state = 0;
+  if (aModifiers & MODIFIER_SHIFT) {
+    state |= STATE_SHIFT;
+  }
+  if (aModifiers & MODIFIER_CONTROL) {
+    state |= STATE_CONTROL;
+  }
+  if (aModifiers & MODIFIER_ALT) {
+    state |= STATE_ALT;
+  }
+  if (aModifiers & MODIFIER_CAPSLOCK) {
+    state |= STATE_CAPSLOCK;
+  }
+  return state;
+}
+
+// static
+Modifiers
+VirtualKey::ShiftStateToModifiers(ShiftState aShiftState)
+{
+  Modifiers modifiers = 0;
+  if (aShiftState & STATE_SHIFT) {
+    modifiers |= MODIFIER_SHIFT;
+  }
+  if (aShiftState & STATE_CONTROL) {
+    modifiers |= MODIFIER_CONTROL;
+  }
+  if (aShiftState & STATE_ALT) {
+    modifiers |= MODIFIER_ALT;
+  }
+  if (aShiftState & STATE_CAPSLOCK) {
+    modifiers |= MODIFIER_CAPSLOCK;
+  }
+  if ((modifiers & (MODIFIER_ALT | MODIFIER_CONTROL)) ==
+         (MODIFIER_ALT | MODIFIER_CONTROL)) {
+    modifiers |= MODIFIER_ALTGRAPH;
+  }
+  return modifiers;
+}
+
 inline PRUnichar
 VirtualKey::GetCompositeChar(ShiftState aShiftState, PRUnichar aBaseChar) const
 {
   return mShiftStates[aShiftState].DeadKey.Table->GetCompositeChar(aBaseChar);
 }
 
 const DeadKeyTable*
 VirtualKey::MatchingDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
@@ -748,16 +906,22 @@ PRUnichar
 NativeKey::ComputeUnicharFromScanCode() const
 {
   return static_cast<PRUnichar>(
            ::MapVirtualKeyEx(ComputeVirtualKeyCodeFromScanCode(),
                              MAPVK_VK_TO_CHAR, mKeyboardLayout));
 }
 
 void
+NativeKey::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent) const
+{
+  InitKeyEvent(aKeyEvent, mModKeyState);
+}
+
+void
 NativeKey::InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
                         const ModifierKeyState& aModKeyState) const
 {
   nsIntPoint point(0, 0);
   mWidget->InitEvent(aKeyEvent, &point);
 
   switch (aKeyEvent.message) {
     case NS_KEY_DOWN:
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -6,16 +6,17 @@
 #ifndef KeyboardLayout_h__
 #define KeyboardLayout_h__
 
 #include "nscore.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsWindowBase.h"
 #include "nsWindowDefs.h"
+#include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
 #include <windows.h>
 
 #define NS_NUM_OF_KEYS          70
 
 #define VK_OEM_1                0xBA   // ';:' for US
 #define VK_OEM_PLUS             0xBB   // '+' any country
 #define VK_OEM_COMMA            0xBC
@@ -49,94 +50,46 @@ static const uint32_t sModifierKeyMap[][
   { nsIWidget::CTRL_L,    VK_CONTROL, VK_LCONTROL },
   { nsIWidget::CTRL_R,    VK_CONTROL, VK_RCONTROL },
   { nsIWidget::ALT_L,     VK_MENU,    VK_LMENU },
   { nsIWidget::ALT_R,     VK_MENU,    VK_RMENU }
 };
 
 class KeyboardLayout;
 
-class ModifierKeyState {
+class ModifierKeyState
+{
 public:
-  ModifierKeyState()
-  {
-    Update();
-  }
+  ModifierKeyState();
+  ModifierKeyState(bool aIsShiftDown, bool aIsControlDown, bool aIsAltDown);
+  ModifierKeyState(Modifiers aModifiers);
 
-  ModifierKeyState(bool aIsShiftDown, bool aIsControlDown, bool aIsAltDown)
-  {
-    Update();
-    Unset(MODIFIER_SHIFT | MODIFIER_CONTROL | MODIFIER_ALT | MODIFIER_ALTGRAPH);
-    Modifiers modifiers = 0;
-    if (aIsShiftDown) {
-      modifiers |= MODIFIER_SHIFT;
-    }
-    if (aIsControlDown) {
-      modifiers |= MODIFIER_CONTROL;
-    }
-    if (aIsAltDown) {
-      modifiers |= MODIFIER_ALT;
-    }
-    if (modifiers) {
-      Set(modifiers);
-    }
-  }
+  MOZ_ALWAYS_INLINE void Update();
 
-  ModifierKeyState(Modifiers aModifiers) :
-    mModifiers(aModifiers)
-  {
-    EnsureAltGr();
-  }
-
-  void Update();
-
-  void Unset(Modifiers aRemovingModifiers)
-  {
-    mModifiers &= ~aRemovingModifiers;
-    // Note that we don't need to unset AltGr flag here automatically.
-    // For nsEditor, we need to remove Alt and Control flags but AltGr isn't
-    // checked in nsEditor, so, it can be kept.
-  }
-
-  void Set(Modifiers aAddingModifiers)
-  {
-    mModifiers |= aAddingModifiers;
-    EnsureAltGr();
-  }
+  MOZ_ALWAYS_INLINE void Unset(Modifiers aRemovingModifiers);
+  MOZ_ALWAYS_INLINE void Set(Modifiers aAddingModifiers);
 
   void InitInputEvent(WidgetInputEvent& aInputEvent) const;
 
-  bool IsShift() const { return (mModifiers & MODIFIER_SHIFT) != 0; }
-  bool IsControl() const { return (mModifiers & MODIFIER_CONTROL) != 0; }
-  bool IsAlt() const { return (mModifiers & MODIFIER_ALT) != 0; }
-  bool IsAltGr() const { return IsControl() && IsAlt(); }
-  bool IsWin() const { return (mModifiers & MODIFIER_OS) != 0; }
+  MOZ_ALWAYS_INLINE bool IsShift() const;
+  MOZ_ALWAYS_INLINE bool IsControl() const;
+  MOZ_ALWAYS_INLINE bool IsAlt() const;
+  MOZ_ALWAYS_INLINE bool IsAltGr() const;
+  MOZ_ALWAYS_INLINE bool IsWin() const;
 
-  bool IsCapsLocked() const { return (mModifiers & MODIFIER_CAPSLOCK) != 0; }
-  bool IsNumLocked() const { return (mModifiers & MODIFIER_NUMLOCK) != 0; }
-  bool IsScrollLocked() const
-  {
-    return (mModifiers & MODIFIER_SCROLLLOCK) != 0;
-  }
+  MOZ_ALWAYS_INLINE bool IsCapsLocked() const;
+  MOZ_ALWAYS_INLINE bool IsNumLocked() const;
+  MOZ_ALWAYS_INLINE bool IsScrollLocked() const;
 
-  Modifiers GetModifiers() const { return mModifiers; }
+  MOZ_ALWAYS_INLINE Modifiers GetModifiers() const;
 
 private:
   Modifiers mModifiers;
 
-  void EnsureAltGr()
-  {
-    // If both Control key and Alt key are pressed, it means AltGr is pressed.
-    // Ideally, we should check whether the current keyboard layout has AltGr
-    // or not.  However, setting AltGr flags for keyboard which doesn't have
-    // AltGr must not be serious bug.  So, it should be OK for now.
-    if (IsAltGr()) {
-      mModifiers |= MODIFIER_ALTGRAPH;
-    }
-  }
+  MOZ_ALWAYS_INLINE void EnsureAltGr();
 
   void InitMouseEvent(WidgetInputEvent& aMouseEvent) const;
 };
 
 struct UniCharsAndModifiers
 {
   // Dead-key + up to 4 characters
   PRUnichar mChars[5];
@@ -191,55 +144,18 @@ public:
     STATE_SHIFT    = 0x01,
     STATE_CONTROL  = 0x02,
     STATE_ALT      = 0x04,
     STATE_CAPSLOCK = 0x08
   };
 
   typedef uint8_t ShiftState;
 
-  static ShiftState ModifiersToShiftState(Modifiers aModifiers)
-  {
-    ShiftState state = 0;
-    if (aModifiers & MODIFIER_SHIFT) {
-      state |= STATE_SHIFT;
-    }
-    if (aModifiers & MODIFIER_CONTROL) {
-      state |= STATE_CONTROL;
-    }
-    if (aModifiers & MODIFIER_ALT) {
-      state |= STATE_ALT;
-    }
-    if (aModifiers & MODIFIER_CAPSLOCK) {
-      state |= STATE_CAPSLOCK;
-    }
-    return state;
-  }
-
-  static Modifiers ShiftStateToModifiers(ShiftState aShiftState)
-  {
-    Modifiers modifiers = 0;
-    if (aShiftState & STATE_SHIFT) {
-      modifiers |= MODIFIER_SHIFT;
-    }
-    if (aShiftState & STATE_CONTROL) {
-      modifiers |= MODIFIER_CONTROL;
-    }
-    if (aShiftState & STATE_ALT) {
-      modifiers |= MODIFIER_ALT;
-    }
-    if (aShiftState & STATE_CAPSLOCK) {
-      modifiers |= MODIFIER_CAPSLOCK;
-    }
-    if ((modifiers & (MODIFIER_ALT | MODIFIER_CONTROL)) ==
-           (MODIFIER_ALT | MODIFIER_CONTROL)) {
-      modifiers |= MODIFIER_ALTGRAPH;
-    }
-    return modifiers;
-  }
+  static ShiftState ModifiersToShiftState(Modifiers aModifiers);
+  static Modifiers ShiftStateToModifiers(ShiftState aShiftState);
 
 private:
   union KeyShiftState
   {
     struct
     {
       PRUnichar Chars[4];
     } Normal;
@@ -423,20 +339,17 @@ private:
    */
   PRUnichar ComputeUnicharFromScanCode() const;
 
   /**
    * Initializes the aKeyEvent with the information stored in the instance.
    */
   void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
                     const ModifierKeyState& aModKeyState) const;
-  void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent) const
-  {
-    InitKeyEvent(aKeyEvent, mModKeyState);
-  }
+  void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent) const;
 
   /**
    * Dispatches the key event.  Returns true if the event is consumed.
    * Otherwise, false.
    */
   bool DispatchKeyEvent(WidgetKeyboardEvent& aKeyEvent,
                         const MSG* aMsgSentToPlugin = nullptr) const;
 
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -56,16 +56,17 @@ CPP_SOURCES += [
     'nsScreenManagerWin.cpp',
     'nsScreenWin.cpp',
     'nsSound.cpp',
     'nsToolkit.cpp',
     'nsUXThemeData.cpp',
     'nsWidgetFactory.cpp',
     'nsWinGesture.cpp',
     'nsWindow.cpp',
+    'nsWindowBase.cpp',
     'nsWindowDbg.cpp',
     'nsWindowGfx.cpp',
 ]
 
 if CONFIG['MOZ_CRASHREPORTER']:
     CPP_SOURCES += [
         'LSPAnnotator.cpp',
     ]
--- a/widget/windows/nsTextStore.h
+++ b/widget/windows/nsTextStore.h
@@ -8,17 +8,17 @@
 
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsITimer.h"
 #include "nsIWidget.h"
 #include "nsWindowBase.h"
 #include "mozilla/Attributes.h"
-#include "mozilla/TextEvents.h"
+#include "mozilla/TextRange.h"
 
 #include <msctf.h>
 #include <textstor.h>
 
 // GUID_PROP_INPUTSCOPE is declared in inputscope.h using INIT_GUID.
 // With initguid.h, we get its instance instead of extern declaration.
 #ifdef INPUTSCOPE_INIT_GUID
 #include <initguid.h>
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -167,16 +167,18 @@
 #include "nsCrashOnException.h"
 #include "nsIXULRuntime.h"
 
 #include "nsIContent.h"
 
 #include "mozilla/HangMonitor.h"
 #include "WinIMEHandler.h"
 
+#include "npapi.h"
+
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 using namespace mozilla::widget;
 
 /**************************************************************
  **************************************************************
  **
new file mode 100644
--- /dev/null
+++ b/widget/windows/nsWindowBase.cpp
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsWindowBase.h"
+
+#include "mozilla/MiscEvents.h"
+#include "npapi.h"
+
+using namespace mozilla;
+
+bool
+nsWindowBase::DispatchPluginEvent(const MSG& aMsg)
+{
+  if (!PluginHasFocus()) {
+    return false;
+  }
+  WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, this);
+  nsIntPoint point(0, 0);
+  InitEvent(pluginEvent, &point);
+  NPEvent npEvent;
+  npEvent.event = aMsg.message;
+  npEvent.wParam = aMsg.wParam;
+  npEvent.lParam = aMsg.lParam;
+  pluginEvent.pluginEvent = &npEvent;
+  pluginEvent.retargetToFocusedDocument = true;
+  return DispatchWindowEvent(&pluginEvent);
+}
--- a/widget/windows/nsWindowBase.h
+++ b/widget/windows/nsWindowBase.h
@@ -1,19 +1,18 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 nsWindowBase_h_
 #define nsWindowBase_h_
 
-#include "mozilla/MiscEvents.h"
+#include "mozilla/EventForwards.h"
 #include "nsBaseWidget.h"
-#include "npapi.h"
 #include <windows.h>
 
 /*
  * nsWindowBase - Base class of common methods other classes need to access
  * in both win32 and winrt window classes.
  */
 class nsWindowBase : public nsBaseWidget
 {
@@ -54,32 +53,17 @@ public:
    * is called by KeyboardLayout to dispatch gecko events.
    * Returns true if it's consumed.  Otherwise, false.
    */
   virtual bool DispatchKeyboardEvent(mozilla::WidgetGUIEvent* aEvent) = 0;
 
   /*
    * Default dispatch of a plugin event.
    */
-  virtual bool DispatchPluginEvent(const MSG &aMsg)
-  {
-    if (!PluginHasFocus()) {
-      return false;
-    }
-    mozilla::WidgetPluginEvent pluginEvent(true, NS_PLUGIN_INPUT_EVENT, this);
-    nsIntPoint point(0, 0);
-    InitEvent(pluginEvent, &point);
-    NPEvent npEvent;
-    npEvent.event = aMsg.message;
-    npEvent.wParam = aMsg.wParam;
-    npEvent.lParam = aMsg.lParam;
-    pluginEvent.pluginEvent = (void *)&npEvent;
-    pluginEvent.retargetToFocusedDocument = true;
-    return DispatchWindowEvent(&pluginEvent);
-  }
+  virtual bool DispatchPluginEvent(const MSG& aMsg);
 
   /*
    * Returns true if a plugin has focus on this widget.  Otherwise, false.
    */
   virtual bool PluginHasFocus() const MOZ_FINAL
   {
     return (mInputContext.mIMEState.mEnabled == IMEState::PLUGIN);
   }
--- a/widget/xpwidgets/moz.build
+++ b/widget/xpwidgets/moz.build
@@ -24,16 +24,17 @@ CPP_SOURCES += [
     'nsBaseDragService.cpp',
     'nsBaseScreen.cpp',
     'nsBaseWidget.cpp',
     'nsClipboardHelper.cpp',
     'nsClipboardPrivacyHandler.cpp',
     'nsFilePickerProxy.cpp',
     'nsHTMLFormatConverter.cpp',
     'nsIdleService.cpp',
+    'nsIWidgetListener.cpp',
     'nsPrimitiveHelpers.cpp',
     'nsPrintOptionsImpl.cpp',
     'nsPrintSession.cpp',
     'nsPrintSettingsImpl.cpp',
     'nsTransferable.cpp',
     'nsXPLookAndFeel.cpp',
 ]
 
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/nsIWidgetListener.cpp
@@ -0,0 +1,114 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsIWidgetListener.h"
+
+#include "nsRegion.h"
+#include "nsView.h"
+#include "nsIPresShell.h"
+#include "nsIWidget.h"
+#include "nsIXULWindow.h"
+
+#include "mozilla/BasicEvents.h"
+
+using namespace mozilla;
+
+nsIXULWindow*
+nsIWidgetListener::GetXULWindow()
+{
+  return nullptr;
+}
+
+nsView*
+nsIWidgetListener::GetView()
+{
+  return nullptr;
+}
+
+nsIPresShell*
+nsIWidgetListener::GetPresShell()
+{
+  return nullptr;
+}
+
+bool
+nsIWidgetListener::WindowMoved(nsIWidget* aWidget,
+                               int32_t aX,
+                               int32_t aY)
+{
+  return false;
+}
+
+bool
+nsIWidgetListener::WindowResized(nsIWidget* aWidget,
+                                 int32_t aWidth,
+                                 int32_t aHeight)
+{
+  return false;
+}
+
+void
+nsIWidgetListener::SizeModeChanged(nsSizeMode aSizeMode)
+{
+}
+
+bool
+nsIWidgetListener::ZLevelChanged(bool aImmediate,
+                                 nsWindowZ* aPlacement,
+                                 nsIWidget* aRequestBelow,
+                                 nsIWidget** aActualBelow)
+{
+  return false;
+}
+
+void
+nsIWidgetListener::WindowActivated()
+{
+}
+
+void
+nsIWidgetListener::WindowDeactivated()
+{
+}
+
+void
+nsIWidgetListener::OSToolbarButtonPressed()
+{
+}
+
+bool
+nsIWidgetListener::RequestWindowClose(nsIWidget* aWidget)
+{
+  return false;
+}
+
+void
+nsIWidgetListener::WillPaintWindow(nsIWidget* aWidget)
+{
+}
+
+bool
+nsIWidgetListener::PaintWindow(nsIWidget* aWidget,
+                               nsIntRegion aRegion)
+{
+  return false;
+}
+
+void
+nsIWidgetListener::DidPaintWindow()
+{
+}
+
+void
+nsIWidgetListener::RequestRepaint()
+{
+}
+
+nsEventStatus
+nsIWidgetListener::HandleEvent(WidgetGUIEvent* aEvent,
+                               bool aUseAttachedEvents)
+{
+  return nsEventStatus_eIgnore;
+}
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -1,22 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=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 "nsISupports.idl"
 
-interface nsISimpleEnumerator;
+interface nsICancelableRunnable;
+interface nsIDOMWindow;
 interface nsIRunnable;
-interface nsICancelableRunnable;
+interface nsISimpleEnumerator;
 
 /*
- * Memory reporters measure Firefox's memory usage.  They are mainly used to
+ * Memory reporters measure Firefox's memory usage.  They are primarily used to
  * generate the about:memory page.  You should read
  * https://wiki.mozilla.org/Memory_Reporting before writing a memory
  * reporter.
  */
 
 [scriptable, function, uuid(3a61be3b-b93b-461a-a4f8-388214f558b1)]
 interface nsIMemoryReporterCallback : nsISupports
 {
@@ -303,22 +304,42 @@ interface nsIMemoryReporterManager : nsI
   [infallible] readonly attribute boolean hasMozMallocUsableSize;
 
   /*
    * Run a series of GC/CC's in an attempt to minimize the application's memory
    * usage.  When we're finished, we invoke the given runnable if it's not
    * null.  Returns a reference to the runnable used for carrying out the task.
    */
   nsICancelableRunnable minimizeMemoryUsage(in nsIRunnable callback);
+
+  /*
+   * Measure the memory that is known to be owned by this tab, split up into
+   * several broad categories.  Note that this will be an underestimate of the
+   * true number, due to imperfect memory reporter coverage (corresponding to
+   * about:memory's "heap-unclassified"), and due to some memory shared between
+   * tabs not being counted.
+   *
+   * The time taken for the measurement (split into JS and non-JS parts) is
+   * also returned.
+   */
+  void sizeOfTab(in nsIDOMWindow window,
+                 out int64_t jsObjectsSize, out int64_t jsStringsSize,
+                 out int64_t jsOtherSize, out int64_t domSize,
+                 out int64_t styleSize, out int64_t otherSize,
+                 out int64_t totalSize,
+                 out double jsMilliseconds, out double nonJSMilliseconds);
 };
 
 %{C++
 
+#include "js/TypeDecls.h"
 #include "nsStringGlue.h"
 
+class nsPIDOMWindow;
+
 // Note that the memory reporters are held in an nsCOMArray, which means
 // that individual reporters should be referenced with |nsIMemoryReporter *|
 // instead of nsCOMPtr<nsIMemoryReporter>.
 
 XPCOM_API(nsresult) NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter);
 XPCOM_API(nsresult) NS_UnregisterMemoryReporter(nsIMemoryReporter* aReporter);
 
 namespace mozilla {
@@ -350,16 +371,31 @@ DECL_UNREGISTER_DISTINGUISHED_AMOUNT(Sto
 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsVirtual)
 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsPhysical)
 
 DECL_REGISTER_DISTINGUISHED_AMOUNT(Infallible, GhostWindows)
 
 #undef DECL_REGISTER_DISTINGUISHED_AMOUNT
 #undef DECL_UNREGISTER_DISTINGUISHED_AMOUNT
 
+// Likewise for per-tab measurement.
+
+typedef nsresult (*JSSizeOfTabFn)(JSObject* aObj,
+                                  size_t* aJsObjectsSize,
+                                  size_t* aJsStringSize,
+                                  size_t* aJsPrivateSize,
+                                  size_t* aJsOtherSize);
+typedef nsresult (*NonJSSizeOfTabFn)(nsPIDOMWindow* aWindow,
+                                     size_t* aDomSize,
+                                     size_t* aStyleSize,
+                                     size_t* aOtherSize);
+
+nsresult RegisterJSSizeOfTab(JSSizeOfTabFn aSizeOfTabFn);
+nsresult RegisterNonJSSizeOfTab(NonJSSizeOfTabFn aSizeOfTabFn);
+
 }
 
 #if defined(MOZ_DMD)
 namespace mozilla {
 namespace dmd {
 // This runs all the memory reporters but does nothing with the results;  i.e.
 // it does the minimal amount of work possible for DMD to do its thing.
 void RunReporters();
--- a/xpcom/base/nsMemoryInfoDumper.cpp
+++ b/xpcom/base/nsMemoryInfoDumper.cpp
@@ -605,29 +605,30 @@ namespace mozilla {
 
 #define DUMP(o, s) \
   do { \
     nsresult rv = (o)->Write(s); \
     NS_ENSURE_SUCCESS(rv, rv); \
   } while (0)
 
 static nsresult
-DumpReport(nsIGZFileWriter *aWriter, bool aIsFirst,
+DumpReport(nsIGZFileWriter *aWriter, bool *aIsFirstPtr,
   const nsACString &aProcess, const nsACString &aPath, int32_t aKind,
   int32_t aUnits, int64_t aAmount, const nsACString &aDescription)
 {
-  DUMP(aWriter, aIsFirst ? "[" : ",");
-
   // We only want to dump reports for this process.  If |aProcess| is
   // non-nullptr that means we've received it from another process in response
   // to a "child-memory-reporter-request" event;  ignore such reports.
   if (!aProcess.IsEmpty()) {
     return NS_OK;
   }
 
+  DUMP(aWriter, *aIsFirstPtr ? "[" : ",");
+  *aIsFirstPtr = false;
+
   // Generate the process identifier, which is of the form "$PROCESS_NAME
   // (pid $PID)", or just "(pid $PID)" if we don't have a process name.  If
   // we're the main process, we let $PROCESS_NAME be "Main Process".
   nsAutoCString processId;
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     // We're the main process.
     processId.AssignLiteral("Main Process ");
   } else if (ContentChild *cc = ContentChild::GetSingleton()) {
@@ -673,37 +674,32 @@ DumpReport(nsIGZFileWriter *aWriter, boo
   return NS_OK;
 }
 
 class DumpReporterCallback MOZ_FINAL : public nsIMemoryReporterCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
-  DumpReporterCallback(bool* aIsFirstPtr) : mIsFirstPtr(aIsFirstPtr) {}
+  DumpReporterCallback() : mIsFirst(true) {}
 
   NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
       int32_t aKind, int32_t aUnits, int64_t aAmount,
       const nsACString &aDescription,
       nsISupports *aData)
   {
     nsCOMPtr<nsIGZFileWriter> writer = do_QueryInterface(aData);
     NS_ENSURE_TRUE(writer, NS_ERROR_FAILURE);
 
-    // The |isFirst = false| assumes that at least one single reporter is
-    // present and so will have been processed in
-    // DumpProcessMemoryReportsToGZFileWriter() below.
-    bool isFirst = *mIsFirstPtr;
-    *mIsFirstPtr = false;
-    return DumpReport(writer, isFirst, aProcess, aPath, aKind, aUnits, aAmount,
-                      aDescription);
+    return DumpReport(writer, &mIsFirst, aProcess, aPath, aKind, aUnits,
+                      aAmount, aDescription);
   }
 
 private:
-  bool* mIsFirstPtr;
+  bool mIsFirst;
 };
 
 NS_IMPL_ISUPPORTS1(DumpReporterCallback, nsIMemoryReporterCallback)
 
 } // namespace mozilla
 
 static void
 MakeFilename(const char *aPrefix, const nsAString &aIdentifier,
@@ -812,21 +808,20 @@ DumpProcessMemoryReportsToGZFileWriter(n
     do_GetService("@mozilla.org/memory-reporter-manager;1");
   NS_ENSURE_STATE(mgr);
 
   DUMP(aWriter, mgr->GetHasMozMallocUsableSize() ? "true" : "false");
   DUMP(aWriter, ",\n");
   DUMP(aWriter, "  \"reports\": ");
 
   // Process reporters.
-  bool isFirst = true;
   bool more;
   nsCOMPtr<nsISimpleEnumerator> e;
   mgr->EnumerateReporters(getter_AddRefs(e));
-  nsRefPtr<DumpReporterCallback> cb = new DumpReporterCallback(&isFirst);
+  nsRefPtr<DumpReporterCallback> cb = new DumpReporterCallback();
   while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
     nsCOMPtr<nsIMemoryReporter> r;
     e->GetNext(getter_AddRefs(r));
     r->CollectReports(cb, aWriter);
   }
 
   DUMP(aWriter, "\n  ]\n}\n");
 
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -7,17 +7,20 @@
 #include "nsAtomTable.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsServiceManagerUtils.h"
 #include "nsMemoryReporterManager.h"
 #include "nsISimpleEnumerator.h"
 #include "nsThreadUtils.h"
+#include "nsIDOMWindow.h"
+#include "nsPIDOMWindow.h"
 #include "nsIObserverService.h"
+#include "nsIGlobalObject.h"
 #if defined(XP_LINUX)
 #include "nsMemoryInfoDumper.h"
 #endif
 #include "mozilla/Attributes.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 
@@ -840,16 +843,17 @@ HashtableEnumerator::GetNext(nsISupports
 
 } // anonymous namespace
 
 nsMemoryReporterManager::nsMemoryReporterManager()
   : mMutex("nsMemoryReporterManager::mMutex"),
     mIsRegistrationBlocked(false)
 {
     PodZero(&mAmountFns);
+    PodZero(&mSizeOfTabFns);
 }
 
 nsMemoryReporterManager::~nsMemoryReporterManager()
 {
 }
 
 NS_IMETHODIMP
 nsMemoryReporterManager::EnumerateReporters(nsISimpleEnumerator** aResult)
@@ -1262,16 +1266,66 @@ nsMemoryReporterManager::MinimizeMemoryU
 
   nsRefPtr<nsICancelableRunnable> runnable =
     new MinimizeMemoryUsageRunnable(aCallback);
   NS_ADDREF(*aResult = runnable);
 
   return NS_DispatchToMainThread(runnable);
 }
 
+NS_IMETHODIMP
+nsMemoryReporterManager::SizeOfTab(nsIDOMWindow* aTopWindow,
+                                   int64_t* aJSObjectsSize,
+                                   int64_t* aJSStringsSize,
+                                   int64_t* aJSOtherSize,
+                                   int64_t* aDomSize,
+                                   int64_t* aStyleSize,
+                                   int64_t* aOtherSize,
+                                   int64_t* aTotalSize,
+                                   double*  aJSMilliseconds,
+                                   double*  aNonJSMilliseconds)
+{
+    nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aTopWindow);
+    nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(aTopWindow);
+    NS_ENSURE_TRUE(!!global && !!piWindow, NS_ERROR_FAILURE);
+
+    TimeStamp t1 = TimeStamp::Now();
+
+    // Measure JS memory consumption (and possibly some non-JS consumption, via
+    // |jsPrivateSize|).
+    size_t jsObjectsSize, jsStringsSize, jsPrivateSize, jsOtherSize;
+    nsresult rv = mSizeOfTabFns.mJS(global->GetGlobalJSObject(),
+                                    &jsObjectsSize, &jsStringsSize,
+                                    &jsPrivateSize, &jsOtherSize);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    TimeStamp t2 = TimeStamp::Now();
+
+    // Measure non-JS memory consumption.
+    size_t domSize, styleSize, otherSize;
+    mSizeOfTabFns.mNonJS(piWindow, &domSize, &styleSize, &otherSize);
+
+    TimeStamp t3 = TimeStamp::Now();
+
+    *aTotalSize = 0;
+    #define DO(aN, n) { *aN = (n); *aTotalSize += (n); }
+    DO(aJSObjectsSize, jsObjectsSize);
+    DO(aJSStringsSize, jsStringsSize);
+    DO(aJSOtherSize,   jsOtherSize);
+    DO(aDomSize,       jsPrivateSize + domSize);
+    DO(aStyleSize,     styleSize);
+    DO(aOtherSize,     otherSize);
+    #undef DO
+
+    *aJSMilliseconds    = (t2 - t1).ToMilliseconds();
+    *aNonJSMilliseconds = (t3 - t2).ToMilliseconds();
+
+    return NS_OK;
+}
+
 // Most memory reporters don't need thread safety, but some do.  Make them all
 // thread-safe just to be safe.  Memory reporters are created and destroyed
 // infrequently enough that the performance cost should be negligible.
 NS_IMPL_ISUPPORTS1(MemoryUniReporter, nsIMemoryReporter)
 
 nsresult
 NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter)
 {
@@ -1289,44 +1343,41 @@ NS_UnregisterMemoryReporter(nsIMemoryRep
     if (!mgr) {
         return NS_ERROR_FAILURE;
     }
     return mgr->UnregisterReporter(aReporter);
 }
 
 namespace mozilla {
 
+#define GET_MEMORY_REPORTER_MANAGER(mgr)                                      \
+    nsCOMPtr<nsIMemoryReporterManager> imgr =                                 \
+        do_GetService("@mozilla.org/memory-reporter-manager;1");              \
+    nsRefPtr<nsMemoryReporterManager> mgr =                                   \
+        static_cast<nsMemoryReporterManager*>(imgr.get());                    \
+    if (!mgr) {                                                               \
+        return NS_ERROR_FAILURE;                                              \
+    }
+
 // Macro for generating functions that register distinguished amount functions
 // with the memory reporter manager.
 #define DEFINE_REGISTER_DISTINGUISHED_AMOUNT(kind, name)                      \
     nsresult                                                                  \
     Register##name##DistinguishedAmount(kind##AmountFn aAmountFn)             \
     {                                                                         \
-        nsCOMPtr<nsIMemoryReporterManager> imgr =                             \
-            do_GetService("@mozilla.org/memory-reporter-manager;1");          \
-        nsRefPtr<nsMemoryReporterManager> mgr =                               \
-            static_cast<nsMemoryReporterManager*>(imgr.get());                \
-        if (!mgr) {                                                           \
-            return NS_ERROR_FAILURE;                                          \
-        }                                                                     \
+        GET_MEMORY_REPORTER_MANAGER(mgr)                                      \
         mgr->mAmountFns.m##name = aAmountFn;                                  \
         return NS_OK;                                                         \
     }
 
 #define DEFINE_UNREGISTER_DISTINGUISHED_AMOUNT(name)                          \
     nsresult                                                                  \
     Unregister##name##DistinguishedAmount()                                   \
     {                                                                         \
-        nsCOMPtr<nsIMemoryReporterManager> imgr =                             \
-            do_GetService("@mozilla.org/memory-reporter-manager;1");          \
-        nsRefPtr<nsMemoryReporterManager> mgr =                               \
-            static_cast<nsMemoryReporterManager*>(imgr.get());                \
-        if (!mgr) {                                                           \
-            return NS_ERROR_FAILURE;                                          \
-        }                                                                     \
+        GET_MEMORY_REPORTER_MANAGER(mgr)                                      \
         mgr->mAmountFns.m##name = nullptr;                                    \
         return NS_OK;                                                         \
     }
 
 DEFINE_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeGCHeap)
 DEFINE_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeTemporaryPeak)
 DEFINE_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeCompartmentsSystem)
 DEFINE_REGISTER_DISTINGUISHED_AMOUNT(Infallible, JSMainRuntimeCompartmentsUser)
@@ -1339,16 +1390,32 @@ DEFINE_UNREGISTER_DISTINGUISHED_AMOUNT(S
 DEFINE_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsVirtual)
 DEFINE_REGISTER_DISTINGUISHED_AMOUNT(Infallible, LowMemoryEventsPhysical)
 
 DEFINE_REGISTER_DISTINGUISHED_AMOUNT(Infallible, GhostWindows)
 
 #undef DEFINE_REGISTER_DISTINGUISHED_AMOUNT
 #undef DEFINE_UNREGISTER_DISTINGUISHED_AMOUNT
 
+#define DEFINE_REGISTER_SIZE_OF_TAB(name)                                     \
+    nsresult                                                                  \
+    Register##name##SizeOfTab(name##SizeOfTabFn aSizeOfTabFn)                 \
+    {                                                                         \
+        GET_MEMORY_REPORTER_MANAGER(mgr)                                      \
+        mgr->mSizeOfTabFns.m##name = aSizeOfTabFn;                            \
+        return NS_OK;                                                         \
+    }
+
+DEFINE_REGISTER_SIZE_OF_TAB(JS);
+DEFINE_REGISTER_SIZE_OF_TAB(NonJS);
+
+#undef DEFINE_REGISTER_SIZE_OF_TAB
+
+#undef GET_MEMORY_REPORTER_MANAGER
+
 }
 
 #if defined(MOZ_DMD)
 
 namespace mozilla {
 namespace dmd {
 
 class NullReporterCallback : public nsIMemoryReporterCallback
--- a/xpcom/base/nsMemoryReporterManager.h
+++ b/xpcom/base/nsMemoryReporterManager.h
@@ -34,16 +34,23 @@ public:
 
     mozilla::InfallibleAmountFn mLowMemoryEventsVirtual;
     mozilla::InfallibleAmountFn mLowMemoryEventsPhysical;
 
     mozilla::InfallibleAmountFn mGhostWindows;
   };
   AmountFns mAmountFns;
 
+  // Functions that measure per-tab memory consumption.
+  struct SizeOfTabFns {
+    mozilla::JSSizeOfTabFn    mJS;
+    mozilla::NonJSSizeOfTabFn mNonJS;
+  };
+  SizeOfTabFns mSizeOfTabFns;
+
 private:
   nsresult RegisterReporterHelper(nsIMemoryReporter *aReporter, bool aForce);
 
   nsTHashtable<nsISupportsHashKey> mReporters;
   Mutex mMutex;
   bool mIsRegistrationBlocked;
 };
 
--- a/xpcom/glue/nsTArray.h
+++ b/xpcom/glue/nsTArray.h
@@ -58,17 +58,17 @@ class Heap;
 // elements and has the following requirements:
 //
 //   T MUST be safely memmove()'able.
 //   T MUST define a copy-constructor.
 //   T MAY define operator< for sorting.
 //   T MAY define operator== for searching.
 //
 // (Note that the memmove requirement may be relaxed for certain types - see
-// nsTArray_CopyElements below.)
+// nsTArray_CopyChooser below.)
 //
 // For methods taking a Comparator instance, the Comparator must be a class
 // defining the following methods:
 //
 //   class Comparator {
 //     public:
 //       /** @return True if the elements are equals; false otherwise. */
 //       bool Equals(const elem_type& a, const Item& b) const;
@@ -568,17 +568,17 @@ struct AssignRangeAlgorithm<true, true> 
   static void implementation(ElemType* elements, IndexType start,
                              SizeType count, const Item *values) {
     memcpy(elements + start, values, count * sizeof(ElemType));
   }
 };
 
 //
 // Normally elements are copied with memcpy and memmove, but for some element
-// types that is problematic.  The nsTArray_CopyElements template class can be
+// types that is problematic.  The nsTArray_CopyChooser template class can be
 // specialized to ensure that copying calls constructors and destructors
 // instead, as is done below for JS::Heap<E> elements.
 //
 
 //
 // A class that defines how to copy elements using memcpy/memmove.
 //
 struct nsTArray_CopyWithMemutils
@@ -653,24 +653,28 @@ struct nsTArray_CopyWithConstructors
     }
   }
 };
 
 //
 // The default behaviour is to use memcpy/memmove for everything.
 //
 template <class E>
-struct nsTArray_CopyElements : public nsTArray_CopyWithMemutils {};
+struct nsTArray_CopyChooser {
+  typedef nsTArray_CopyWithMemutils Type;
+};
 
 //
 // JS::Heap<E> elements require constructors/destructors to be called and so is
 // specialized here.
 //
 template <class E>
-struct nsTArray_CopyElements<JS::Heap<E> > : public nsTArray_CopyWithConstructors<E> {};
+struct nsTArray_CopyChooser<JS::Heap<E> > {
+  typedef nsTArray_CopyWithConstructors<E> Type;
+};
 
 //
 // Base class for nsTArray_Impl that is templated on element type and derived
 // nsTArray_Impl class, to allow extra conversions to be added for specific
 // types.
 //
 template <class E, class Derived>
 struct nsTArray_TypedBase : public nsTArray_SafeElementAtHelper<E, Derived> {};
@@ -712,21 +716,21 @@ struct nsTArray_TypedBase<JS::Heap<E>, D
 // is if you're writing code which mutates a TArray which may or may not be
 // infallible.
 //
 // Code which merely reads from a TArray which may or may not be infallible can
 // simply cast the TArray to |const nsTArray&|; both fallible and infallible
 // TArrays can be cast to |const nsTArray&|.
 //
 template<class E, class Alloc>
-class nsTArray_Impl : public nsTArray_base<Alloc, nsTArray_CopyElements<E> >,
+class nsTArray_Impl : public nsTArray_base<Alloc, typename nsTArray_CopyChooser<E>::Type>,
                       public nsTArray_TypedBase<E, nsTArray_Impl<E, Alloc> >
 {
 public:
-  typedef nsTArray_CopyElements<E>                   copy_type;
+  typedef typename nsTArray_CopyChooser<E>::Type     copy_type;
   typedef nsTArray_base<Alloc, copy_type>            base_type;
   typedef typename base_type::size_type              size_type;
   typedef typename base_type::index_type             index_type;
   typedef E                                          elem_type;
   typedef nsTArray_Impl<E, Alloc>                    self_type;
   typedef nsTArrayElementTraits<E>                   elem_traits;
   typedef nsTArray_SafeElementAtHelper<E, self_type> safeelementat_helper_type;
 
--- a/xpfe/appshell/src/nsAppShellService.cpp
+++ b/xpfe/appshell/src/nsAppShellService.cpp
@@ -18,17 +18,19 @@
 #include "nsPIWindowWatcher.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsWebShellWindow.h"
 
 #include "nsCRT.h"
 #include "prprf.h"
 
+#include "nsWidgetInitData.h"
 #include "nsWidgetsCID.h"
+#include "nsIWidget.h"
 #include "nsIRequestObserver.h"
 
 /* For implementing GetHiddenWindowAndJSContext */
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "jsapi.h"
 
 #include "nsAppShellService.h"
--- a/xpfe/appshell/src/nsChromeTreeOwner.cpp
+++ b/xpfe/appshell/src/nsChromeTreeOwner.cpp
@@ -14,16 +14,17 @@
 #include "nsIServiceManager.h"
 #include "nsIDocShellTreeItem.h"
 
 // Interfaces needed to include
 #include "nsIPrompt.h"
 #include "nsIAuthPrompt.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsIWebProgress.h"
+#include "nsIWidget.h"
 #include "nsIWindowMediator.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMXULElement.h"
 #include "nsIXULBrowserWindow.h"
 #include "mozilla/dom/Element.h"
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/src/nsContentTreeOwner.cpp
@@ -29,16 +29,17 @@
 #include "nsIXULBrowserWindow.h"
 #include "nsIPrincipal.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIWebNavigation.h"
 #include "nsDocShellCID.h"
 #include "nsIExternalURLHandlerService.h"
 #include "nsIMIMEInfo.h"
+#include "nsIWidget.h"
 #include "mozilla/BrowserElementParent.h"
 
 #include "nsIDOMDocument.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #if defined(XP_MACOSX)
 #include "nsThreadUtils.h"
--- a/xpfe/appshell/src/nsWebShellWindow.cpp
+++ b/xpfe/appshell/src/nsWebShellWindow.cpp
@@ -21,16 +21,17 @@
 
 #include "nsEscape.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsIWindowWatcher.h"
 
 #include "nsIDOMXULElement.h"
 
+#include "nsWidgetInitData.h"
 #include "nsWidgetsCID.h"
 #include "nsIWidget.h"
 #include "nsIWidgetListener.h"
 
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMNodeList.h"
 
 #include "nsITimer.h"
--- a/xpfe/appshell/src/nsWebShellWindow.h
+++ b/xpfe/appshell/src/nsWebShellWindow.h
@@ -11,16 +11,18 @@
 #include "nsITimer.h"
 #include "nsCOMPtr.h"
 #include "nsXULWindow.h"
 #include "nsIWidgetListener.h"
 
 /* Forward declarations.... */
 class nsIURI;
 
+struct nsWidgetInitData;
+
 namespace mozilla {
 class WebShellWindowTimerCallback;
 } // namespace mozilla
 
 class nsWebShellWindow : public nsXULWindow,
                          public nsIWebProgressListener,
                          public nsIWidgetListener
 {
--- a/xpfe/appshell/src/nsXULWindow.h
+++ b/xpfe/appshell/src/nsXULWindow.h
@@ -12,16 +12,17 @@
 #include "nsContentTreeOwner.h"
 
 // Helper classes
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsString.h"
 #include "nsWeakReference.h"
 #include "nsCOMArray.h"
+#include "nsRect.h"
 
 // Interfaces needed
 #include "nsIBaseWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDOMWindow.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"