Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Tue, 29 Oct 2013 19:20:42 -0700
changeset 152663 829d7bef8b0a6d2cda14cfdc0fd0061fdedb0dd7
parent 152662 cdfe0db3e7620b96e43efdf2714fbfe61954713f (current diff)
parent 152654 35b73bb96ca0a7eea38a022ae63505857eb8132b (diff)
child 152683 747923d3bc466bc00a362a93d7531fc4ad3e53c4
child 161482 fe534998400415f1a10e999076392e21840de6b4
push id25557
push userrnewman@mozilla.com
push dateWed, 30 Oct 2013 02:21:21 +0000
treeherdermozilla-central@829d7bef8b0a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.0a1
first release with
nightly linux32
829d7bef8b0a / 28.0a1 / 20131030030201 / files
nightly linux64
829d7bef8b0a / 28.0a1 / 20131030030201 / files
nightly mac
829d7bef8b0a / 28.0a1 / 20131030030201 / files
nightly win32
829d7bef8b0a / 28.0a1 / 20131030030201 / files
nightly win64
829d7bef8b0a / 28.0a1 / 20131030030201 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to s-c.
accessible/src/base/nsAccessNode.cpp
accessible/src/base/nsAccessNode.h
layout/reftests/forms/input/color/testcase-style.css
media/mtransport/third_party/Makefile.in
media/webrtc/Makefile.in
mobile/android/base/BrowserApp.java
netwerk/protocol/app/AppProtocolHandler.js
netwerk/protocol/app/AppProtocolHandler.manifest
toolkit/mozapps/update/tests/unit_aus_update/downloadMar.js
--- a/Makefile.in
+++ b/Makefile.in
@@ -27,19 +27,19 @@ include $(topsrcdir)/config/config.mk
 GARBAGE_DIRS += dist _javagen _profile staticlib
 DIST_GARBAGE = config.cache config.log config.status* config-defs.h \
    config/autoconf.mk \
    mozilla-config.h \
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    .mozconfig.mk
 
 ifndef MOZ_PROFILE_USE
-# We need to explicitly put backend.RecursiveMakeBackend.built here
+# We need to explicitly put backend.RecursiveMakeBackend here
 # otherwise the rule in rules.mk doesn't run early enough.
-libs binaries export tools:: CLOBBER $(topsrcdir)/configure config.status backend.RecursiveMakeBackend.built
+libs binaries export tools:: CLOBBER $(topsrcdir)/configure config.status backend.RecursiveMakeBackend
 ifndef LIBXUL_SDK
 libs binaries export tools:: js-config-status
 endif
 endif
 
 CLOBBER: $(topsrcdir)/CLOBBER
 	@echo "STOP!  The CLOBBER file has changed."
 	@echo "Please run the build through a sanctioned build wrapper, such as"
@@ -58,25 +58,25 @@ config.status: $(topsrcdir)/configure
 	@echo "Please rerun configure."
 	@echo "To ignore this message, touch 'config.status' in the build directory,"
 	@echo "but your build might not succeed."
 	@exit 1
 
 ifndef LIBXUL_SDK
 .PHONY: js-config-status
 js-config-status:
-	$(call SUBMAKE,backend.RecursiveMakeBackend.built,js/src,1)
+	$(call SUBMAKE,backend.RecursiveMakeBackend,js/src,1)
 endif
 
 install_manifests := bin idl include public private sdk
 install_manifest_depends = \
   CLOBBER \
   $(topsrcdir)/configure \
   config.status \
-  backend.RecursiveMakeBackend.built \
+  backend.RecursiveMakeBackend \
   $(NULL)
 
 ifndef LIBXUL_SDK
 install_manifest_depends += js-config-status
 endif
 
 .PHONY: install-manifests
 install-manifests: $(addprefix install-dist-,$(install_manifests))
--- a/accessible/public/msaa/ISimpleDOMNode.idl
+++ b/accessible/public/msaa/ISimpleDOMNode.idl
@@ -79,17 +79,17 @@ cpp_quote("// DOM navigation - get a dif
 cpp_quote("//")
 cpp_quote("// get_innerHTML(/* [out] */ BSTR *htmlText);")
 cpp_quote("// ---------------------------------------------------------------------------------------------------=")
 cpp_quote("// Returns HTML of this DOM node's subtree. Does not include the start and end tag for this node/element.")
 cpp_quote("//")
 cpp_quote("//")
 cpp_quote("// get_localInterface(/* [out] */ void **localInterface);")
 cpp_quote("// ---------------------------------------------------------------------------------------------------=")
-cpp_quote("// Only available in Gecko's process - casts to an XPCOM nsAccessNode object pointer")
+cpp_quote("// Only available in Gecko's process")
 cpp_quote("//")
 cpp_quote("//")
 cpp_quote("// get_language(/* [out] */ BSTR *htmlText);")
 cpp_quote("// ---------------------------------------------------------------------------------------------------=")
 cpp_quote("// Returns the computed language for this node, or empty string if unknown.")
 cpp_quote("//")
 cpp_quote("//")
 cpp_quote("///////////////////////////////////////////////////////////////////////////////////////////////////////")
--- a/accessible/src/atk/AccessibleWrap.h
+++ b/accessible/src/atk/AccessibleWrap.h
@@ -47,17 +47,16 @@ class MaiHyperlink;
  */
 class AccessibleWrap : public Accessible
 {
 public:
   AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~AccessibleWrap();
   void ShutdownAtkObject();
 
-  // nsAccessNode
   virtual void Shutdown();
 
   // return the atk object for this AccessibleWrap
   NS_IMETHOD GetNativeInterface(void **aOutAccessible);
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
 
   AtkObject * GetAtkObject(void);
   static AtkObject * GetAtkObject(nsIAccessible * acc);
--- a/accessible/src/atk/AtkSocketAccessible.h
+++ b/accessible/src/atk/AtkSocketAccessible.h
@@ -40,17 +40,16 @@ public:
    * True if the current Atk version supports AtkSocket and it was correctly
    * loaded.
    */
   static bool gCanEmbed;
 
   AtkSocketAccessible(nsIContent* aContent, DocAccessible* aDoc,
                       const nsCString& aPlugId);
 
-  // nsAccessNode
   virtual void Shutdown();
 
   // nsIAccessible
   NS_IMETHODIMP GetNativeInterface(void** aOutAccessible);
 };
 
 } // namespace a11y
 } // namespace mozilla
--- a/accessible/src/base/moz.build
+++ b/accessible/src/base/moz.build
@@ -5,18 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 include('../shared.mozbuild')
 
 MODULE = 'accessibility'
 
 EXPORTS += [
     'AccEvent.h',
-    'nsAccessibilityService.h',
-    'nsAccessNode.h',
+    'nsAccessibilityService.h'
 ]
 
 EXPORTS.mozilla.a11y += [
     'AccTypes.h',
     'DocManager.h',
     'FocusManager.h',
     'Platform.h',
     'RelationType.h',
@@ -40,17 +39,16 @@ SOURCES += [
     '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',
     'SelectionManager.cpp',
     'StyleInfo.cpp',
     'TextAttrs.cpp',
     'TextUpdater.cpp',
deleted file mode 100644
--- a/accessible/src/base/nsAccessNode.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/* -*- 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 "nsAccessNode.h"
-
-#include "nsAccUtils.h"
-#include "nsCoreUtils.h"
-#include "RootAccessible.h"
-
-#include "nsIDocShell.h"
-
-using namespace mozilla::a11y;
-
-/* For documentation of the accessibility architecture,
- * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
- */
-
-/*
- * Class nsAccessNode
- */
-
-////////////////////////////////////////////////////////////////////////////////
-// AccessNode. nsISupports
-
-NS_IMPL_CYCLE_COLLECTION_1(nsAccessNode, mContent)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessNode)
-  NS_INTERFACE_MAP_ENTRY(nsAccessNode)
-NS_INTERFACE_MAP_END
- 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAccessNode)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsAccessNode, LastRelease())
-
-////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode construction/desctruction
-
-nsAccessNode::
-  nsAccessNode(nsIContent* aContent, DocAccessible* aDoc) :
-  mContent(aContent), mDoc(aDoc)
-{
-}
-
-nsAccessNode::~nsAccessNode()
-{
-  NS_ASSERTION(!mDoc, "LastRelease was never called!?!");
-}
-
-void nsAccessNode::LastRelease()
-{
-  // First cleanup if needed...
-  if (mDoc) {
-    Shutdown();
-    NS_ASSERTION(!mDoc, "A Shutdown() impl forgot to call its parent's Shutdown?");
-  }
-  // ... then die.
-  delete this;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode public
-
-
-void
-nsAccessNode::Shutdown()
-{
-  mContent = nullptr;
-  mDoc = nullptr;
-}
-
-RootAccessible*
-nsAccessNode::RootAccessible() const
-{
-  nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(GetNode());
-  NS_ASSERTION(docShell, "No docshell for mContent");
-  if (!docShell) {
-    return nullptr;
-  }
-  nsCOMPtr<nsIDocShellTreeItem> root;
-  docShell->GetRootTreeItem(getter_AddRefs(root));
-  NS_ASSERTION(root, "No root content tree item");
-  if (!root) {
-    return nullptr;
-  }
-
-  DocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
-  return docAcc ? docAcc->AsRoot() : nullptr;
-}
-
-nsIFrame*
-nsAccessNode::GetFrame() const
-{
-  return mContent ? mContent->GetPrimaryFrame() : nullptr;
-}
-
-nsINode*
-nsAccessNode::GetNode() const
-{
-  return mContent;
-}
-
-void
-nsAccessNode::Language(nsAString& aLanguage)
-{
-  aLanguage.Truncate();
-
-  if (!mDoc)
-    return;
-
-  nsCoreUtils::GetLanguageFor(mContent, nullptr, aLanguage);
-  if (aLanguage.IsEmpty()) { // Nothing found, so use document's language
-    mDoc->DocumentNode()->GetHeaderData(nsGkAtoms::headerContentLanguage,
-                                        aLanguage);
-  }
-}
-
deleted file mode 100644
--- a/accessible/src/base/nsAccessNode.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -*- 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/. */
-
-/* For documentation of the accessibility architecture, 
- * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
- */
-
-#ifndef _nsAccessNode_H_
-#define _nsAccessNode_H_
-
-#include "nsINode.h"
-
-class nsIContent;
-class nsIFrame;
-
-namespace mozilla {
-namespace a11y {
-
-class DocAccessible;
-class RootAccessible;
-
-class nsAccessNode : public nsISupports
-{
-public:
-
-  nsAccessNode(nsIContent* aContent, DocAccessible* aDoc);
-  virtual ~nsAccessNode();
-
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS(nsAccessNode)
-
-  /**
-   * Return the document accessible for this access node.
-   */
-  DocAccessible* Document() const { return mDoc; }
-
-  /**
-   * Return the root document accessible for this accessnode.
-   */
-  a11y::RootAccessible* RootAccessible() const;
-
-  /**
-   * Shutdown the access node object.
-   */
-  virtual void Shutdown();
-
-  /**
-   * Return frame for the given access node object.
-   */
-  virtual nsIFrame* GetFrame() const;
-
-  /**
-   * Return DOM node associated with the accessible.
-   */
-  virtual nsINode* GetNode() const;
-  nsIContent* GetContent() const { return mContent; }
-
-  /**
-   * Return node type information of DOM node associated with the accessible.
-   */
-  bool IsContent() const
-  {
-    return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT);
-  }
-
-  /**
-   * Return the unique identifier of the accessible.
-   */
-  void* UniqueID() { return static_cast<void*>(this); }
-
-  /**
-   * Interface methods on nsIAccessible shared with ISimpleDOM.
-   */
-  void Language(nsAString& aLocale);
-
-protected:
-  void LastRelease();
-
-  nsCOMPtr<nsIContent> mContent;
-  DocAccessible* mDoc;
-
-private:
-  nsAccessNode() MOZ_DELETE;
-  nsAccessNode(const nsAccessNode&) MOZ_DELETE;
-  nsAccessNode& operator =(const nsAccessNode&) MOZ_DELETE;
-};
-
-} // namespace a11y
-} // namespace mozilla
-
-#endif
-
--- a/accessible/src/generic/ARIAGridAccessible.cpp
+++ b/accessible/src/generic/ARIAGridAccessible.cpp
@@ -35,17 +35,17 @@ ARIAGridAccessible::
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_ISUPPORTS_INHERITED1(ARIAGridAccessible,
                              Accessible,
                              nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
-//nsAccessNode
+// Accessible
 
 void
 ARIAGridAccessible::Shutdown()
 {
   mTable = nullptr;
   AccessibleWrap::Shutdown();
 }
 
--- a/accessible/src/generic/ARIAGridAccessible.h
+++ b/accessible/src/generic/ARIAGridAccessible.h
@@ -31,18 +31,16 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessibleTable
   NS_FORWARD_NSIACCESSIBLETABLE(xpcAccessibleTable::)
 
   // Accessible
   virtual TableAccessible* AsTable() { return this; }
-
-  // nsAccessNode
   virtual void Shutdown();
 
   // TableAccessible
   virtual uint32_t ColCount();
   virtual uint32_t RowCount();
   virtual Accessible* CellAt(uint32_t aRowIndex, uint32_t aColumnIndex);
   virtual bool IsColSelected(uint32_t aColIdx);
   virtual bool IsRowSelected(uint32_t aRowIdx);
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -83,79 +83,37 @@
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/Element.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// Accessible. nsISupports
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED_2(Accessible, nsAccessNode,
-                                     mParent, mChildren)
-
-NS_IMPL_ADDREF_INHERITED(Accessible, nsAccessNode)
-NS_IMPL_RELEASE_INHERITED(Accessible, nsAccessNode)
-
-nsresult
-Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
-{
-  // Custom-built QueryInterface() knows when we support nsIAccessibleSelectable
-  // based on role attribute and aria-multiselectable
-  *aInstancePtr = nullptr;
-
-  if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
-    *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(Accessible);
-    return NS_OK;
-  }
-
-  if (aIID.Equals(NS_GET_IID(nsIAccessible))) {
-    *aInstancePtr = static_cast<nsIAccessible*>(this);
-    NS_ADDREF_THIS();
-    return NS_OK;
-  }
-
-  if (aIID.Equals(NS_GET_IID(Accessible))) {
-    *aInstancePtr = static_cast<Accessible*>(this);
-    NS_ADDREF_THIS();
-    return NS_OK;
-  }
-
-  if (aIID.Equals(NS_GET_IID(nsIAccessibleSelectable))) {
-    if (IsSelect()) {
-      *aInstancePtr = static_cast<nsIAccessibleSelectable*>(this);
-      NS_ADDREF_THIS();
-      return NS_OK;
-    }
-    return NS_ERROR_NO_INTERFACE;
-  }
-
-  if (aIID.Equals(NS_GET_IID(nsIAccessibleValue))) {
-    if (HasNumericValue()) {
-      *aInstancePtr = static_cast<nsIAccessibleValue*>(this);
-      NS_ADDREF_THIS();
-      return NS_OK;
-    }
-  }
-
-  if (aIID.Equals(NS_GET_IID(nsIAccessibleHyperLink))) {
-    if (IsLink()) {
-      *aInstancePtr = static_cast<nsIAccessibleHyperLink*>(this);
-      NS_ADDREF_THIS();
-      return NS_OK;
-    }
-    return NS_ERROR_NO_INTERFACE;
-  }
-
-  return nsAccessNode::QueryInterface(aIID, aInstancePtr);
-}
+// Accessible: nsISupports and cycle collection
+
+NS_IMPL_CYCLE_COLLECTION_3(Accessible,
+                           mContent, mParent, mChildren)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Accessible)
+  NS_INTERFACE_MAP_ENTRY(nsIAccessible)
+  if (aIID.Equals(NS_GET_IID(Accessible)))
+    foundInterface = static_cast<nsIAccessible*>(this);
+  else
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleSelectable, IsSelect())
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleValue, HasNumericValue())
+  NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleHyperLink, IsLink())
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessible)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(Accessible)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(Accessible, LastRelease())
 
 Accessible::Accessible(nsIContent* aContent, DocAccessible* aDoc) :
-  nsAccessNode(aContent, aDoc),
+  mContent(aContent), mDoc(aDoc),
   mParent(nullptr), mIndexInParent(-1), mChildrenFlags(eChildrenUninitialized),
   mStateFlags(0), mType(0), mGenericTypes(0), mIndexOfEmbeddedChild(-1),
   mRoleMapEntry(nullptr)
 {
 #ifdef NS_DEBUG_X
    {
      nsCOMPtr<nsIPresShell> shell(do_QueryReferent(aShell));
      printf(">>> %p Created Acc - DOM: %p  PS: %p", 
@@ -170,21 +128,19 @@ Accessible::Accessible(nsIContent* aCont
       Name(buf);
       printf(" Name:[%s]", NS_ConvertUTF16toUTF8(buf).get());
      }
      printf("\n");
    }
 #endif
 }
 
-//-----------------------------------------------------
-// destruction
-//-----------------------------------------------------
 Accessible::~Accessible()
 {
+  NS_ASSERTION(!mDoc, "LastRelease was never called!?!");
 }
 
 NS_IMETHODIMP
 Accessible::GetDocument(nsIAccessibleDocument** aDocument)
 {
   NS_ENSURE_ARG_POINTER(aDocument);
 
   NS_IF_ADDREF(*aDocument = Document());
@@ -2619,31 +2575,29 @@ Accessible::AppendTextTo(nsAString& aTex
     // character if its parent hypertext accessible doesn't expose children to
     // AT.
     aText += kImaginaryEmbeddedObjectChar;
   } else {
     aText += kEmbeddedObjectChar;
   }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode public methods
-
 void
 Accessible::Shutdown()
 {
   // Mark the accessible as defunct, invalidate the child count and pointers to 
   // other accessibles, also make sure none of its children point to this parent
   mStateFlags |= eIsDefunct;
 
   InvalidateChildren();
   if (mParent)
     mParent->RemoveChild(this);
 
-  nsAccessNode::Shutdown();
+  mContent = nullptr;
+  mDoc = nullptr;
 }
 
 // Accessible protected
 void
 Accessible::ARIAName(nsString& aName)
 {
   // aria-labelledby now takes precedence over aria-label
   nsresult rv = nsTextEquivUtils::
@@ -2711,16 +2665,63 @@ Accessible::UnbindFromParent()
   mIndexInParent = -1;
   mIndexOfEmbeddedChild = -1;
   mGroupInfo = nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible public methods
 
+RootAccessible*
+Accessible::RootAccessible() const
+{
+  nsCOMPtr<nsIDocShell> docShell = nsCoreUtils::GetDocShellFor(GetNode());
+  NS_ASSERTION(docShell, "No docshell for mContent");
+  if (!docShell) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDocShellTreeItem> root;
+  docShell->GetRootTreeItem(getter_AddRefs(root));
+  NS_ASSERTION(root, "No root content tree item");
+  if (!root) {
+    return nullptr;
+  }
+
+  DocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
+  return docAcc ? docAcc->AsRoot() : nullptr;
+}
+
+nsIFrame*
+Accessible::GetFrame() const
+{
+  return mContent ? mContent->GetPrimaryFrame() : nullptr;
+}
+
+nsINode*
+Accessible::GetNode() const
+{
+  return mContent;
+}
+
+void
+Accessible::Language(nsAString& aLanguage)
+{
+  aLanguage.Truncate();
+
+  if (!mDoc)
+    return;
+
+  nsCoreUtils::GetLanguageFor(mContent, nullptr, aLanguage);
+  if (aLanguage.IsEmpty()) { // Nothing found, so use document's language
+    mDoc->DocumentNode()->GetHeaderData(nsGkAtoms::headerContentLanguage,
+                                        aLanguage);
+  }
+}
+
 void
 Accessible::InvalidateChildren()
 {
   int32_t childCount = mChildren.Length();
   for (int32_t childIdx = 0; childIdx < childCount; childIdx++) {
     Accessible* child = mChildren.ElementAt(childIdx);
     child->UnbindFromParent();
   }
@@ -3123,16 +3124,29 @@ Accessible::ContainerWidget() const
   }
   return nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible protected methods
 
 void
+Accessible::LastRelease()
+{
+  // First cleanup if needed...
+  if (mDoc) {
+    Shutdown();
+    NS_ASSERTION(!mDoc,
+                 "A Shutdown() impl forgot to call its parent's Shutdown?");
+  }
+  // ... then die.
+  delete this;
+}
+
+void
 Accessible::CacheChildren()
 {
   DocAccessible* doc = Document();
   NS_ENSURE_TRUE_VOID(doc);
 
   TreeWalker walker(this, mContent);
 
   Accessible* child = nullptr;
--- a/accessible/src/generic/Accessible.h
+++ b/accessible/src/generic/Accessible.h
@@ -5,17 +5,16 @@
 
 #ifndef _Accessible_H_
 #define _Accessible_H_
 
 #include "mozilla/a11y/AccTypes.h"
 #include "mozilla/a11y/RelationType.h"
 #include "mozilla/a11y/Role.h"
 #include "mozilla/a11y/States.h"
-#include "nsAccessNode.h"
 
 #include "nsIAccessible.h"
 #include "nsIAccessibleHyperLink.h"
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleValue.h"
 #include "nsIAccessibleStates.h"
 
 #include "nsIContent.h"
@@ -31,23 +30,25 @@ class nsIAtom;
 class nsView;
 
 namespace mozilla {
 namespace a11y {
 
 class Accessible;
 class AccEvent;
 class AccGroupInfo;
+class DocAccessible;
 class EmbeddedObjCollector;
 class HTMLImageMapAccessible;
 class HTMLLIAccessible;
 class HyperTextAccessible;
 class ImageAccessible;
 class KeyBinding;
 class Relation;
+class RootAccessible;
 class TableAccessible;
 class TableCellAccessible;
 class TextLeafAccessible;
 class XULLabelAccessible;
 class XULTreeAccessible;
 
 /**
  * Name type flags.
@@ -96,42 +97,78 @@ typedef nsRefPtrHashtable<nsPtrHashKey<c
 #define NS_ACCESSIBLE_IMPL_IID                          \
 {  /* 133c8bf4-4913-4355-bd50-426bd1d6e1ad */           \
   0x133c8bf4,                                           \
   0x4913,                                               \
   0x4355,                                               \
   { 0xbd, 0x50, 0x42, 0x6b, 0xd1, 0xd6, 0xe1, 0xad }    \
 }
 
-class Accessible : public nsAccessNode,
-                   public nsIAccessible,
+class Accessible : public nsIAccessible,
                    public nsIAccessibleHyperLink,
                    public nsIAccessibleSelectable,
                    public nsIAccessibleValue
 {
 public:
   Accessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~Accessible();
 
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Accessible, nsAccessNode)
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(Accessible, nsIAccessible)
 
   NS_DECL_NSIACCESSIBLE
   NS_DECL_NSIACCESSIBLEHYPERLINK
   NS_DECL_NSIACCESSIBLESELECTABLE
   NS_DECL_NSIACCESSIBLEVALUE
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLE_IMPL_IID)
 
   //////////////////////////////////////////////////////////////////////////////
-  // nsAccessNode
+  // Public methods
+
+  /**
+   * Return the document accessible for this accessible.
+   */
+  DocAccessible* Document() const { return mDoc; }
+
+  /**
+   * Return the root document accessible for this accessible.
+   */
+  a11y::RootAccessible* RootAccessible() const;
+
+  /**
+   * Return frame for this accessible.
+   */
+  virtual nsIFrame* GetFrame() const;
 
-  virtual void Shutdown();
+  /**
+   * Return DOM node associated with the accessible.
+   */
+  virtual nsINode* GetNode() const;
+  inline already_AddRefed<nsIDOMNode> DOMNode() const
+  {
+    nsCOMPtr<nsIDOMNode> DOMNode = do_QueryInterface(GetNode());
+    return DOMNode.forget();
+  }
+  nsIContent* GetContent() const { return mContent; }
 
-  //////////////////////////////////////////////////////////////////////////////
-  // Public methods
+  /**
+   * Return node type information of DOM node associated with the accessible.
+   */
+  bool IsContent() const
+    { return GetNode() && GetNode()->IsNodeOfType(nsINode::eCONTENT); }
+
+  /**
+   * Return the unique identifier of the accessible.
+   */
+  void* UniqueID() { return static_cast<void*>(this); }
+
+  /**
+   * Return language associated with the accessible.
+   */
+  void Language(nsAString& aLocale);
 
   /**
    * Get the description of this accessible.
    */
   virtual void Description(nsString& aDescription);
 
   /**
    * Get the value of this accessible.
@@ -142,25 +179,16 @@ public:
    * Get the name of this accessible.
    *
    * Note: aName.IsVoid() when name was left empty by the author on purpose.
    * aName.IsEmpty() when the author missed name, AT can try to repair a name.
    */
   virtual ENameValueFlag Name(nsString& aName);
 
   /**
-   * Return DOM node associated with this accessible.
-   */
-  inline already_AddRefed<nsIDOMNode> DOMNode() const
-  {
-    nsCOMPtr<nsIDOMNode> DOMNode = do_QueryInterface(GetNode());
-    return DOMNode.forget();
-  }
-
-  /**
    * Maps ARIA state attributes to state of accessible. Note the given state
    * argument should hold states for accessible before you pass it into this
    * method.
    *
    * @param  [in/out] where to fill the states into.
    */
   virtual void ApplyARIAState(uint64_t* aState) const;
 
@@ -296,16 +324,21 @@ public:
    * Get the relation of the given type.
    */
   virtual Relation RelationByType(RelationType aType);
 
   //////////////////////////////////////////////////////////////////////////////
   // Initializing methods
 
   /**
+   * Shutdown this accessible object.
+   */
+  virtual void Shutdown();
+
+  /**
    * Set the ARIA role map entry for a new accessible.
    */
   void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
     { mRoleMapEntry = aRoleMapEntry; }
 
   /**
    * Update the children cache.
    */
@@ -379,17 +412,16 @@ public:
   inline Accessible* FirstChild()
     { return GetChildAt(0); }
   inline Accessible* LastChild()
   {
     uint32_t childCount = ChildCount();
     return childCount != 0 ? GetChildAt(childCount - 1) : nullptr;
   }
 
-
   /**
    * Return embedded accessible children count.
    */
   uint32_t EmbeddedChildCount();
 
   /**
    * Return embedded accessible child at the given index.
    */
@@ -752,16 +784,21 @@ protected:
    * account ARIA.
    */
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes();
 
   //////////////////////////////////////////////////////////////////////////////
   // Initializing, cache and tree traverse methods
 
   /**
+   * Destroy the object.
+   */
+  void LastRelease();
+
+  /**
    * Cache accessible children.
    */
   virtual void CacheChildren();
 
   /**
    * Set accessible parent and index in parent.
    */
   virtual void BindToParent(Accessible* aParent, uint32_t aIndexInParent);
@@ -895,16 +932,19 @@ protected:
   uint32_t GetActionRule();
 
   /**
    * Return group info.
    */
   AccGroupInfo* GetGroupInfo();
 
   // Data Members
+  nsCOMPtr<nsIContent> mContent;
+  DocAccessible* mDoc;
+
   nsRefPtr<Accessible> mParent;
   nsTArray<nsRefPtr<Accessible> > mChildren;
   int32_t mIndexInParent;
 
   static const uint8_t kChildrenFlagsBits = 2;
   static const uint8_t kStateFlagsBits = 5;
   static const uint8_t kTypeBits = 6;
   static const uint8_t kGenericTypesBits = 12;
@@ -927,16 +967,22 @@ protected:
 
   nsAutoPtr<AccGroupInfo> mGroupInfo;
   friend class AccGroupInfo;
 
   /**
    * Non-null indicates author-supplied role; possibly state & value as well
    */
   nsRoleMapEntry* mRoleMapEntry;
+
+private:
+  Accessible() MOZ_DELETE;
+  Accessible(const Accessible&) MOZ_DELETE;
+  Accessible& operator =(const Accessible&) MOZ_DELETE;
+
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(Accessible,
                               NS_ACCESSIBLE_IMPL_IID)
 
 
 /**
  * Represent key binding associated with accessible (such as access key and
--- a/accessible/src/generic/ApplicationAccessible.cpp
+++ b/accessible/src/generic/ApplicationAccessible.cpp
@@ -260,28 +260,24 @@ ApplicationAccessible::GetPlatformVersio
   nsresult rv = mAppInfo->GetPlatformVersion(cversion);
   NS_ENSURE_SUCCESS(rv, rv);
 
   AppendUTF8toUTF16(cversion, aVersion);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode public methods
+// Accessible public methods
 
 void
 ApplicationAccessible::Shutdown()
 {
   mAppInfo = nullptr;
 }
 
-
-////////////////////////////////////////////////////////////////////////////////
-// Accessible public methods
-
 void
 ApplicationAccessible::ApplyARIAState(uint64_t* aState) const
 {
 }
 
 role
 ApplicationAccessible::NativeRole()
 {
--- a/accessible/src/generic/ApplicationAccessible.h
+++ b/accessible/src/generic/ApplicationAccessible.h
@@ -52,20 +52,18 @@ public:
   NS_IMETHOD TakeFocus();
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString &aName);
   NS_IMETHOD GetActionDescription(uint8_t aIndex, nsAString &aDescription);
   NS_IMETHOD DoAction(uint8_t aIndex);
 
   // nsIAccessibleApplication
   NS_DECL_NSIACCESSIBLEAPPLICATION
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual GroupPos GroupPosition();
   virtual ENameValueFlag Name(nsString& aName);
   virtual void ApplyARIAState(uint64_t* aState) const;
   virtual void Description(nsString& aDescription);
   virtual void Value(nsString& aValue);
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t State();
--- a/accessible/src/generic/BaseAccessibles.cpp
+++ b/accessible/src/generic/BaseAccessibles.cpp
@@ -150,17 +150,17 @@ LinkableAccessible::DoAction(uint8_t aIn
 KeyBinding
 LinkableAccessible::AccessKey() const
 {
   return mActionAcc ?
     mActionAcc->AccessKey() : Accessible::AccessKey();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// LinkableAccessible. nsAccessNode
+// LinkableAccessible. Accessible
 
 void
 LinkableAccessible::Shutdown()
 {
   mIsLink = false;
   mIsOnclick = false;
   mActionAcc = nullptr;
   AccessibleWrap::Shutdown();
--- a/accessible/src/generic/BaseAccessibles.h
+++ b/accessible/src/generic/BaseAccessibles.h
@@ -59,20 +59,18 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
   NS_IMETHOD DoAction(uint8_t index);
   NS_IMETHOD TakeFocus();
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual void Value(nsString& aValue);
   virtual uint64_t NativeLinkState() const;
 
   // ActionAccessible
   virtual uint8_t ActionCount();
   virtual KeyBinding AccessKey() const;
 
   // HyperLinkAccessible
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -547,17 +547,17 @@ DocAccessible::GetAccessible(nsINode* aN
   if (parent)
     parent->TestChildCache(accessible);
 #endif
 
   return accessible;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode
+// Accessible
 
 void
 DocAccessible::Init()
 {
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate))
     logging::DocCreate("document initialize", mDocumentNode, this);
 #endif
--- a/accessible/src/generic/DocAccessible.h
+++ b/accessible/src/generic/DocAccessible.h
@@ -66,24 +66,23 @@ public:
 
   // nsIScrollPositionListener
   virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) {}
   virtual void ScrollPositionDidChange(nscoord aX, nscoord aY);
 
   // nsIDocumentObserver
   NS_DECL_NSIDOCUMENTOBSERVER
 
-  // nsAccessNode
+  // Accessible
   virtual void Init();
   virtual void Shutdown();
   virtual nsIFrame* GetFrame() const;
   virtual nsINode* GetNode() const { return mDocumentNode; }
   nsIDocument* DocumentNode() const { return mDocumentNode; }
 
-  // Accessible
   virtual mozilla::a11y::ENameValueFlag Name(nsString& aName);
   virtual void Description(nsString& aDescription);
   virtual Accessible* FocusedChild();
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual uint64_t NativeInteractiveState() const;
   virtual bool NativelyUnavailable() const;
   virtual void ApplyARIAState(uint64_t* aState) const;
@@ -217,17 +216,17 @@ public:
    * Return whether the given DOM node has an accessible or not.
    */
   bool HasAccessible(nsINode* aNode) const
     { return GetAccessible(aNode); }
 
   /**
    * Return the cached accessible by the given unique ID within this document.
    *
-   * @note   the unique ID matches with the uniqueID() of nsAccessNode
+   * @note   the unique ID matches with the uniqueID() of Accessible
    *
    * @param  aUniqueID  [in] the unique ID used to cache the node.
    */
   Accessible* GetAccessibleByUniqueID(void* aUniqueID)
   {
     return UniqueID() == aUniqueID ?
       this : mAccessibleCache.GetWeak(aUniqueID);
   }
--- a/accessible/src/generic/OuterDocAccessible.cpp
+++ b/accessible/src/generic/OuterDocAccessible.cpp
@@ -97,17 +97,17 @@ OuterDocAccessible::GetActionDescription
 
 NS_IMETHODIMP
 OuterDocAccessible::DoAction(uint8_t aIndex)
 {
   return NS_ERROR_INVALID_ARG;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode public
+// Accessible public
 
 void
 OuterDocAccessible::Shutdown()
 {
   // XXX: sometimes outerdoc accessible is shutdown because of layout style
   // change however the presshell of underlying document isn't destroyed and
   // the document doesn't get pagehide events. Schedule a document rebind
   // to its parent document. Otherwise a document accessible may be lost if its
@@ -128,19 +128,16 @@ OuterDocAccessible::Shutdown()
 #endif
     RemoveChild(child);
     mDoc->BindChildDocument(child->AsDoc());
   }
 
   AccessibleWrap::Shutdown();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Accessible public
-
 void
 OuterDocAccessible::InvalidateChildren()
 {
   // Do not invalidate children because DocManager is responsible for
   // document accessible lifetime when DOM document is created or destroyed. If
   // DOM document isn't destroyed but its presshell is destroyed (for example,
   // when DOM node of outerdoc accessible is hidden), then outerdoc accessible
   // notifies DocManager about this. If presshell is created for existing
--- a/accessible/src/generic/OuterDocAccessible.h
+++ b/accessible/src/generic/OuterDocAccessible.h
@@ -28,20 +28,18 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
   NS_IMETHOD GetActionDescription(uint8_t aIndex, nsAString& aDescription);
   NS_IMETHOD DoAction(uint8_t aIndex);
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
                                    EWhichChildAtPoint aWhichChild);
 
   virtual void InvalidateChildren();
   virtual bool InsertChildAt(uint32_t aIdx, Accessible* aChild) MOZ_OVERRIDE;
   virtual bool RemoveChild(Accessible* aAccessible);
 
--- a/accessible/src/generic/RootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -462,22 +462,22 @@ RootAccessible::ProcessDOMEvent(nsIDOMEv
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START,
                             accessible);
   }
 #endif
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode
+// Accessible
 
 void
 RootAccessible::Shutdown()
 {
-  // Called manually or by nsAccessNode::LastRelease()
+  // Called manually or by Accessible::LastRelease()
   if (!PresShell())
     return;  // Already shutdown
 
   DocAccessibleWrap::Shutdown();
 }
 
 // nsIAccessible method
 Relation
--- a/accessible/src/generic/RootAccessible.h
+++ b/accessible/src/generic/RootAccessible.h
@@ -24,20 +24,18 @@ class RootAccessible : public DocAccessi
 public:
   RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
                  nsIPresShell* aPresShell);
   virtual ~RootAccessible();
 
   // nsIDOMEventListener
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual mozilla::a11y::ENameValueFlag Name(nsString& aName);
   virtual Relation RelationByType(RelationType aType) MOZ_OVERRIDE;
   virtual mozilla::a11y::role NativeRole();
   virtual uint64_t NativeState();
 
   // RootAccessible
 
   /**
--- a/accessible/src/html/HTMLListAccessible.cpp
+++ b/accessible/src/html/HTMLListAccessible.cpp
@@ -142,28 +142,25 @@ HTMLLIAccessible::CacheChildren()
 HTMLListBulletAccessible::
   HTMLListBulletAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   LeafAccessible(aContent, aDoc)
 {
   mStateFlags |= eSharedNode;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// HTMLListBulletAccessible: nsAccessNode
+// HTMLListBulletAccessible: Accessible
 
 nsIFrame*
 HTMLListBulletAccessible::GetFrame() const
 {
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
   return blockFrame ? blockFrame->GetBullet() : nullptr;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// HTMLListBulletAccessible: Accessible
-
 ENameValueFlag
 HTMLListBulletAccessible::Name(nsString &aName)
 {
   aName.Truncate();
 
   // Native anonymous content, ARIA can't be used. Get list bullet text.
   nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
   if (blockFrame) {
--- a/accessible/src/html/HTMLListAccessible.h
+++ b/accessible/src/html/HTMLListAccessible.h
@@ -41,24 +41,22 @@ class HTMLLIAccessible : public HyperTex
 {
 public:
   HTMLLIAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~HTMLLIAccessible() { }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
-  // nsAccessNode
-  virtual void Shutdown();
-
   // nsIAccessible
   NS_IMETHOD GetBounds(int32_t* aX, int32_t* aY,
                        int32_t* aWidth, int32_t* aHeight);
 
   // Accessible
+  virtual void Shutdown();
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
 
   // nsHTMLLIAccessible
   void UpdateBullet(bool aHasBullet);
 
 protected:
   // Accessible
@@ -73,20 +71,18 @@ private:
  * Used for bullet of HTML list item element (for example, HTML li).
  */
 class HTMLListBulletAccessible : public LeafAccessible
 {
 public:
   HTMLListBulletAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~HTMLListBulletAccessible() { }
 
-  // nsAccessNode
+  // Accessible
   virtual nsIFrame* GetFrame() const;
-
-  // Accessible
   virtual ENameValueFlag Name(nsString& aName);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual void AppendTextTo(nsAString& aText, uint32_t aStartOffset = 0,
                             uint32_t aLength = UINT32_MAX);
 
   // HTMLListBulletAccessible
 
--- a/accessible/src/html/HTMLSelectAccessible.cpp
+++ b/accessible/src/html/HTMLSelectAccessible.cpp
@@ -590,36 +590,33 @@ HTMLComboboxListAccessible::
   HTMLComboboxListAccessible(nsIAccessible* aParent, nsIContent* aContent,
                              DocAccessible* aDoc) :
   HTMLSelectListAccessible(aContent, aDoc)
 {
   mStateFlags |= eSharedNode;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// HTMLComboboxAccessible: nsAccessNode
+// HTMLComboboxAccessible: Accessible
 
 nsIFrame*
 HTMLComboboxListAccessible::GetFrame() const
 {
   nsIFrame* frame = HTMLSelectListAccessible::GetFrame();
 
   if (frame) {
     nsIComboboxControlFrame* comboBox = do_QueryFrame(frame);
     if (comboBox) {
       return comboBox->GetDropDown();
     }
   }
 
   return nullptr;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// HTMLComboboxAccessible: Accessible
-
 role
 HTMLComboboxListAccessible::NativeRole()
 {
   return roles::COMBOBOX_LIST;
 }
 
 uint64_t
 HTMLComboboxListAccessible::NativeState()
--- a/accessible/src/html/HTMLSelectAccessible.h
+++ b/accessible/src/html/HTMLSelectAccessible.h
@@ -170,20 +170,18 @@ public:
 
   HTMLComboboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~HTMLComboboxAccessible() {}
 
   // nsIAccessible
   NS_IMETHOD DoAction(uint8_t index);
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual void Description(nsString& aDescription);
   virtual void Value(nsString& aValue);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual void InvalidateChildren();
 
   // ActionAccessible
   virtual uint8_t ActionCount();
@@ -216,20 +214,18 @@ private:
 class HTMLComboboxListAccessible : public HTMLSelectListAccessible
 {
 public:
 
   HTMLComboboxListAccessible(nsIAccessible* aParent, nsIContent* aContent,
                              DocAccessible* aDoc);
   virtual ~HTMLComboboxListAccessible() {}
 
-  // nsAccessNode
+  // Accessible
   virtual nsIFrame* GetFrame() const;
-
-  // Accessible
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual void GetBoundsRect(nsRect& aBounds, nsIFrame** aBoundingFrame);
 
   // Widgets
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
 };
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -360,29 +360,25 @@ HTMLTableRowAccessible::NativeRole()
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS_INHERITED1(HTMLTableAccessible, Accessible,
                              nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
-//nsAccessNode
+// HTMLTableAccessible: Accessible
 
 void
 HTMLTableAccessible::Shutdown()
 {
   mTable = nullptr;
   AccessibleWrap::Shutdown();
 }
 
-
-////////////////////////////////////////////////////////////////////////////////
-// HTMLTableAccessible: Accessible implementation
-
 void
 HTMLTableAccessible::CacheChildren()
 {
   // Move caption accessible so that it's the first child. Check for the first
   // caption only, because nsAccessibilityService ensures we don't create
   // accessibles for the other captions, since only the first is actually
   // visible.
   TreeWalker walker(this, mContent);
--- a/accessible/src/html/HTMLTableAccessible.h
+++ b/accessible/src/html/HTMLTableAccessible.h
@@ -158,20 +158,18 @@ public:
   virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows);
   virtual void SelectCol(uint32_t aColIdx);
   virtual void SelectRow(uint32_t aRowIdx);
   virtual void UnselectCol(uint32_t aColIdx);
   virtual void UnselectRow(uint32_t aRowIdx);
   virtual bool IsProbablyLayoutTable();
   virtual Accessible* AsAccessible() { return this; }
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual TableAccessible* AsTable() { return this; }
   virtual void Description(nsString& aDescription);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() MOZ_OVERRIDE;
   virtual Relation RelationByType(RelationType aRelationType) MOZ_OVERRIDE;
 
 protected:
--- a/accessible/src/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/src/windows/msaa/DocAccessibleWrap.cpp
@@ -72,17 +72,17 @@ DocAccessibleWrap::get_accValue(VARIANT 
 
   *aValue = ::SysAllocStringLen(URL.get(), URL.Length());
   return *aValue ? S_OK : E_OUTOFMEMORY;
 
   A11Y_TRYBLOCK_END
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsAccessNode
+// Accessible
 
 void
 DocAccessibleWrap::Shutdown()
 {
   // Do window emulation specific shutdown if emulation was started.
   if (nsWinUtils::IsWindowEmulationStarted()) {
     // Destroy window created for root document.
     if (mDocFlags & eTabDocument) {
--- a/accessible/src/windows/msaa/DocAccessibleWrap.h
+++ b/accessible/src/windows/msaa/DocAccessibleWrap.h
@@ -23,17 +23,17 @@ public:
 
   // IAccessible
 
     // Override get_accValue to provide URL when no other value is available
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue( 
         /* [optional][in] */ VARIANT varChild,
         /* [retval][out] */ BSTR __RPC_FAR *pszValue);
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
 
   // DocAccessible
   virtual void* GetNativeWindow() const;
 
 protected:
   // DocAccessible
   virtual void DoInitialUpdate();
--- a/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.cpp
+++ b/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.cpp
@@ -20,28 +20,25 @@ HTMLWin32ObjectOwnerAccessible::
   AccessibleWrap(aContent, aDoc), mHwnd(aHwnd)
 {
   // Our only child is a HTMLWin32ObjectAccessible object.
   if (mHwnd)
     mNativeAccessible = new HTMLWin32ObjectAccessible(mHwnd);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// HTMLWin32ObjectOwnerAccessible: nsAccessNode implementation
+// HTMLWin32ObjectOwnerAccessible: Accessible implementation
 
 void
 HTMLWin32ObjectOwnerAccessible::Shutdown()
 {
   AccessibleWrap::Shutdown();
   mNativeAccessible = nullptr;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// HTMLWin32ObjectOwnerAccessible: Accessible implementation
-
 role
 HTMLWin32ObjectOwnerAccessible::NativeRole()
 {
   return roles::EMBEDDED_OBJECT;
 }
 
 bool
 HTMLWin32ObjectOwnerAccessible::NativelyUnavailable() const
--- a/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.h
+++ b/accessible/src/windows/msaa/HTMLWin32ObjectAccessible.h
@@ -21,20 +21,18 @@ public:
   // will still point to Gecko accessible sibling content. This is necessary
   // because the native plugin accessible doesn't know where it exists in the
   // Mozilla tree, and returns null for previous and next sibling. This would
   // have the effect of cutting off all content after the plugin.
   HTMLWin32ObjectOwnerAccessible(nsIContent* aContent,
                                    DocAccessible* aDoc, void* aHwnd);
   virtual ~HTMLWin32ObjectOwnerAccessible() {}
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual mozilla::a11y::role NativeRole();
   virtual bool NativelyUnavailable() const;
 
 protected:
 
   // Accessible
   virtual void CacheChildren();
 
--- a/accessible/src/xul/XULListboxAccessible.cpp
+++ b/accessible/src/xul/XULListboxAccessible.cpp
@@ -128,17 +128,17 @@ XULListboxAccessible::QueryInterface(REF
     NS_ADDREF_THIS();
     return NS_OK;
   }
 
   return NS_ERROR_NO_INTERFACE;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-//nsAccessNode
+// Accessible
 
 void
 XULListboxAccessible::Shutdown()
 {
   mTable = nullptr;
   XULSelectControlAccessible::Shutdown();
 }
 
--- a/accessible/src/xul/XULListboxAccessible.h
+++ b/accessible/src/xul/XULListboxAccessible.h
@@ -87,20 +87,18 @@ public:
   virtual void SelectedCells(nsTArray<Accessible*>* aCells);
   virtual void SelectedCellIndices(nsTArray<uint32_t>* aCells);
   virtual void SelectedColIndices(nsTArray<uint32_t>* aCols);
   virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows);
   virtual void SelectRow(uint32_t aRowIdx);
   virtual void UnselectRow(uint32_t aRowIdx);
   virtual Accessible* AsAccessible() { return this; }
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual void Value(nsString& aValue);
   virtual TableAccessible* AsTable() { return this; }
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
 
   // Widgets
   virtual bool IsWidget() const;
   virtual bool IsActiveWidget() const;
--- a/accessible/src/xul/XULSelectControlAccessible.cpp
+++ b/accessible/src/xul/XULSelectControlAccessible.cpp
@@ -31,17 +31,17 @@ XULSelectControlAccessible::
   XULSelectControlAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc)
 {
   mGenericTypes |= eSelect;
   mSelectControl = do_QueryInterface(aContent);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// XULSelectControlAccessible: nsAccessNode
+// XULSelectControlAccessible: Accessible
 
 void
 XULSelectControlAccessible::Shutdown()
 {
   mSelectControl = nullptr;
   AccessibleWrap::Shutdown();
 }
 
--- a/accessible/src/xul/XULSelectControlAccessible.h
+++ b/accessible/src/xul/XULSelectControlAccessible.h
@@ -17,17 +17,17 @@ namespace a11y {
  * The basic implementation of accessible selection for XUL select controls.
  */
 class XULSelectControlAccessible : public AccessibleWrap
 {
 public:
   XULSelectControlAccessible(nsIContent* aContent, DocAccessible* aDoc);
   virtual ~XULSelectControlAccessible() {}
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
 
   // SelectAccessible
   virtual already_AddRefed<nsIArray> SelectedItems();
   virtual uint32_t SelectedItemCount();
   virtual Accessible* GetSelectedItem(uint32_t aIndex);
   virtual bool IsItemSelected(uint32_t aIndex);
   virtual bool AddItemToSelection(uint32_t aIndex);
--- a/accessible/src/xul/XULTreeAccessible.cpp
+++ b/accessible/src/xul/XULTreeAccessible.cpp
@@ -129,36 +129,33 @@ XULTreeAccessible::Value(nsString& aValu
       cols->GetKeyColumn(getter_AddRefs(keyCol));
 
     mTreeView->GetCellText(currentIndex, keyCol, aValue);
   }
 
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// XULTreeAccessible: nsAccessNode implementation
+// XULTreeAccessible: Accessible implementation
 
 void
 XULTreeAccessible::Shutdown()
 {
   // XXX: we don't remove accessible from document cache if shutdown wasn't
   // initiated by document destroying. Note, we can't remove accessible from
   // document cache here while document is going to be shutdown. Note, this is
   // not unique place where we have similar problem.
   ClearCache(mAccessibleCache);
 
   mTree = nullptr;
   mTreeView = nullptr;
 
   AccessibleWrap::Shutdown();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// XULTreeAccessible: Accessible implementation (put methods here)
-
 role
 XULTreeAccessible::NativeRole()
 {
   // No primary column means we're in a list. In fact, history and mail turn off
   // the primary flag when switching to a flat view.
 
   nsIContent* child = nsTreeUtils::GetDescendantChild(mContent, nsGkAtoms::treechildren);
   NS_ASSERTION(child, "tree without treechildren!");
@@ -884,32 +881,28 @@ XULTreeItemAccessibleBase::DoAction(uint
       (aIndex != eAction_Expand || !IsExpandable()))
     return NS_ERROR_INVALID_ARG;
 
   DoCommand(nullptr, aIndex);
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// XULTreeItemAccessibleBase: nsAccessNode implementation
+// XULTreeItemAccessibleBase: Accessible implementation
 
 void
 XULTreeItemAccessibleBase::Shutdown()
 {
   mTree = nullptr;
   mTreeView = nullptr;
   mRow = -1;
 
   AccessibleWrap::Shutdown();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// XULTreeItemAccessibleBase: Accessible public methods
-
-// nsIAccessible::groupPosition
 GroupPos
 XULTreeItemAccessibleBase::GroupPosition()
 {
   GroupPos groupPos;
 
   int32_t level;
   nsresult rv = mTreeView->GetLevel(mRow, &level);
   NS_ENSURE_SUCCESS(rv, groupPos);
@@ -1129,28 +1122,25 @@ XULTreeItemAccessible::Name(nsString& aN
 {
   aName.Truncate();
 
   GetCellName(mColumn, aName);
   return eNameOK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// XULTreeItemAccessible: nsAccessNode implementation
+// XULTreeItemAccessible: Accessible implementation
 
 void
 XULTreeItemAccessible::Shutdown()
 {
   mColumn = nullptr;
   XULTreeItemAccessibleBase::Shutdown();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// XULTreeItemAccessible: Accessible implementation
-
 role
 XULTreeItemAccessible::NativeRole()
 {
   nsCOMPtr<nsITreeColumns> columns;
   mTree->GetColumns(getter_AddRefs(columns));
   if (!columns) {
     NS_ERROR("No tree columns object in the tree!");
     return roles::NOTHING;
--- a/accessible/src/xul/XULTreeAccessible.h
+++ b/accessible/src/xul/XULTreeAccessible.h
@@ -33,20 +33,18 @@ public:
 
   XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc,
                     nsTreeBodyFrame* aTreeframe);
 
   // nsISupports and cycle collection
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULTreeAccessible, Accessible)
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual void Value(nsString& aValue);
   virtual a11y::role NativeRole();
   virtual uint64_t NativeState();
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
                                    EWhichChildAtPoint aWhichChild);
 
   virtual Accessible* GetChildAt(uint32_t aIndex);
   virtual uint32_t ChildCount() const;
@@ -150,20 +148,18 @@ public:
                        int32_t *aWidth, int32_t *aHeight);
 
   NS_IMETHOD SetSelected(bool aSelect);
   NS_IMETHOD TakeFocus();
 
   NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName);
   NS_IMETHOD DoAction(uint8_t aIndex);
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual GroupPos GroupPosition();
   virtual uint64_t NativeState();
   virtual uint64_t NativeInteractiveState() const;
   virtual int32_t IndexInParent() const;
   virtual Relation RelationByType(RelationType aType) MOZ_OVERRIDE;
   virtual Accessible* FocusedChild();
 
   // ActionAccessible
@@ -231,20 +227,18 @@ public:
                         Accessible* aParent, nsITreeBoxObject* aTree,
                         nsITreeView* aTreeView, int32_t aRow);
 
   // nsISupports and cycle collection
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULTreeItemAccessible,
                                            XULTreeItemAccessibleBase)
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual ENameValueFlag Name(nsString& aName);
   virtual a11y::role NativeRole();
 
   // XULTreeItemAccessibleBase
   virtual void RowInvalidated(int32_t aStartColIdx, int32_t aEndColIdx);
 
 protected:
 
--- a/accessible/src/xul/XULTreeGridAccessible.cpp
+++ b/accessible/src/xul/XULTreeGridAccessible.cpp
@@ -215,28 +215,25 @@ XULTreeGridAccessible::UnselectRow(uint3
   nsCOMPtr<nsITreeSelection> selection;
   mTreeView->GetSelection(getter_AddRefs(selection));
 
   if (selection)
     selection->ClearRange(aRowIdx, aRowIdx);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// XULTreeGridAccessible: nsAccessNode implementation
+// XULTreeGridAccessible: Accessible implementation
 
 void
 XULTreeGridAccessible::Shutdown()
 {
   mTable = nullptr;
   XULTreeAccessible::Shutdown();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// XULTreeGridAccessible: Accessible implementation
-
 role
 XULTreeGridAccessible::NativeRole()
 {
   nsCOMPtr<nsITreeColumns> treeColumns;
   mTree->GetColumns(getter_AddRefs(treeColumns));
   if (!treeColumns) {
     NS_ERROR("No treecolumns object for tree!");
     return roles::NOTHING;
@@ -286,28 +283,25 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
 
 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible,
                          XULTreeItemAccessibleBase)
 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
                           XULTreeItemAccessibleBase)
 
 ////////////////////////////////////////////////////////////////////////////////
-// XULTreeGridRowAccessible: nsAccessNode implementation
+// XULTreeGridRowAccessible: Accessible implementation
 
 void
 XULTreeGridRowAccessible::Shutdown()
 {
   ClearCache(mAccessibleCache);
   XULTreeItemAccessibleBase::Shutdown();
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// XULTreeGridRowAccessible: Accessible implementation
-
 role
 XULTreeGridRowAccessible::NativeRole()
 {
   return roles::ROW;
 }
 
 ENameValueFlag
 XULTreeGridRowAccessible::Name(nsString& aName)
--- a/accessible/src/xul/XULTreeGridAccessible.h
+++ b/accessible/src/xul/XULTreeGridAccessible.h
@@ -49,20 +49,18 @@ public:
   virtual void SelectedCells(nsTArray<Accessible*>* aCells);
   virtual void SelectedCellIndices(nsTArray<uint32_t>* aCells);
   virtual void SelectedColIndices(nsTArray<uint32_t>* aCols);
   virtual void SelectedRowIndices(nsTArray<uint32_t>* aRows);
   virtual void SelectRow(uint32_t aRowIdx);
   virtual void UnselectRow(uint32_t aRowIdx);
   virtual Accessible* AsAccessible() { return this; }
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual TableAccessible* AsTable() { return this; }
   virtual a11y::role NativeRole();
 
 protected:
 
   // XULTreeAccessible
   virtual already_AddRefed<Accessible> CreateTreeItemAccessible(int32_t aRow);
 };
@@ -81,20 +79,18 @@ public:
                            Accessible* aParent, nsITreeBoxObject* aTree,
                            nsITreeView* aTreeView, int32_t aRow);
 
   // nsISupports and cycle collection
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULTreeGridRowAccessible,
                                            XULTreeItemAccessibleBase)
 
-  // nsAccessNode
+  // Accessible
   virtual void Shutdown();
-
-  // Accessible
   virtual a11y::role NativeRole();
   virtual ENameValueFlag Name(nsString& aName);
   virtual Accessible* ChildAtPoint(int32_t aX, int32_t aY,
                                    EWhichChildAtPoint aWhichChild);
 
   virtual Accessible* GetChildAt(uint32_t aIndex);
   virtual uint32_t ChildCount() const;
 
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -563,16 +563,20 @@ pref("dom.disable_window_print", true);
 
 // Disable window.showModalDialog
 pref("dom.disable_window_showModalDialog", true);
 
 // Enable new experimental html forms
 pref("dom.experimental_forms", true);
 pref("dom.forms.number", true);
 
+// Don't enable <input type=color> yet as we don't have a color picker
+// implemented for b2g (bug 875751)
+pref("dom.forms.color", false);
+
 // Turns on gralloc-based direct texturing for Gonk
 pref("gfx.gralloc.enabled", false);
 
 // XXXX REMOVE FOR PRODUCTION. Turns on GC and CC logging
 pref("javascript.options.mem.log", false);
 
 // Increase mark slice time from 10ms to 30ms
 pref("javascript.options.mem.gc_incremental_slice_ms", 30);
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "166023c341cca944563c410f05dff37a992cb05b", 
+    "revision": "d2dbad943faf566fe36dbe79086127da837af6a3", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -540,19 +540,16 @@
 @BINPATH@/components/ActivityWrapper.js
 @BINPATH@/components/ActivityMessageConfigurator.js
 
 @BINPATH@/components/TCPSocket.js
 @BINPATH@/components/TCPServerSocket.js
 @BINPATH@/components/TCPSocketParentIntermediary.js
 @BINPATH@/components/TCPSocket.manifest
 
-@BINPATH@/components/AppProtocolHandler.js
-@BINPATH@/components/AppProtocolHandler.manifest
-
 @BINPATH@/components/Payment.js
 @BINPATH@/components/PaymentFlowInfo.js
 @BINPATH@/components/PaymentRequestInfo.js
 @BINPATH@/components/Payment.manifest
 
 ; InputMethod API
 @BINPATH@/components/MozKeyboard.js
 @BINPATH@/components/InputMethod.manifest
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1181,17 +1181,17 @@ pref("devtools.gcli.hideIntro", false);
 // How eager are we to show help: never=1, sometimes=2, always=3
 pref("devtools.gcli.eagerHelper", 2);
 
 // Remember the Web Console filters
 pref("devtools.webconsole.filter.network", true);
 pref("devtools.webconsole.filter.networkinfo", true);
 pref("devtools.webconsole.filter.netwarn", true);
 pref("devtools.webconsole.filter.csserror", true);
-pref("devtools.webconsole.filter.cssparser", true);
+pref("devtools.webconsole.filter.cssparser", false);
 pref("devtools.webconsole.filter.csslog", false);
 pref("devtools.webconsole.filter.exception", true);
 pref("devtools.webconsole.filter.jswarn", true);
 pref("devtools.webconsole.filter.jslog", true);
 pref("devtools.webconsole.filter.error", true);
 pref("devtools.webconsole.filter.warn", true);
 pref("devtools.webconsole.filter.info", true);
 pref("devtools.webconsole.filter.log", true);
--- a/browser/base/content/test/general/browser_popupNotification.js
+++ b/browser/base/content/test/general/browser_popupNotification.js
@@ -144,70 +144,38 @@ function basicNotification() {
           self.shownCallbackTriggered = true;
           break;
         case "removed":
           self.removedCallbackTriggered = true;
           break;
       }
     }
   };
-  this.addOptions = function(options) {
-    for (let [name, value] in Iterator(options))
-      self.options[name] = value;
-  }
 }
 
+basicNotification.prototype.addOptions = function(options) {
+  for (let [name, value] in Iterator(options))
+    this.options[name] = value;
+};
+
 function errorNotification() {
   var self = this;
-  this.browser = gBrowser.selectedBrowser;
-  this.id = "test-notification-" + gTestIndex;
-  this.message = "This is popup notification " + this.id + " from test " + gTestIndex;
-  this.anchorID = null;
-  this.mainAction = {
-    label: "Main Action",
-    accessKey: "M",
-    callback: function () {
-      self.mainActionClicked = true;
-      throw new Error("Oops!");
-    }
+  this.mainAction.callback = function () {
+    self.mainActionClicked = true;
+    throw new Error("Oops!");
   };
-  this.secondaryActions = [
-    {
-      label: "Secondary Action",
-      accessKey: "S",
-      callback: function () {
-        self.secondaryActionClicked = true;
-        throw new Error("Oops!");
-      }
-    }
-  ];
-  this.options = {
-    eventCallback: function (eventName) {
-      switch (eventName) {
-        case "dismissed":
-          self.dismissalCallbackTriggered = true;
-          break;
-        case "showing":
-          self.showingCallbackTriggered = true;
-          break;
-        case "shown":
-          self.shownCallbackTriggered = true;
-          break;
-        case "removed":
-          self.removedCallbackTriggered = true;
-          break;
-      }
-    }
+  this.secondaryActions[0].callback = function () {
+    self.secondaryActionClicked = true;
+    throw new Error("Oops!");
   };
-  this.addOptions = function(options) {
-    for (let [name, value] in Iterator(options))
-      self.options[name] = value;
-  }
 }
 
+errorNotification.prototype = new basicNotification();
+errorNotification.prototype.constructor = errorNotification;
+
 var wrongBrowserNotificationObject = new basicNotification();
 var wrongBrowserNotification;
 
 var tests = [
   { // Test #0
     run: function () {
       this.notifyObj = new basicNotification();
       showNotification(this.notifyObj);
--- a/browser/devtools/app-manager/content/projects.js
+++ b/browser/devtools/app-manager/content/projects.js
@@ -9,17 +9,17 @@ const Cr = Components.results;
 Cu.import("resource:///modules/devtools/gDevTools.jsm");
 const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 const {require} = devtools;
 const {ConnectionManager, Connection} = require("devtools/client/connection-manager");
 const {AppProjects} = require("devtools/app-manager/app-projects");
 const {AppValidator} = require("devtools/app-manager/app-validator");
 const {Services} = Cu.import("resource://gre/modules/Services.jsm");
 const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm");
-const {installHosted, installPackaged, getTargetForApp} = require("devtools/app-actor-front");
+const {installHosted, installPackaged, getTargetForApp, reloadApp} = require("devtools/app-actor-front");
 const {EventEmitter} = Cu.import("resource:///modules/devtools/shared/event-emitter.js");
 
 const promise = require("sdk/core/promise");
 
 const MANIFEST_EDITOR_ENABLED = "devtools.appmanager.manifestEditor.enabled";
 
 window.addEventListener("message", function(event) {
   try {
@@ -171,26 +171,36 @@ let UI = {
         })
         .then(() => {
            // Install the app to the device if we are connected,
            // and there is no error
            if (project.errorsCount == 0 && this.listTabsResponse) {
              return this.install(project);
            }
          })
-        .then(
-         () => {
+        .then(() => {
            button.disabled = false;
-         },
-         (res) => {
-           button.disabled = false;
-           let message = res.error + ": " + res.message;
-           alert(message);
-           this.connection.log(message);
-         });
+           // Finally try to reload the app if it is already opened
+           this.reload(project);
+        },
+        (res) => {
+          button.disabled = false;
+          let message = res.error + ": " + res.message;
+          alert(message);
+          this.connection.log(message);
+        });
+  },
+
+  reload: function (project) {
+    return reloadApp(this.connection.client,
+              this.listTabsResponse.webappsActor,
+              this._getProjectManifestURL(project)).
+      then(() => {
+        this.connection.log("App reloaded");
+      });
   },
 
   remove: function(location, event) {
     if (event) {
       // We don't want the "click" event to be propagated to the project item.
       // That would trigger `selectProject()`.
       event.stopPropagation();
     }
--- a/browser/devtools/shadereditor/test/head.js
+++ b/browser/devtools/shadereditor/test/head.js
@@ -196,17 +196,17 @@ function ensurePixelIs(aDebuggee, aPosit
 function navigate(aTarget, aUrl) {
   let navigated = once(aTarget, "navigate");
   aTarget.client.activeTab.navigateTo(aUrl);
   return navigated;
 }
 
 function reload(aTarget) {
   let navigated = once(aTarget, "navigate");
-  aTarget.client.activeTab.reload();
+  executeSoon(() => aTarget.client.activeTab.reload());
   return navigated;
 }
 
 function initBackend(aUrl) {
   info("Initializing a shader editor front.");
 
   if (!DebuggerServer.initialized) {
     DebuggerServer.init(() => true);
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -516,19 +516,16 @@
 @BINPATH@/components/Push.js
 @BINPATH@/components/Push.manifest
 @BINPATH@/components/PushServiceLauncher.js
 @BINPATH@/components/TCPSocket.js
 @BINPATH@/components/TCPServerSocket.js
 @BINPATH@/components/TCPSocketParentIntermediary.js
 @BINPATH@/components/TCPSocket.manifest
 
-@BINPATH@/components/AppProtocolHandler.js
-@BINPATH@/components/AppProtocolHandler.manifest
-
 @BINPATH@/components/Payment.js
 @BINPATH@/components/PaymentFlowInfo.js
 @BINPATH@/components/PaymentRequestInfo.js
 @BINPATH@/components/Payment.manifest
 
 #ifdef MOZ_WEBRTC
 @BINPATH@/components/PeerConnection.js
 @BINPATH@/components/PeerConnection.manifest
--- a/browser/metro/base/content/browser.xul
+++ b/browser/metro/base/content/browser.xul
@@ -233,17 +233,18 @@
             <box id="identity-box" align="center" role="button">
               <image id="identity-icon"/>
             </box>
 
             <textbox id="urlbar-edit" type="url" flex="1"
                      autocompletesearch="history"
                      autocompletepopup="urlbar-autocomplete"
                      completeselectedindex="true"
-                     placeholder="&urlbar.emptytext;"/>
+                     placeholder="&urlbar.emptytext;"
+                     onclick="SelectionHelperUI.urlbarClick();"/>
 
             <toolbarbutton id="go-button" class="urlbar-button"
                            command="cmd_go"/>
             <toolbarbutton id="reload-button" class="urlbar-button"
                            oncommand="CommandUpdater.doCommand(
                                         event.shiftKey ? 'cmd_forceReload'
                                                        : 'cmd_reload');"/>
             <toolbarbutton id="stop-button" class="urlbar-button"
--- a/browser/metro/base/content/contenthandlers/SelectionHandler.js
+++ b/browser/metro/base/content/contenthandlers/SelectionHandler.js
@@ -20,16 +20,17 @@ var SelectionHandler = {
     addMessageListener("Browser:SelectionCopy", this);
     addMessageListener("Browser:SelectionDebug", this);
     addMessageListener("Browser:CaretAttach", this);
     addMessageListener("Browser:CaretMove", this);
     addMessageListener("Browser:CaretUpdate", this);
     addMessageListener("Browser:SelectionSwitchMode", this);
     addMessageListener("Browser:RepositionInfoRequest", this);
     addMessageListener("Browser:SelectionHandlerPing", this);
+    addMessageListener("Browser:ResetLastPos", this);
   },
 
   shutdown: function shutdown() {
     removeMessageListener("Browser:SelectionStart", this);
     removeMessageListener("Browser:SelectionAttach", this);
     removeMessageListener("Browser:SelectionEnd", this);
     removeMessageListener("Browser:SelectionMoveStart", this);
     removeMessageListener("Browser:SelectionMove", this);
@@ -39,16 +40,17 @@ var SelectionHandler = {
     removeMessageListener("Browser:SelectionCopy", this);
     removeMessageListener("Browser:SelectionDebug", this);
     removeMessageListener("Browser:CaretAttach", this);
     removeMessageListener("Browser:CaretMove", this);
     removeMessageListener("Browser:CaretUpdate", this);
     removeMessageListener("Browser:SelectionSwitchMode", this);
     removeMessageListener("Browser:RepositionInfoRequest", this);
     removeMessageListener("Browser:SelectionHandlerPing", this);
+    removeMessageListener("Browser:ResetLastPos", this);
   },
 
   sendAsync: function sendAsync(aMsg, aJson) {
     sendAsyncMessage(aMsg, aJson);
   },
 
   /*************************************************
    * Browser event handlers
@@ -538,16 +540,20 @@ var SelectionHandler = {
         content.setTimeout (function () {
           SelectionHandler._repositionInfoRequest(json);
         }, 50);
         break;
 
       case "Browser:SelectionHandlerPing":
         this._onPing(json.id);
         break;
+
+      case "Browser:ResetLastPos":
+        this._onClickCoords(json.xPos, json.yPos);
+        break;
     }
   },
 
   /*************************************************
    * Utilities
    */
 
   /*
--- a/browser/metro/base/content/helperui/SelectionHelperUI.js
+++ b/browser/metro/base/content/helperui/SelectionHelperUI.js
@@ -787,16 +787,26 @@ var SelectionHelperUI = {
       this.startMark.show();
     }
   },
 
   /*
    * Event handlers for document events
    */
 
+   urlbarClick: function() {
+    // Workaround for bug 925457: taping browser chrome resets last tap
+    // co-ordinates to 'undefined' so that we know not to shift the browser
+    // when the keyboard is up (in SelectionHandler._calcNewContentPosition())
+    Browser.selectedTab.browser.messageManager.sendAsyncMessage("Browser:ResetLastPos", {
+      xPos: null,
+      yPos: null
+    });
+   },
+
   /*
    * Handles taps that move the current caret around in text edits,
    * clear active selection and focus when neccessary, or change
    * modes.
    */
   _onClick: function(aEvent) {
     if (this.layerMode == kChromeLayer && this._targetIsEditable) {
       this.attachToCaret(this._msgTarget, aEvent.clientX, aEvent.clientY);
--- a/browser/metro/profile/metro.js
+++ b/browser/metro/profile/metro.js
@@ -643,8 +643,12 @@ pref("full-screen-api.content-only", tru
 pref("full-screen-api.ignore-widgets", true);
 
 // image visibility prefs.
 // image visibility tries to only keep images near the viewport decoded instead
 // of keeping all images decoded.
 pref("layout.imagevisibility.enabled", true);
 pref("layout.imagevisibility.numscrollportwidths", 1);
 pref("layout.imagevisibility.numscrollportheights", 1);
+
+// Don't enable <input type=color> yet as we don't have a color picker
+// implemented for Windows Metro (bug 895464)
+pref("dom.forms.color", false);
--- a/browser/themes/shared/devtools/dark-theme.css
+++ b/browser/themes/shared/devtools/dark-theme.css
@@ -58,34 +58,34 @@
 
 .theme-link,
 .cm-s-mozilla .cm-link { /* blue */
   color: #3689b2;
 }
 
 .theme-comment,
 .cm-s-mozilla .cm-meta,
-.cm-s-mozilla .cm-hr { /* grey */
+.cm-s-mozilla .cm-hr,
+.cm-s-mozilla .cm-comment { /* grey */
   color: #5c6773;
 }
 
 .theme-gutter {
   background-color: #0f171f;
   color: #667380;
   border-color: #303b47;
 }
 
 .theme-separator { /* grey */
   border-color: #303b47;
 }
 
 .theme-fg-color1,
 .cm-s-mozilla .cm-variable-2,
-.cm-s-mozilla .cm-quote,
-.cm-s-mozilla .CodeMirror-matchingbracket { /* green */
+.cm-s-mozilla .cm-quote { /* green */
   color: #5c9966;
 }
 
 .theme-fg-color2,
 .cm-s-mozilla .cm-attribute,
 .cm-s-mozilla .cm-builtin,
 .cm-s-mozilla .cm-variable,
 .cm-s-mozilla .cm-def,
@@ -96,35 +96,33 @@
 }
 
 .theme-fg-color3,
 .cm-s-mozilla .cm-tag,
 .cm-s-mozilla .cm-header { /* pink/lavender */
   color: #a673bf;
 }
 
-.theme-fg-color4,
-.cm-s-mozilla .cm-comment { /* purple/violet */
+.theme-fg-color4 { /* purple/violet */
   color: #6270b2;
 }
 
 .theme-fg-color5,
 .cm-s-mozilla .cm-bracket,
 .cm-s-mozilla .cm-atom,
 .cm-s-mozilla .cm-keyword { /* Yellow */
   color: #a18650;
 }
 
 .theme-fg-color6,
 .cm-s-mozilla .cm-string  { /* Orange */
   color: #b26b47;
 }
 
 .theme-fg-color7,
-.cm-s-mozilla .CodeMirror-nonmatchingbracket,
 .cm-s-mozilla .cm-string-2,
 .cm-s-mozilla .cm-error { /* Red */
   color: #bf5656;
 }
 
 .theme-fg-contrast { /* To be used for text on theme-bg-contrast */
   color: black;
 }
@@ -155,20 +153,28 @@
 .cm-s-mozilla .CodeMirror-lines .CodeMirror-cursor {
   border-left: solid 1px #fff;
 }
 
 .cm-s-mozilla.CodeMirror-focused .CodeMirror-selected { /* selected text (focused) */
   background: rgb(185, 215, 253);
 }
 
-.dcm-s-mozilla .CodeMirror-selected { /* selected text (unfocused) */
+.cm-s-mozilla .CodeMirror-selected { /* selected text (unfocused) */
   background: rgb(176, 176, 176);
 }
 
 .CodeMirror-activeline-background { /* selected color with alpha */
-  background: rgba(185, 215, 253, .05);
+  background: rgba(185, 215, 253, .15);
+}
+
+.cm-s-mozilla .CodeMirror-linenumber { /* line number text */
+  color: #5f7387;
+}
+
+.cm-s-mozilla .CodeMirror-gutters { /* vertical line next to line numbers */
+  border-right-color: #343c45;
 }
 
 .cm-s-markup-view pre {
   line-height: 1.4em;
   min-height: 1.4em;
 }
--- a/browser/themes/shared/devtools/light-theme.css
+++ b/browser/themes/shared/devtools/light-theme.css
@@ -58,34 +58,34 @@
 
 .theme-link,
 .cm-s-mozilla .cm-link { /* blue */
   color: hsl(208,56%,40%);
 }
 
 .theme-comment,
 .cm-s-mozilla .cm-meta,
-.cm-s-mozilla .cm-hr { /* grey */
+.cm-s-mozilla .cm-hr,
+.cm-s-mozilla .cm-comment { /* grey */
   color: hsl(90,2%,46%);
 }
 
 .theme-gutter {
   background-color: hsl(0,0%,90%);
   color: #667380;
   border-color: hsl(0,0%,65%);
 }
 
 .theme-separator { /* grey */
   border-color: #cddae5;
 }
 
 .theme-fg-color1,
 .cm-s-mozilla .cm-variable-2,
-.cm-s-mozilla .cm-quote,
-.cm-s-mozilla .CodeMirror-matchingbracket { /* green */
+.cm-s-mozilla .cm-quote { /* green */
   color: hsl(72,100%,27%);
 }
 
 .theme-fg-color2,
 .cm-s-mozilla .cm-attribute,
 .cm-s-mozilla .cm-builtin,
 .cm-s-mozilla .cm-variable,
 .cm-s-mozilla .cm-def,
@@ -96,35 +96,33 @@
 }
 
 .theme-fg-color3,
 .cm-s-mozilla .cm-tag,
 .cm-s-mozilla .cm-header { /* dark blue */
   color: hsl(208,81%,21%)
 }
 
-.theme-fg-color4,
-.cm-s-mozilla .cm-comment { /* Orange */
+.theme-fg-color4 { /* Orange */
   color: hsl(24,85%,39%);
 }
 
 .theme-fg-color5,
 .cm-s-mozilla .cm-bracket,
 .cm-s-mozilla .cm-keyword,
 .cm-s-mozilla .cm-atom { /* Yellow */
   color: #a18650;
 }
 
 .theme-fg-color6,
 .cm-s-mozilla .cm-string { /* Orange */
   color: hsl(24,85%,39%);
 }
 
 .theme-fg-color7,
-.cm-s-mozilla .CodeMirror-nonmatchingbracket,
 .cm-s-mozilla .cm-string-2,
 .cm-s-mozilla .cm-error { /* Red */
   color: #bf5656;
 }
 
 .theme-fg-contrast { /* To be used for text on theme-bg-contrast */
   color: black;
 }
@@ -160,15 +158,28 @@
   background: rgb(185, 215, 253);
 }
 
 .cm-s-mozilla .CodeMirror-selected { /* selected text (unfocused) */
   background: rgb(176, 176, 176);
 }
 
 .CodeMirror-activeline-background { /* selected color with alpha */
-  background: rgba(185, 215, 253, .4);
+  background: rgba(185, 215, 253, .35);
+}
+
+div.cm-s-mozilla span.CodeMirror-matchingbracket { /* highlight brackets */
+  outline: solid 1px rgba(0, 0, 0, .25);
+  color: black;
+}
+
+.cm-s-mozilla .CodeMirror-linenumber { /* line number text */
+  color: #667380;
+}
+
+.cm-s-mozilla .CodeMirror-gutters { /* vertical line next to line numbers */
+  border-right-color: #a6a6a6;
 }
 
 .cm-s-markup-view pre {
   line-height: 1.4em;
   min-height: 1.4em;
 }
--- a/build/ConfigStatus.py
+++ b/build/ConfigStatus.py
@@ -20,64 +20,51 @@ from mozbuild.backend.recursivemake impo
 from mozbuild.frontend.emitter import TreeMetadataEmitter
 from mozbuild.frontend.reader import BuildReader
 from mozbuild.mozinfo import write_mozinfo
 
 
 log_manager = LoggingManager()
 
 
-def config_status(topobjdir = '.', topsrcdir = '.',
-                  defines = [], non_global_defines = [], substs = [],
-                  files = [], headers = []):
+def config_status(topobjdir='.', topsrcdir='.',
+        defines=[], non_global_defines=[], substs=[]):
     '''Main function, providing config.status functionality.
 
     Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS
-    variables, but like config.status from autoconf 2.6, single files may be
-    generated with the --file and --header options. Several such options can
-    be given to generate several files at the same time.
+    variables.
 
     Without the -n option, this program acts as config.status and considers
     the current directory as the top object directory, even when config.status
     is in a different directory. It will, however, treat the directory
-    containing config.status as the top object directory with the -n option,
-    while files given to the --file and --header arguments are considered
-    relative to the current directory.
+    containing config.status as the top object directory with the -n option.
 
     The --recheck option, like with the original config.status, runs configure
     again, with the options given in the "ac_configure_args" subst.
 
     The options to this function are passed when creating the
-    ConfigEnvironment, except for files and headers, which contain the list
-    of files and headers to be generated by default. These lists, as well as
-    the actual wrapper script around this function, are meant to be generated
-    by configure. See build/autoconf/config.status.m4.
-
-    Unlike config.status behaviour with CONFIG_FILES and CONFIG_HEADERS,
-    but like config.status behaviour with --file and --header, providing
-    files or headers on the command line inhibits the default generation of
-    files when given headers and headers when given files.
-
-    Unlike config.status, the FILE:TEMPLATE syntax is not supported for
-    files and headers. The template is always the filename suffixed with
-    '.in', in the corresponding directory under the top source directory.
+    ConfigEnvironment. These lists, as well as the actual wrapper script
+    around this function, are meant to be generated by configure.
+    See build/autoconf/config.status.m4.
     '''
 
     if 'CONFIG_FILES' in os.environ:
-        raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.'
+        raise Exception('Using the CONFIG_FILES environment variable is not '
+            'supported.')
     if 'CONFIG_HEADERS' in os.environ:
-        raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.'
+        raise Exception('Using the CONFIG_HEADERS environment variable is not '
+            'supported.')
+
+    if not os.path.isabs(topsrcdir):
+        raise Exception('topsrcdir must be defined as an absolute directory: '
+            '%s' % topsrcdir)
 
     parser = OptionParser()
     parser.add_option('--recheck', dest='recheck', action='store_true',
                       help='update config.status by reconfiguring in the same conditions')
-    parser.add_option('--file', dest='files', metavar='FILE', action='append',
-                      help='instantiate the configuration file FILE')
-    parser.add_option('--header', dest='headers', metavar='FILE', action='append',
-                      help='instantiate the configuration header FILE')
     parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
                       help='display verbose output')
     parser.add_option('-n', dest='not_topobjdir', action='store_true',
                       help='do not consider current directory as top object directory')
     (options, args) = parser.parse_args()
 
     # Without -n, the current directory is meant to be the top object directory
     if not options.not_topobjdir:
@@ -94,44 +81,20 @@ def config_status(topobjdir = '.', topsr
     reader = BuildReader(env)
     emitter = TreeMetadataEmitter(env)
     backend = RecursiveMakeBackend(env)
     # This won't actually do anything because of the magic of generators.
     definitions = emitter.emit(reader.read_topsrcdir())
 
     if options.recheck:
         # Execute configure from the top object directory
-        if not os.path.isabs(topsrcdir):
-            topsrcdir = relpath(topsrcdir, topobjdir)
         os.chdir(topobjdir)
         os.execlp('sh', 'sh', '-c', ' '.join([os.path.join(topsrcdir, 'configure'), env.substs['ac_configure_args'], '--no-create', '--no-recursion']))
 
-    if options.files:
-        files = options.files
-        headers = []
-    if options.headers:
-        headers = options.headers
-        if not options.files:
-            files = []
-    # Default to display messages when giving --file or --headers on the
-    # command line.
-    log_level = logging.INFO
-
-    if options.files or options.headers or options.verbose:
-        log_level = logging.DEBUG
-
+    log_level = logging.DEBUG if options.verbose else logging.INFO
     log_manager.add_terminal_logging(level=log_level)
     log_manager.enable_unstructured()
 
-    if not options.files and not options.headers:
-        print('Reticulating splines...', file=sys.stderr)
-        summary = backend.consume(definitions)
-
-        for line in summary.summaries():
-            print(line, file=sys.stderr)
+    print('Reticulating splines...', file=sys.stderr)
+    summary = backend.consume(definitions)
 
-        files = [os.path.join(topobjdir, f) for f in files]
-        headers = [os.path.join(topobjdir, f) for f in headers]
-
-    for file in files:
-        env.create_config_file(file)
-    for header in headers:
-        env.create_config_header(header)
+    for line in summary.summaries():
+        print(line, file=sys.stderr)
--- a/build/autoconf/config.status.m4
+++ b/build/autoconf/config.status.m4
@@ -37,17 +37,17 @@ define([_MOZ_AC_DEFINE_UNQUOTED], defn([
 define([AC_DEFINE_UNQUOTED],
 [cat >> confdefs.pytmp <<EOF
     (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
 EOF
 ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl
 ])
 
 dnl Replace AC_OUTPUT to create and call a python config.status
-define([AC_OUTPUT],
+define([_MOZ_AC_OUTPUT],
 [dnl Top source directory in Windows format (as opposed to msys format).
 WIN_TOP_SRC=
 encoding=utf-8
 case "$host_os" in
 mingw*)
     WIN_TOP_SRC=`cd $srcdir; pwd -W`
     encoding=mbcs
     ;;
@@ -116,57 +116,30 @@ dnl Add in the output from the subconfig
 for ac_subst_arg in $_subconfigure_ac_subst_args; do
   variable='$'$ac_subst_arg
   echo "    (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS
 done
 
 cat >> $CONFIG_STATUS <<\EOF
 ] ]
 
-dnl List of files to apply AC_SUBSTs to. This is the list of files given
-dnl as an argument to AC_OUTPUT ($1)
-files = [
-EOF
-
-for out in $1; do
-  echo "    '$out'," >> $CONFIG_STATUS
-done
-
-cat >> $CONFIG_STATUS <<\EOF
-]
-
-dnl List of header files to apply AC_DEFINEs to. This is stored in the
-dnl AC_LIST_HEADER m4 macro by AC_CONFIG_HEADER.
-headers = [
-EOF
-
-ifdef(<<<AC_LIST_HEADER>>>, <<<
-HEADERS="AC_LIST_HEADER"
-for header in $HEADERS; do
-  echo "    '$header'," >> $CONFIG_STATUS
-done
->>>)dnl
-
-cat >> $CONFIG_STATUS <<\EOF
-]
-
 dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
 non_global_defines = [
 EOF
 
 if test -n "$_NON_GLOBAL_ACDEFINES"; then
   for var in $_NON_GLOBAL_ACDEFINES; do
     echo "    '$var'," >> $CONFIG_STATUS
   done
 fi
 
 cat >> $CONFIG_STATUS <<EOF
 ]
 
-__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs', 'files', 'headers']
+__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs']
 
 dnl Do the actual work
 if __name__ == '__main__':
     args = dict([(name, globals()[name]) for name in __all__])
     import sys
 dnl Don't rely on virtualenv here. Standalone js doesn't use it.
     sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
     from ConfigStatus import config_status
@@ -177,9 +150,23 @@ chmod +x $CONFIG_STATUS
 rm -fr confdefs* $ac_clean_files
 dnl Execute config.status, unless --no-create was passed to configure.
 if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
     trap '' EXIT
     exit 1
 fi
 ])
 
+define([m4_fatal],[
+errprint([$1
+])
+m4exit(1)
+])
+
+define([AC_OUTPUT], [ifelse($#_$1, 1_, [_MOZ_AC_OUTPUT()],
+[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])]
+)])
+
+define([AC_CONFIG_HEADER],
+[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
+])
+
 AC_SUBST([MOZ_PSEUDO_DERECURSE])
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -344,30 +344,8 @@ class B2GRemoteAutomation(Automation):
         def wait(self, timeout=None):
             # this should never happen
             raise Exception("'wait' called on B2GInstance")
 
         def kill(self):
             # this should never happen
             raise Exception("'kill' called on B2GInstance")
 
-
-class B2GDesktopAutomation(Automation):
-
-    def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
-        """ build the application command line """
-
-        cmd = os.path.abspath(app)
-        args = []
-
-        if debuggerInfo:
-            args.extend(debuggerInfo["args"])
-            args.append(cmd)
-            cmd = os.path.abspath(debuggerInfo["path"])
-
-        if self.IS_MAC:
-            args.append("-foreground")
-
-        profileDirectory = profileDir + "/"
-
-        args.extend(("-profile", profileDirectory))
-        args.extend(extraArgs)
-        return cmd, args
--- a/build/mobile/robocop/PaintedSurface.java.in
+++ b/build/mobile/robocop/PaintedSurface.java.in
@@ -1,16 +1,21 @@
 #filter substitution
 /* 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/. */
 
 package @ANDROID_PACKAGE_NAME@;
 
+import android.graphics.Bitmap;
+import android.util.Base64;
+import android.util.Base64OutputStream;
+
 import java.io.BufferedWriter;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
 
 public class PaintedSurface {
     private String mFileName;
     private int mWidth;
@@ -39,38 +44,62 @@ public class PaintedSurface {
     public final int getWidth() {
         return mWidth;
     }
 
     public final int getHeight() {
         return mHeight;
     }
 
+    private int pixelAtIndex(int index) {
+        int b1 = mPixelBuffer.get(index) & 0xFF;
+        int b2 = mPixelBuffer.get(index + 1) & 0xFF;
+        int b3 = mPixelBuffer.get(index + 2) & 0xFF;
+        int b4 = mPixelBuffer.get(index + 3) & 0xFF;
+        int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0);
+        return value;
+    }
+
     public final int getPixelAt(int x, int y) {
         if (mPixelBuffer == null) {
             throw new RoboCopException("Trying to access PaintedSurface with no active PixelBuffer");
         }
 
         if (x >= mWidth || x < 0) {
             throw new RoboCopException("Trying to access PaintedSurface with invalid x value");
         }
 
         if (y >= mHeight || y < 0) {
             throw new RoboCopException("Trying to access PaintedSurface with invalid y value");
         }
 
         // The rows are reversed so row 0 is at the end and we start with the last row.
         // This is why we do mHeight-y;
         int index = (x + ((mHeight - y - 1) * mWidth)) * 4;
-        int b1 = mPixelBuffer.get(index) & 0xFF;
-        int b2 = mPixelBuffer.get(index + 1) & 0xFF;
-        int b3 = mPixelBuffer.get(index + 2) & 0xFF;
-        int b4 = mPixelBuffer.get(index + 3) & 0xFF;
-        int value = (b1 << 24) + (b2 << 16) + (b3 << 8) + (b4 << 0);
-        return value;
+        return pixelAtIndex(index);
+    }
+
+    public final String asDataUri() {
+        try {
+            Bitmap bm = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
+            for (int y = 0; y < mHeight; y++) {
+                for (int x = 0; x < mWidth; x++) {
+                    int index = (x + ((mHeight - y - 1) * mWidth)) * 4;
+                    bm.setPixel(x, y, pixelAtIndex(index));
+                }
+            }
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            out.write("data:image/png;base64,".getBytes());
+            Base64OutputStream b64 = new Base64OutputStream(out, Base64.NO_WRAP);
+            bm.compress(Bitmap.CompressFormat.PNG, 100, b64);
+            return new String(out.toByteArray());
+        } catch (Exception e) {
+            FennecNativeDriver.log(FennecNativeDriver.LogLevel.ERROR, e);
+            throw new RoboCopException("Unable to convert surface to a PNG data:uri");
+        }
     }
 
     public void close() {
         try {
             mPixelFile.close();
         } catch (Exception e) {
             FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG, e);
         }
--- a/config/makefiles/xpidl/Makefile.in
+++ b/config/makefiles/xpidl/Makefile.in
@@ -1,15 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SUPPRESS_DEFAULT_RULES := 1
 STANDALONE_MAKEFILE := 1
-NO_MAKEFILE_RULE := 1
 
 include $(topsrcdir)/config/rules.mk
 
 # Building XPIDLs effectively consists of two steps:
 #
 #   1) Staging all .idl files to a common directory.
 #   2) Doing everything with the .idl files.
 #
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -597,36 +597,31 @@ ifndef MOZBUILD_BACKEND_CHECKED
 
 # Since Makefile is listed as a global dependency, this has the
 # unfortunate side-effect of invalidating all targets if it is executed.
 # So e.g. if you are in /dom/bindings and /foo/moz.build changes,
 # /dom/bindings will get invalidated. The upside is if the current
 # Makefile/backend.mk is updated as a result of backend regeneration, we
 # actually pick up the changes. This should reduce the amount of
 # required clobbers and is thus the lesser evil.
-Makefile: $(DEPTH)/backend.RecursiveMakeBackend.built
+Makefile: $(DEPTH)/backend.RecursiveMakeBackend
 	@$(TOUCH) $@
 
-$(DEPTH)/backend.RecursiveMakeBackend.built:
+$(DEPTH)/backend.RecursiveMakeBackend:
 	@echo "Build configuration changed. Regenerating backend."
 	@cd $(DEPTH) && $(PYTHON) ./config.status
 	@$(TOUCH) $@
 
-include $(DEPTH)/backend.RecursiveMakeBackend.built.pp
+include $(DEPTH)/backend.RecursiveMakeBackend.pp
 
-default:: $(DEPTH)/backend.RecursiveMakeBackend.built
+default:: $(DEPTH)/backend.RecursiveMakeBackend
 
 export MOZBUILD_BACKEND_CHECKED=1
 endif
 
-
-# SUBMAKEFILES: List of Makefiles for next level down.
-#   This is used to update or create the Makefiles before invoking them.
-SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
-
 # The root makefile doesn't want to do a plain export/libs, because
 # of the tiers and because of libxul. Suppress the default rules in favor
 # of something else. Makefiles which use this var *must* provide a sensible
 # default rule before including rules.mk
 ifndef SUPPRESS_DEFAULT_RULES
 default all::
 	$(MAKE) export
 ifdef MOZ_PSEUDO_DERECURSE
@@ -644,35 +639,24 @@ ECHO := true
 QUIET := -q
 endif
 
 # Do everything from scratch
 everything::
 	$(MAKE) clean
 	$(MAKE) all
 
-# Target to only regenerate makefiles
-makefiles: $(SUBMAKEFILES)
-ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS))
-	$(LOOP_OVER_PARALLEL_DIRS)
-	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
-endif
-
 ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS)))
 $(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only)
 endif
 
 HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS))
 
 # Dependencies which, if modified, should cause everything to rebuild
 GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk
-ifndef NO_MAKEFILE_RULE
-GLOBAL_DEPS += Makefile.in
-endif
 
 ##############################################
 OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
 
 compile:: $(OBJ_TARGETS)
 
 include $(topsrcdir)/config/makefiles/target_libs.mk
 
@@ -737,30 +721,30 @@ endif
 
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
 ##############################################
 
 checkout:
 	$(MAKE) -C $(topsrcdir) -f client.mk checkout
 
-clean clobber realclean clobber_all:: $(SUBMAKEFILES)
+clean clobber realclean clobber_all::
 	-$(RM) $(ALL_TRASH)
 	-$(RM) -r $(ALL_TRASH_DIRS)
 
 ifdef TIERS
 clean clobber realclean clobber_all distclean::
 	$(foreach dir, \
 		$(foreach tier, $(TIERS), $(tier_$(tier)_staticdirs) $(tier_$(tier)_dirs)), \
 		-$(call SUBMAKE,$@,$(dir)))
 else
 clean clobber realclean clobber_all distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 
-distclean:: $(SUBMAKEFILES)
+distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 endif
 
 distclean::
 	-$(RM) -r $(ALL_TRASH_DIRS)
 	-$(RM) $(ALL_TRASH)  \
 	Makefile .HSancillary \
 	$(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
@@ -1158,44 +1142,16 @@ endif
 ###############################################################################
 # Java rules
 ###############################################################################
 ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS))
   include $(topsrcdir)/config/makefiles/java-build.mk
 endif
 
 ###############################################################################
-# Update Files Managed by Build Backend
-###############################################################################
-
-ifndef NO_MAKEFILE_RULE
-Makefile: Makefile.in
-	@$(PYTHON) $(DEPTH)/config.status -n --file=Makefile
-	@$(TOUCH) $@
-endif
-
-ifndef NO_SUBMAKEFILES_RULE
-ifdef SUBMAKEFILES
-# VPATH does not work on some machines in this case, so add $(srcdir)
-$(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@"
-	@$(TOUCH) "$@"
-endif
-endif
-
-ifdef AUTOUPDATE_CONFIGURE
-$(topsrcdir)/configure: $(topsrcdir)/configure.in
-	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck
-endif
-
-$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
-	$(PYTHON) $(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk
-	$(TOUCH) $@
-
-###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
 ###############################################################################
 
 ifneq ($(XPI_NAME),)
 $(FINAL_TARGET):
 	$(NSINSTALL) -D $@
 
 export:: $(FINAL_TARGET)
@@ -1620,34 +1576,34 @@ endif
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
 tags: TAGS
 
-TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+TAGS: $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	-etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 
 ifndef INCLUDED_DEBUGMAKE_MK #{
   ## Only parse when an echo* or show* target is requested
   ifneq (,$(call isTargetStem,echo,show))
     include $(topsrcdir)/config/makefiles/debugmake.mk
   endif #}
 endif #}
 
 documentation:
 	@cd $(DEPTH)
 	$(DOXYGEN) $(DEPTH)/config/doxygen.cfg
 
 ifdef ENABLE_TESTS
-check:: $(SUBMAKEFILES)
+check::
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 endif
 
 
 FREEZE_VARIABLES = \
   CSRCS \
--- a/configure.in
+++ b/configure.in
@@ -3980,17 +3980,17 @@ MOZ_UNIVERSALCHARDET=1
 MOZ_URL_CLASSIFIER=
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
 MOZ_PDF_PRINTING=
 MOZ_DISABLE_CRYPTOLEGACY=
 NSS_DISABLE_DBM=
 NECKO_COOKIES=1
-NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
+NECKO_PROTOCOLS_DEFAULT="about app data file ftp http res viewsource websocket wyciwyg device"
 USE_ARM_KUSER=
 BUILD_CTYPES=1
 MOZ_USE_NATIVE_POPUP_WINDOWS=
 MOZ_ANDROID_HISTORY=
 MOZ_WEBSMS_BACKEND=
 MOZ_ANDROID_BEAM=
 ACCESSIBILITY=1
 MOZ_TIME_MANAGER=
@@ -8767,27 +8767,20 @@ HAVE_STATVFS
 HAVE_STATFS64
 HAVE_STATFS
 HAVE_SYS_STATVFS_H
 HAVE_SYS_STATFS_H
 HAVE_SYS_VFS_H
 HAVE_SYS_MOUNT_H
 "
 
-# FUTURE? Consider moving all these to moz.build files.
-AC_CONFIG_HEADER(
-netwerk/necko-config.h
-xpcom/xpcom-config.h
-xpcom/xpcom-private.h
-)
-
 AC_SUBST(STLPORT_LIBS)
 
 export WRITE_MOZINFO=1
-AC_OUTPUT([mozilla-config.h])
+AC_OUTPUT()
 unset WRITE_MOZINFO
 
 # Hack around an Apple bug that affects the egrep that comes with OS X 10.7.
 # "env ARCHPREFERENCE=i386,x86_64 arch egrep" first tries to use the 32-bit
 # Intel part of the egrep fat binary, even on 64-bit systems, and falls back on
 # the 64-bit part if it's not a fat binary, as can happen with MacPorts. We
 # (apparently) only need this hack when egrep's "pattern" is particularly long
 # (as in the following code) and the first egrep on our $PATH is Apple's.  See
--- a/content/events/src/nsDOMKeyboardEvent.cpp
+++ b/content/events/src/nsDOMKeyboardEvent.cpp
@@ -18,16 +18,17 @@ nsDOMKeyboardEvent::nsDOMKeyboardEvent(m
   NS_ASSERTION(mEvent->eventStructType == NS_KEY_EVENT, "event type mismatch");
 
   if (aEvent) {
     mEventIsInternal = false;
   }
   else {
     mEventIsInternal = true;
     mEvent->time = PR_Now();
+    mEvent->AsKeyboardEvent()->mKeyNameIndex = KEY_NAME_INDEX_USE_STRING;
   }
 }
 
 NS_IMPL_ADDREF_INHERITED(nsDOMKeyboardEvent, nsDOMUIEvent)
 NS_IMPL_RELEASE_INHERITED(nsDOMKeyboardEvent, nsDOMUIEvent)
 
 NS_INTERFACE_MAP_BEGIN(nsDOMKeyboardEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMKeyEvent)
@@ -97,19 +98,17 @@ nsDOMKeyboardEvent::GetModifierState(con
 
   *aState = GetModifierState(aKey);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMKeyboardEvent::GetKey(nsAString& aKeyName)
 {
-  if (!mEventIsInternal) {
-    mEvent->AsKeyboardEvent()->GetDOMKeyName(aKeyName);
-  }
+  mEvent->AsKeyboardEvent()->GetDOMKeyName(aKeyName);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMKeyboardEvent::GetCharCode(uint32_t* aCharCode)
 {
   NS_ENSURE_ARG_POINTER(aCharCode);
   *aCharCode = CharCode();
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -130,17 +130,17 @@ RoundDown(double aDouble)
 {
   return (aDouble > 0) ? static_cast<int32_t>(floor(aDouble)) :
                          static_cast<int32_t>(ceil(aDouble));
 }
 
 static inline bool
 IsMouseEventReal(WidgetEvent* aEvent)
 {
-  NS_ABORT_IF_FALSE(aEvent->IsMouseDerivedEvent(), "Not a mouse event");
+  NS_ABORT_IF_FALSE(aEvent->AsMouseEvent(), "Not a mouse event");
   // Return true if not synthesized.
   return aEvent->AsMouseEvent()->reason == WidgetMouseEvent::eReal;
 }
 
 #ifdef DEBUG_DOCSHELL_FOCUS
 static void
 PrintDocTree(nsIDocShellTreeItem* aParentItem, int aLevel)
 {
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -12,16 +12,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsIObserver.h"
 #include "mozilla/CORSMode.h"
 #include "DOMMediaStream.h"
 #include "AudioChannelCommon.h"
 #include "DecoderTraits.h"
 #include "nsIAudioChannelAgent.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "mozilla/dom/TextTrackManager.h"
 
 // Define to output information on decoding and painting framerate
 /* #define DEBUG_FRAME_RATE 1 */
 
 class nsIChannel;
 class nsIHttpChannel;
 class nsILoadGroup;
@@ -508,22 +509,18 @@ public:
   uint32_t GetMozFrameBufferLength(ErrorResult& aRv) const;
 
   void SetMozFrameBufferLength(uint32_t aValue, ErrorResult& aRv);
 
   JSObject* MozGetMetadata(JSContext* aCx, ErrorResult& aRv);
 
   double MozFragmentEnd();
 
-  // XPCOM GetMozAudioChannelType() is OK
-
-  void SetMozAudioChannelType(const nsAString& aValue, ErrorResult& aRv)
-  {
-    SetHTMLAttr(nsGkAtoms::mozaudiochannel, aValue, aRv);
-  }
+  AudioChannel MozAudioChannelType() const;
+  void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
 
   TextTrackList* TextTracks() const;
 
   already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
                                            const nsAString& aLabel,
                                            const nsAString& aLanguage);
 
   void AddTextTrack(TextTrack* aTextTrack) {
--- a/content/html/content/src/HTMLMediaElement.cpp
+++ b/content/html/content/src/HTMLMediaElement.cpp
@@ -3923,10 +3923,46 @@ HTMLMediaElement::AddTextTrack(TextTrack
 void
 HTMLMediaElement::PopulatePendingTextTrackList()
 {
   if (mTextTrackManager) {
     mTextTrackManager->PopulatePendingList();
   }
 }
 
+AudioChannel
+HTMLMediaElement::MozAudioChannelType() const
+{
+  switch (mAudioChannelType) {
+    case AUDIO_CHANNEL_CONTENT:
+      return AudioChannel::Content;
+
+    case AUDIO_CHANNEL_NOTIFICATION:
+      return AudioChannel::Notification;
+
+    case AUDIO_CHANNEL_ALARM:
+      return AudioChannel::Alarm;
+
+    case AUDIO_CHANNEL_TELEPHONY:
+      return AudioChannel::Telephony;
+
+    case AUDIO_CHANNEL_RINGER:
+      return AudioChannel::Ringer;
+
+    case AUDIO_CHANNEL_PUBLICNOTIFICATION:
+      return AudioChannel::Publicnotification;
+
+    default:
+      return AudioChannel::Normal;
+  }
+}
+
+void
+HTMLMediaElement::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
+{
+  nsString channel;
+  channel.AssignASCII(AudioChannelValues::strings[uint32_t(aValue)].value,
+                      AudioChannelValues::strings[uint32_t(aValue)].length);
+  SetHTMLAttr(nsGkAtoms::mozaudiochannel, channel, aRv);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/content/html/content/test/test_mozaudiochannel.html
+++ b/content/html/content/test/test_mozaudiochannel.html
@@ -38,16 +38,16 @@ audio2.mozAudioChannelType = "alarm";
 ok(audio2.mozAudioChannelType == "alarm", "Default audio2 channel == 'alarm'");
 
 var audio3 = document.getElementById("audio3");
 ok(audio3, "Audio Element exists");
 ok(audio3.mozAudioChannelType == "content", "Default audio3 channel == 'content'");
 try {
 audio3.mozAudioChannelType = "foo";
 } catch(e) {}
-ok(audio3.mozAudioChannelType == "normal", "audio3 channel == 'normal'");
+ok(audio3.mozAudioChannelType == "content", "audio3 channel == 'content'");
 audio3.mozAudioChannelType = "alarm";
 ok(audio3.mozAudioChannelType == "alarm", "audio3 channel == 'alarm'");
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/media/TextTrack.cpp
+++ b/content/media/TextTrack.cpp
@@ -70,17 +70,19 @@ TextTrack::SetDefaultSettings()
   mCuePos = 0;
   mDirty = false;
   mReadyState = HTMLTrackElement::NONE;
 }
 
 void
 TextTrack::Update(double aTime)
 {
-  mCueList->Update(aTime);
+  if (mCueList) {
+    mCueList->Update(aTime);
+  }
 }
 
 JSObject*
 TextTrack::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return TextTrackBinding::Wrap(aCx, aScope, this);
 }
 
--- a/content/media/webaudio/AudioContext.h
+++ b/content/media/webaudio/AudioContext.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 AudioContext_h_
 #define AudioContext_h_
 
-#include "mozilla/dom/AudioContextBinding.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "EnableWebAudioCheck.h"
 #include "MediaBufferDecoder.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/TypedArray.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMEventTargetHelper.h"
--- a/content/media/webaudio/AudioDestinationNode.h
+++ b/content/media/webaudio/AudioDestinationNode.h
@@ -2,17 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 AudioDestinationNode_h_
 #define AudioDestinationNode_h_
 
-#include "mozilla/dom/AudioContextBinding.h"
+#include "mozilla/dom/AudioChannelBinding.h"
 #include "AudioNode.h"
 #include "nsIDOMEventListener.h"
 #include "nsIAudioChannelAgent.h"
 #include "AudioChannelCommon.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 namespace dom {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -8455,17 +8455,23 @@ if (""",
             ]
         methods = []
 
         if self.needToInitIds:
             methods.append(self.initIdsMethod())
 
         methods.append(self.initMethod())
         methods.append(self.initFromJSONMethod())
-        methods.append(self.toObjectMethod())
+        try:
+            methods.append(self.toObjectMethod())
+        except MethodNotCreatorError:
+            # If we can't have a ToObject() because one of our members can only
+            # be returned from [NewObject] methods, then just skip generating
+            # ToObject().
+            pass
         methods.append(self.traceDictionaryMethod())
 
         if CGDictionary.isDictionaryCopyConstructible(d):
             disallowCopyConstruction = False
             # Note: no base constructors because our operator= will
             # deal with that.
             ctors.append(ClassConstructor([Argument("const %s&" % selfName,
                                                     "aOther")],
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -245,17 +245,16 @@ ParserResults.pkl: $(globalgen_dependenc
 	  .changed-dependency-list
 	@$(TOUCH) $@
 
 GARBAGE += \
   webidlyacc.py \
   parser.out \
   $(wildcard *-example.h) \
   $(wildcard *-example.cpp) \
-  $(unified_binding_cpp_files) \
   .BindingGen \
   .all-webidl-file-list \
   .generated-events-webidl-files \
   .changed-dependency-list \
   $(binding_dependency_trackers) \
   $(NULL)
 
 # Make sure all binding header files are created during the export stage, so we
--- a/dom/bindings/TypedArray.h
+++ b/dom/bindings/TypedArray.h
@@ -28,17 +28,19 @@ protected:
 
   TypedArrayObjectStorage()
   {
   }
 
 public:
   inline void TraceSelf(JSTracer* trc)
   {
-    JS_CallObjectTracer(trc, &mObj, "TypedArray.mObj");
+    if (mObj) {
+      JS_CallObjectTracer(trc, &mObj, "TypedArray.mObj");
+    }
   }
 
 private:
   TypedArrayObjectStorage(const TypedArrayObjectStorage&) MOZ_DELETE;
 };
 
 /*
  * Various typed array classes for argument conversion.  We have a base class
--- a/dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl
+++ b/dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl
@@ -5,26 +5,26 @@
 #include "nsISupports.idl"
 
 interface nsIDOMMozCellBroadcastEtwsInfo;
 
 /**
  * MozCellBroadcastMessage encapsulates Cell Broadcast short message service
  * (CBS) messages.
  */
-[scriptable, uuid(cb210e8b-ad9c-4052-b70c-02ec0c25d669)]
+[scriptable, uuid(6abe65de-6729-41f7-906a-3f3a2dbe30ae)]
 interface nsIDOMMozCellBroadcastMessage : nsISupports
 {
   /**
    * Indication of the geographical area over which the Message Code is unique,
    * and the display mode.
    *
    * Possible values are: "cell-immediate", "plmn", "location-area" and "cell".
    */
-  readonly attribute DOMString geographicalScope;
+  readonly attribute DOMString gsmGeographicalScope;
 
   /**
    * The Message Code differentiates between messages from the same source and
    * type (e.g., with the same Message Identifier).
    */
   readonly attribute unsigned short messageCode;
 
   /**
@@ -54,16 +54,21 @@ interface nsIDOMMozCellBroadcastMessage 
    * System time stamp at receival.
    */
   readonly attribute jsval timestamp; // jsval is for Date.
 
   /**
    * Additional ETWS-specific info.
    */
   readonly attribute nsIDOMMozCellBroadcastEtwsInfo etws;
+
+  /**
+   * Service Category.
+   */
+  readonly attribute long cdmaServiceCategory;
 };
 
 /**
  * ETWS (Earthquake and Tsunami Warning service) Primary Notification message
  * specific information.
  */
 [scriptable, uuid(af009d9a-f5e8-4573-a6ee-a85118465bed)]
 interface nsIDOMMozCellBroadcastEtwsInfo : nsISupports
--- a/dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js
+++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_etws.js
@@ -97,30 +97,31 @@ function testEtwsMessageAttributes() {
     // ok(event instanceof MozCellBroadcastEvent,
     //    "event is instanceof " + event.constructor)
     ok(event, "event is valid");
 
     let message = event.message;
     ok(message, "event.message is valid");
 
     // Attributes other than `language` and `body` should always be assigned.
-    ok(message.geographicalScope != null, "message.geographicalScope");
+    ok(message.gsmGeographicalScope != null, "message.gsmGeographicalScope");
     ok(message.messageCode != null, "message.messageCode");
     ok(message.messageId != null, "message.messageId");
     ok('language' in message, "message.language");
     ok(message.language == null, "message.language");
     ok('body' in message, "message.body");
     ok(message.body == null, "message.body");
     is(message.messageClass, "normal", "message.messageClass");
     ok(message.timestamp != null, "message.timestamp");
     ok(message.etws != null, "message.etws");
     ok(message.etws.warningType != null, "message.etws.warningType");
     ok(message.etws.emergencyUserAlert != null,
        "message.etws.emergencyUserAlert");
     ok(message.etws.popup != null, "message.etws.popup");
+    ok(message.cdmaServiceCategory != null, "message.cdmaServiceCategory");
 
     window.setTimeout(testReceiving_ETWS_GeographicalScope, 0);
   });
 
   // Here we use a simple ETWS message for test.
   let pdu = buildHexStr(0, CB_MESSAGE_SIZE_ETWS * 2); // 6 octets
   sendCellBroadcastMessage(pdu);
 }
@@ -129,18 +130,18 @@ function testReceiving_ETWS_Geographical
   log("Test receiving ETWS Primary Notification - Geographical Scope");
 
   function do_test(gs, nextTest) {
     // Here we use a simple ETWS message for test.
     let pdu = buildHexStr(((gs & 0x03) << 14), 4)
             + buildHexStr(0, (CB_MESSAGE_SIZE_ETWS - 2) * 2);
 
     doTestHelper(pdu, nextTest, function (message) {
-      is(message.geographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs],
-         "message.geographicalScope");
+      is(message.gsmGeographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs],
+         "message.gsmGeographicalScope");
     });
   }
 
   repeat(do_test, seq(CB_GSM_GEOGRAPHICAL_SCOPE_NAMES.length),
          testReceiving_ETWS_MessageCode);
 }
 
 function testReceiving_ETWS_MessageCode() {
--- a/dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js
+++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_gsm.js
@@ -152,29 +152,30 @@ function testGsmMessageAttributes() {
     // ok(event instanceof MozCellBroadcastEvent,
     //    "event is instanceof " + event.constructor)
     ok(event, "event is valid");
 
     let message = event.message;
     ok(message, "event.message is valid");
 
     // Attributes other than `language` and `body` should always be assigned.
-    ok(message.geographicalScope != null, "message.geographicalScope");
+    ok(message.gsmGeographicalScope != null, "message.gsmGeographicalScope");
     ok(message.messageCode != null, "message.messageCode");
     ok(message.messageId != null, "message.messageId");
     ok(message.language != null, "message.language");
     ok(message.body != null, "message.body");
     ok(message.messageClass != null, "message.messageClass");
     ok(message.timestamp != null, "message.timestamp");
     ok('etws' in message, "message.etws");
     if (message.etws) {
       ok('warningType' in message.etws, "message.etws.warningType");
       ok(message.etws.emergencyUserAlert != null, "message.etws.emergencyUserAlert");
       ok(message.etws.popup != null, "message.etws.popup");
     }
+    ok(message.cdmaServiceCategory != null, "message.cdmaServiceCategory");
 
     window.setTimeout(testReceiving_GSM_GeographicalScope, 0);
   });
 
   // Here we use a simple GSM message for test.
   let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2);
   sendCellBroadcastMessage(pdu);
 }
@@ -182,18 +183,18 @@ function testGsmMessageAttributes() {
 function testReceiving_GSM_GeographicalScope() {
   log("Test receiving GSM Cell Broadcast - Geographical Scope");
 
   function do_test(gs, nextTest) {
     let pdu = buildHexStr(((gs & 0x03) << 14), 4)
             + buildHexStr(0, (CB_MESSAGE_SIZE_GSM - 2) * 2);
 
     doTestHelper(pdu, nextTest, function (message) {
-      is(message.geographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs],
-         "message.geographicalScope");
+      is(message.gsmGeographicalScope, CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[gs],
+         "message.gsmGeographicalScope");
     });
   }
 
   repeat(do_test, seq(CB_GSM_GEOGRAPHICAL_SCOPE_NAMES.length),
          testReceiving_GSM_MessageCode);
 }
 
 function testReceiving_GSM_MessageCode() {
@@ -435,17 +436,36 @@ function testReceiving_GSM_Multipart() {
     }
 
     doTestHelper(pdus, nextTest, function (message) {
       is(message.body.length, (numParts * CB_MAX_CONTENT_7BIT),
          "message.body");
     });
   }
 
-  repeat(do_test, seq(16, 1), cleanUp);
+  repeat(do_test, seq(16, 1), testReceiving_GSM_ServiceCategory);
+}
+
+function testReceiving_GSM_ServiceCategory() {
+  log("Test receiving GSM Cell Broadcast - Service Category");
+
+  cbs.addEventListener("received", function onreceived(event) {
+    cbs.removeEventListener("received", onreceived);
+
+    let message = event.message;
+
+    // Bug 910091
+    // "Service Category" is not defined in GSM.  We should always get '0' here.
+    is(message.cdmaServiceCategory, 0, "message.cdmaServiceCategory");
+
+    window.setTimeout(cleanUp, 0);
+  });
+
+  let pdu = buildHexStr(0, CB_MESSAGE_SIZE_GSM * 2);
+  sendCellBroadcastMessage(pdu);
 }
 
 function cleanUp() {
   if (pendingEmulatorCmdCount > 0) {
     window.setTimeout(cleanUp, 100);
     return;
   }
 
--- a/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
+++ b/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
@@ -12,17 +12,17 @@ namespace mozilla {
 namespace dom {
 class PositionOptions;
 }
 }
 %}
 
 [ptr] native NamespacedPositionOptions(mozilla::dom::PositionOptions);
 
-[builtinclass, uuid(1bc7d103-c7ae-4467-881c-21a8dfa17938)]
+[builtinclass, uuid(9142ab45-0ab5-418c-9bab-338a6d271d4f)]
 interface nsIDOMGeoGeolocation : nsISupports
 {
   int32_t watchPosition(in nsIDOMGeoPositionCallback callback,
                         in nsIDOMGeoPositionErrorCallback errorCallback,
                         in NamespacedPositionOptions options);
   void getCurrentPosition(in nsIDOMGeoPositionCallback callback,
                           in nsIDOMGeoPositionErrorCallback errorCallback,
                           in NamespacedPositionOptions options);
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -23,17 +23,17 @@
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
-#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX)
 #include "mozilla/Sandbox.h"
 #endif
 #include "mozilla/unused.h"
 
 #include "nsIConsoleListener.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMemoryInfoDumper.h"
@@ -548,17 +548,17 @@ ContentChild::AllocPImageBridgeChild(moz
 bool
 ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
 {
   ChildPrivileges privs = (aPrivs == PRIVILEGES_DEFAULT) ?
                           GeckoChildProcessHost::DefaultChildPrivileges() :
                           aPrivs;
   // If this fails, we die.
   SetCurrentProcessPrivileges(privs);
-#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_UNIX)
   // SetCurrentProcessSandbox should be moved close to process initialization
   // time if/when possible. SetCurrentProcessPrivileges should probably be
   // moved as well. Right now this is set ONLY if we receive the
   // RecvSetProcessPrivileges message. See bug 880808.
   SetCurrentProcessSandbox();
 #endif
   return true;
 }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -2790,28 +2790,28 @@ void nsPluginInstanceOwner::Paint(gfxCon
 
   Renderer renderer(window, this, pluginSize, pluginDirtyRect);
 
   Display* dpy = mozilla::DefaultXDisplay();
   Screen* screen = DefaultScreenOfDisplay(dpy);
   Visual* visual = DefaultVisualOfScreen(screen);
 
   renderer.Draw(aContext, nsIntSize(window->width, window->height),
-                rendererFlags, screen, visual, nullptr);
+                rendererFlags, screen, visual);
 }
 nsresult
-nsPluginInstanceOwner::Renderer::DrawWithXlib(gfxXlibSurface* xsurface, 
+nsPluginInstanceOwner::Renderer::DrawWithXlib(cairo_surface_t* xsurface,
                                               nsIntPoint offset,
                                               nsIntRect *clipRects, 
                                               uint32_t numClipRects)
 {
-  Screen *screen = cairo_xlib_surface_get_screen(xsurface->CairoSurface());
+  Screen *screen = cairo_xlib_surface_get_screen(xsurface);
   Colormap colormap;
   Visual* visual;
-  if (!xsurface->GetColormapAndVisual(&colormap, &visual)) {
+  if (!gfxXlibSurface::GetColormapAndVisual(xsurface, &colormap, &visual)) {
     NS_ERROR("Failed to get visual and colormap");
     return NS_ERROR_UNEXPECTED;
   }
 
   nsNPAPIPluginInstance *instance = mInstanceOwner->mInstance;
   if (!instance)
     return NS_ERROR_FAILURE;
 
@@ -2845,20 +2845,20 @@ nsPluginInstanceOwner::Renderer::DrawWit
   }
   else {
     clipRect.x = offset.x;
     clipRect.y = offset.y;
     clipRect.width  = mWindow->width;
     clipRect.height = mWindow->height;
     // Don't ask the plugin to draw outside the drawable.
     // This also ensures that the unsigned clip rectangle offsets won't be -ve.
-    gfxIntSize surfaceSize = xsurface->GetSize();
     clipRect.IntersectRect(clipRect,
                            nsIntRect(0, 0,
-                                     surfaceSize.width, surfaceSize.height));
+                                     cairo_xlib_surface_get_width(xsurface),
+                                     cairo_xlib_surface_get_height(xsurface)));
   }
 
   NPRect newClipRect;
   newClipRect.left = clipRect.x;
   newClipRect.top = clipRect.y;
   newClipRect.right = clipRect.XMost();
   newClipRect.bottom = clipRect.YMost();
   if (mWindow->clipRect.left    != newClipRect.left   ||
@@ -2901,17 +2901,17 @@ nsPluginInstanceOwner::Renderer::DrawWit
     return NS_OK;
 
   {
     XEvent pluginEvent = XEvent();
     XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose;
     // set the drawing info
     exposeEvent.type = GraphicsExpose;
     exposeEvent.display = DisplayOfScreen(screen);
-    exposeEvent.drawable = xsurface->XDrawable();
+    exposeEvent.drawable = cairo_xlib_surface_get_drawable(xsurface);
     exposeEvent.x = dirtyRect.x;
     exposeEvent.y = dirtyRect.y;
     exposeEvent.width  = dirtyRect.width;
     exposeEvent.height = dirtyRect.height;
     exposeEvent.count = 0;
     // information not set:
     exposeEvent.serial = 0;
     exposeEvent.send_event = False;
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -334,18 +334,19 @@ private:
 #endif
   {
   public:
     Renderer(NPWindow* aWindow, nsPluginInstanceOwner* aInstanceOwner,
              const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
     : mWindow(aWindow), mInstanceOwner(aInstanceOwner),
     mPluginSize(aPluginSize), mDirtyRect(aDirtyRect)
     {}
-    virtual nsresult DrawWithXlib(gfxXlibSurface* surface, nsIntPoint offset, 
-                                  nsIntRect* clipRects, uint32_t numClipRects);
+    virtual nsresult DrawWithXlib(cairo_surface_t* surface,
+                                  nsIntPoint offset,
+                                  nsIntRect* clipRects, uint32_t numClipRects) MOZ_OVERRIDE;
   private:
     NPWindow* mWindow;
     nsPluginInstanceOwner* mInstanceOwner;
     const nsIntSize& mPluginSize;
     const nsIntRect& mDirtyRect;
   };
 #endif
 
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -239,17 +239,19 @@ NetworkManager.prototype = {
             // Add extra host route. For example, mms proxy or mmsc.
             this.setExtraHostRoute(network);
             // Remove pre-created default route and let setAndConfigureActive()
             // to set default route only on preferred network
             this.removeDefaultRoute(network.name);
             this.setAndConfigureActive();
             // Update data connection when Wifi connected/disconnected
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
-              this.mRIL.getRadioInterface(0).updateRILNetworkInterface();
+              for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) {
+                this.mRIL.getRadioInterface(i).updateRILNetworkInterface();
+              }
             }
 
             this.onConnectionChanged(network);
 
             // Probing the public network accessibility after routing table is ready
             CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_CONNECT, this.active);
             break;
           case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
@@ -267,17 +269,19 @@ NetworkManager.prototype = {
             } else if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
               this.removeDefaultRoute(network.name);
             }
             // Abort ongoing captive portal detection on the wifi interface
             CaptivePortalDetectionHelper.notify(CaptivePortalDetectionHelper.EVENT_DISCONNECT, network);
             this.setAndConfigureActive();
             // Update data connection when Wifi connected/disconnected
             if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
-              this.mRIL.getRadioInterface(0).updateRILNetworkInterface();
+              for (let i = 0; i < this.mRIL.numRadioInterfaces; i++) {
+                this.mRIL.getRadioInterface(i).updateRILNetworkInterface();
+              }
             }
             break;
         }
         break;
       case TOPIC_INTERFACE_REGISTERED:
         let regNetwork = subject.QueryInterface(Ci.nsINetworkInterface);
         // Add extra host route. For example, mms proxy or mmsc.
         this.setExtraHostRoute(regNetwork);
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -313,49 +313,52 @@ MobileCFInfo.prototype = {
   action: -1,
   reason: -1,
   number: null,
   timeSeconds: 0,
   serviceClass: -1
 };
 
 function CellBroadcastMessage(pdu) {
-  this.geographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope];
+  this.gsmGeographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope];
   this.messageCode = pdu.messageCode;
   this.messageId = pdu.messageId;
   this.language = pdu.language;
   this.body = pdu.fullBody;
   this.messageClass = pdu.messageClass;
   this.timestamp = new Date(pdu.timestamp);
 
   if (pdu.etws != null) {
     this.etws = new CellBroadcastEtwsInfo(pdu.etws);
   }
+
+  this.cdmaServiceCategory = pdu.serviceCategory;
 }
 CellBroadcastMessage.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastMessage]),
   classID:        CELLBROADCASTMESSAGE_CID,
   classInfo:      XPCOMUtils.generateCI({
     classID:          CELLBROADCASTMESSAGE_CID,
     classDescription: "CellBroadcastMessage",
     flags:            Ci.nsIClassInfo.DOM_OBJECT,
     interfaces:       [Ci.nsIDOMMozCellBroadcastMessage]
   }),
 
   // nsIDOMMozCellBroadcastMessage
 
-  geographicalScope: null,
+  gsmGeographicalScope: null,
   messageCode: null,
   messageId: null,
   language: null,
   body: null,
   messageClass: null,
   timestamp: null,
 
-  etws: null
+  etws: null,
+  cdmaServiceCategory: null
 };
 
 function CellBroadcastEtwsInfo(etwsInfo) {
   if (etwsInfo.warningType != null) {
     this.warningType = RIL.CB_ETWS_WARNING_TYPE_NAMES[etwsInfo.warningType];
   }
   this.emergencyUserAlert = etwsInfo.emergencyUserAlert;
   this.popup = etwsInfo.popup;
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -1055,16 +1055,17 @@ RadioInterface.prototype = {
                                        this.clientId, message);
         break;
       case "sms-received":
         let ackOk = this.handleSmsReceived(message);
         if (ackOk) {
           this.workerMessenger.send("ackSMS", { result: RIL.PDU_FCS_OK });
         }
         return;
+      case "broadcastsms-received":
       case "cellbroadcast-received":
         message.timestamp = Date.now();
         gMessageManager.sendCellBroadcastMessage("RIL:CellBroadcastReceived",
                                                  this.clientId, message);
         break;
       case "datacallstatechange":
         this.handleDataCallState(message);
         break;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -2758,18 +2758,25 @@ this.PDU_CDMA_MSG_CODING_GSM_DCS = 0x0A;
 this.PDU_CDMA_MSG_TYPE_DELIVER = 0x01;        // Receive
 this.PDU_CDMA_MSG_TYPE_SUBMIT = 0x02;         // Send
 
 // SMS User Data Subparameters, as defined in 3GPP2 C.S0015-A v2.0, Table 4.5-1
 this.PDU_CDMA_MSG_USERDATA_MSG_ID = 0x00;           // Message Identifier
 this.PDU_CDMA_MSG_USERDATA_BODY = 0x01;             // User Data Body
 this.PDU_CDMA_MSG_USERDATA_TIMESTAMP = 0x03;        // Message Center Time Stamp
 this.PDU_CDMA_REPLY_OPTION = 0x0A;                  // Reply Option
+this.PDU_CDMA_LANGUAGE_INDICATOR = 0x0D;            // Language Indicator
 this.PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER = 0x0E;  // Callback Number
 
+// CDMA Language Indicator: Language groups
+// see 3GPP2 C.R1001-F table 9.2-1
+this.CB_CDMA_LANG_GROUP = [
+  null, "en", "fr", "es", "ja", "ko", "zh", "he"
+];
+
 // IS-91 Message Type, as defined in TIA/EIA/IS-91-A, Table 9
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_VOICEMAIL_STATUS = 0x82;
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS_FULL = 0x83;
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_CLI = 0x84;
 this.PDU_CDMA_MSG_CODING_IS_91_TYPE_SMS = 0x85;
 
 // CDMA roaming preference mode
 this.CDMA_ROAMING_PREFERENCE_HOME = 0;
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -4215,17 +4215,23 @@ let RIL = {
 
     if (message) {
       message.result = PDU_FCS_OK;
       if (message.messageClass == GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_2]) {
         // `MS shall ensure that the message has been to the SMS data field in
         // the (U)SIM before sending an ACK to the SC.`  ~ 3GPP 23.038 clause 4
         message.result = PDU_FCS_RESERVED;
       }
-      message.rilMessageType = "sms-received";
+
+      if (message.messageType == PDU_CDMA_MSG_TYPE_BROADCAST) {
+        message.rilMessageType = "broadcastsms-received";
+      } else {
+        message.rilMessageType = "sms-received";
+      }
+
       this.sendChromeMessage(message);
 
       // We will acknowledge receipt of the SMS after we try to store it
       // in the database.
       return MOZ_FCS_WAIT_FOR_EXPLICIT_ACK;
     }
 
     return PDU_FCS_OK;
@@ -8805,35 +8811,38 @@ let CdmaPDUHelper = {
       message.sender += String.fromCharCode(addrDigit);
     }
 
     // User Data
     this.decodeUserData(message);
 
     // Transform message to GSM msg
     let msg = {
-      SMSC:           "",
-      mti:            0,
-      udhi:           0,
-      sender:         message.sender,
-      recipient:      null,
-      pid:            PDU_PID_DEFAULT,
-      epid:           PDU_PID_DEFAULT,
-      dcs:            0,
-      mwi:            null, //message[PDU_CDMA_MSG_USERDATA_BODY].header ? message[PDU_CDMA_MSG_USERDATA_BODY].header.mwi : null,
-      replace:        false,
-      header:         message[PDU_CDMA_MSG_USERDATA_BODY].header,
-      body:           message[PDU_CDMA_MSG_USERDATA_BODY].body,
-      data:           null,
-      timestamp:      message[PDU_CDMA_MSG_USERDATA_TIMESTAMP],
-      status:         null,
-      scts:           null,
-      dt:             null,
-      encoding:       message[PDU_CDMA_MSG_USERDATA_BODY].encoding,
-      messageClass:   GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL]
+      SMSC:            "",
+      mti:             0,
+      udhi:            0,
+      sender:          message.sender,
+      recipient:       null,
+      pid:             PDU_PID_DEFAULT,
+      epid:            PDU_PID_DEFAULT,
+      dcs:             0,
+      mwi:             null, //message[PDU_CDMA_MSG_USERDATA_BODY].header ? message[PDU_CDMA_MSG_USERDATA_BODY].header.mwi : null,
+      replace:         false,
+      header:          message[PDU_CDMA_MSG_USERDATA_BODY].header,
+      body:            message[PDU_CDMA_MSG_USERDATA_BODY].body,
+      data:            null,
+      timestamp:       message[PDU_CDMA_MSG_USERDATA_TIMESTAMP],
+      language:        message[PDU_CDMA_LANGUAGE_INDICATOR],
+      status:          null,
+      scts:            null,
+      dt:              null,
+      encoding:        message[PDU_CDMA_MSG_USERDATA_BODY].encoding,
+      messageClass:    GECKO_SMS_MESSAGE_CLASSES[PDU_DCS_MSG_CLASS_NORMAL],
+      messageType:     message.messageType,
+      serviceCategory: message.service
     };
 
     return msg;
   },
 
 
   /**
    * Helper for processing received SMS parcel data.
@@ -8925,16 +8934,19 @@ let CdmaPDUHelper = {
           message[id] = this.decodeUserDataMsg(message[PDU_CDMA_MSG_USERDATA_MSG_ID].userHeader);
           break;
         case PDU_CDMA_MSG_USERDATA_TIMESTAMP:
           message[id] = this.decodeUserDataTimestamp();
           break;
         case PDU_CDMA_REPLY_OPTION:
           message[id] = this.decodeUserDataReplyAction();
           break;
+        case PDU_CDMA_LANGUAGE_INDICATOR:
+          message[id] = this.decodeLanguageIndicator();
+          break;
         case PDU_CDMA_MSG_USERDATA_CALLBACK_NUMBER:
           message[id] = this.decodeUserDataCallbackNumber();
           break;
       }
 
       userDataLength -= (length + 2);
       userDataBuffer = [];
     }
@@ -9306,16 +9318,27 @@ let CdmaPDUHelper = {
                    readAck: (replyAction & 0x2) ? true : false,
                    report: (replyAction & 0x1) ? true : false
                  };
 
     return result;
   },
 
   /**
+   * User data subparameter decoder : Language Indicator
+   *
+   * @see 3GGP2 C.S0015-B 2.0, 4.5.14 Language Indicator
+   */
+  decodeLanguageIndicator: function cdma_decodeLanguageIndicator() {
+    let language = BitBufferHelper.readBits(8);
+    let result = CB_CDMA_LANG_GROUP[language];
+    return result;
+  },
+
+  /**
    * User data subparameter decoder : Call-Back Number
    *
    * @see 3GGP2 C.S0015-B 2.0, 4.5.15 Call-Back Number
    */
   decodeUserDataCallbackNumber: function cdma_decodeUserDataCallbackNumber() {
     let digitMode = BitBufferHelper.readBits(1);
     if (digitMode) {
       let numberType = BitBufferHelper.readBits(3),
new file mode 100644
--- /dev/null
+++ b/dom/webidl/AppInfo.webidl
@@ -0,0 +1,12 @@
+/* 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/. */
+
+/**
+  * This dictionnary holds the parameters supporting the app:// protocol.
+  */
+dictionary AppInfo
+{
+  DOMString path = "";
+  boolean   isCoreApp = false;
+};
new file mode 100644
--- /dev/null
+++ b/dom/webidl/AudioChannel.webidl
@@ -0,0 +1,49 @@
+/* -*- Mode: IDL; 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/.
+ */
+
+// AudioChannels are used by:
+// * HTMLMediaElement
+// * AudioContext (WebAudio)
+// When used, it has to throw an exception if the app tries to change the audio
+// channel type without the permission (manifest file for B2G apps).
+// The supported values are:
+// * normal (default value)
+//   Automatically paused if "notification" or higher priority channel
+//   is played
+//   Use case: normal applications
+// * content
+//   Automatically paused if "notification" or higher priority channel
+//   is played. Also paused if another app starts using "content"
+//   channel. Using this channel never affects applications using
+//   the "normal" channel.
+//   Use case: video/audio players
+// * notification
+//   Automatically paused if "alarm" or higher priority channel is played.
+//   Use case: New email, incoming SMS
+// * alarm
+//   Automatically paused if "telephony" or higher priority channel is
+//   played.
+//   User case: Alarm clock, calendar alarms
+// * telephony
+//   Automatically paused if "ringer" or higher priority
+//   channel is played.
+//   Use case: dialer, voip
+// * ringer
+//   Automatically paused if "publicnotification" or higher priority
+//   channel is played.
+//   Use case: dialer, voip
+// * publicnotification
+//   Always plays in speaker, even when headphones are plugged in.
+//   Use case: Camera shutter sound.
+enum AudioChannel {
+  "normal",
+  "content",
+  "notification",
+  "alarm",
+  "telephony",
+  "ringer",
+  "publicnotification",
+};
--- a/dom/webidl/AudioContext.webidl
+++ b/dom/webidl/AudioContext.webidl
@@ -93,24 +93,14 @@ partial interface AudioContext {
 
     // Same as createScriptProcessor()
     [NewObject, Throws, Pref="media.webaudio.legacy.AudioContext"]
     ScriptProcessorNode createJavaScriptNode(optional unsigned long bufferSize = 0,
                                              optional unsigned long numberOfInputChannels = 2,
                                              optional unsigned long numberOfOutputChannels = 2);
 };
 
-enum AudioChannel {
-  "normal",
-  "content",
-  "notification",
-  "alarm",
-  "telephony",
-  "ringer",
-  "publicnotification",
-};
-
 // Mozilla extensions
 partial interface AudioContext {
-  // Read HTMLMediaElement.webidl for more information about this attribute.
+  // Read AudioChannel.webidl for more information about this attribute.
   [Pref="media.useAudioChannelService", SetterThrows]
   attribute AudioChannel mozAudioChannelType;
 };
--- a/dom/webidl/DummyBinding.webidl
+++ b/dom/webidl/DummyBinding.webidl
@@ -22,13 +22,14 @@ interface DummyInterface : EventTarget {
   void MmsParameters(optional MmsParameters arg);
   void MmsAttachment(optional MmsAttachment arg);
   void AsyncScrollEventDetail(optional AsyncScrollEventDetail arg);
   void OpenWindowEventDetail(optional OpenWindowEventDetail arg);
   void DOMWindowResizeEventDetail(optional DOMWindowResizeEventDetail arg);
   void WifiOptions(optional WifiCommandOptions arg1,
                    optional WifiResultOptions arg2);
   void AppNotificationServiceOptions(optional AppNotificationServiceOptions arg);
+  void AppInfo(optional AppInfo arg1);
 };
 
 interface DummyInterfaceWorkers {
   BlobPropertyBag blobBag();
 };
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -128,47 +128,17 @@ partial interface HTMLMediaElement {
   object? mozGetMetadata();
 
   // Mozilla extension: provides access to the fragment end time if
   // the media element has a fragment URI for the currentSrc, otherwise
   // it is equal to the media duration.
   readonly attribute double mozFragmentEnd;
 
   // Mozilla extension: an audio channel type for media elements.
-  // An exception is thrown if the app tries to change the audio channel type
-  // without the permission (manifest file for B2G apps).
-  // The supported values are:
-  // * normal (default value)
-  //   Automatically paused if "notification" or higher priority channel
-  //   is played
-  //   Use case: normal applications
-  // * content
-  //   Automatically paused if "notification" or higher priority channel
-  //   is played. Also paused if another app starts using "content"
-  //   channel. Using this channel never affects applications using
-  //   the "normal" channel.
-  //   Use case: video/audio players
-  // * notification
-  //   Automatically paused if "alarm" or higher priority channel is played.
-  //   Use case: New email, incoming SMS
-  // * alarm
-  //   Automatically paused if "telephony" or higher priority channel is
-  //   played.
-  //   User case: Alarm clock, calendar alarms
-  // * telephony
-  //   Automatically paused if "ringer" or higher priority
-  //   channel is played.
-  //   Use case: dialer, voip
-  // * ringer
-  //   Automatically paused if "publicnotification" or higher priority
-  //   channel is played.
-  //   Use case: dialer, voip
-  // * publicnotification
-  //   Always plays in speaker, even when headphones are plugged in.
-  //   Use case: Camera shutter sound.
+  // Read AudioChannel.webidl for more information about this attribute.
   [SetterThrows]
-  attribute DOMString mozAudioChannelType;
+  attribute AudioChannel mozAudioChannelType;
 
   // In addition the media element has this new events:
   // * onmozinterruptbegin - called when the media element is interrupted
   //   because of the audiochannel manager.
   // * onmozinterruptend - called when the interruption is concluded
 };
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -15,22 +15,24 @@ PREPROCESSED_WEBIDL_FILES = [
     'Navigator.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
     'AbstractWorker.webidl',
     'AnalyserNode.webidl',
     'AnimationEvent.webidl',
+    'AppInfo.webidl',
     'AppNotificationServiceOptions.webidl',
     'ArchiveReader.webidl',
     'ArchiveRequest.webidl',
     'Attr.webidl',
     'AudioBuffer.webidl',
     'AudioBufferSourceNode.webidl',
+    'AudioChannel.webidl',
     'AudioContext.webidl',
     'AudioDestinationNode.webidl',
     'AudioListener.webidl',
     'AudioNode.webidl',
     'AudioParam.webidl',
     'AudioProcessingEvent.webidl',
     'AudioStreamTrack.webidl',
     'BarProp.webidl',
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -932,16 +932,20 @@ public:
 
 class GFX2D_API Factory
 {
 public:
   static bool HasSSE2();
 
   static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize);
 
+  static TemporaryRef<SourceSurface>
+    CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
+                                       SurfaceFormat aFormat);
+
   static TemporaryRef<DrawTarget>
     CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
 
   static TemporaryRef<DrawTarget>
     CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT);
      
   static TemporaryRef<DrawTarget>
     CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -1056,16 +1056,30 @@ DrawTargetCairo::CreateSourceSurfaceFrom
         new SourceSurfaceCairo(surf, size, aSurface.mFormat);
       return source;
     }
   }
 
   return nullptr;
 }
 
+TemporaryRef<SourceSurface>
+DrawTargetCairo::CreateSourceSurfaceForCairoSurface(cairo_surface_t *aSurface,
+                                                    SurfaceFormat aFormat)
+{
+  IntSize size;
+  if (GetCairoSurfaceSize(aSurface, size)) {
+    RefPtr<SourceSurfaceCairo> source =
+      new SourceSurfaceCairo(aSurface, size, aFormat);
+    return source;
+  }
+
+  return nullptr;
+}
+
 TemporaryRef<DrawTarget>
 DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
 {
   cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext),
                                                           GfxFormatToCairoContent(aFormat),
                                                           aSize.width, aSize.height);
 
   if (!cairo_surface_status(similar)) {
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -152,16 +152,20 @@ public:
 
   // Call to set up aContext for drawing (with the current transform, etc).
   // Pass the path you're going to be using if you have one.
   // Implicitly calls WillChange(aPath).
   void PrepareForDrawing(cairo_t* aContext, const Path* aPath = nullptr);
 
   static cairo_surface_t *GetDummySurface();
 
+  static TemporaryRef<SourceSurface>
+      CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
+                                         SurfaceFormat aFormat);
+
 private: // methods
   // Init cairo surface without doing a cairo_surface_reference() call.
   bool InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize);
 
   enum DrawPatternType { DRAW_FILL, DRAW_STROKE };
   void DrawPattern(const Pattern& aPattern,
                    const StrokeOptions& aStrokeOptions,
                    const DrawOptions& aOptions,
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -549,16 +549,28 @@ Factory::CreateDrawTargetForCairoSurface
   if (mRecorder && retVal) {
     RefPtr<DrawTarget> recordDT = new DrawTargetRecording(mRecorder, retVal);
     return recordDT;
   }
 #endif
   return retVal;
 }
 
+TemporaryRef<SourceSurface>
+Factory::CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
+                                            SurfaceFormat aFormat)
+{
+  RefPtr<SourceSurface> retVal;
+
+#ifdef USE_CAIRO
+  retVal = DrawTargetCairo::CreateSourceSurfaceForCairoSurface(aSurface, aFormat);
+#endif
+  return retVal;
+}
+
 #ifdef XP_MACOSX
 TemporaryRef<DrawTarget>
 Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize)
 {
   RefPtr<DrawTarget> retVal;
 
   RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
 
--- a/gfx/layers/ipc/Axis.cpp
+++ b/gfx/layers/ipc/Axis.cpp
@@ -58,26 +58,26 @@ static float gAccelerationMultiplier = 1
  */
 static float gFlingStoppedThreshold = 0.01f;
 
 /**
  * Maximum size of velocity queue. The queue contains last N velocity records.
  * On touch end we calculate the average velocity in order to compensate
  * touch/mouse drivers misbehaviour.
  */
-static int gMaxVelocityQueueSize = 5;
+static uint32_t gMaxVelocityQueueSize = 5;
 
 static void ReadAxisPrefs()
 {
   Preferences::AddFloatVarCache(&gMaxEventAcceleration, "apz.max_event_acceleration", gMaxEventAcceleration);
   Preferences::AddFloatVarCache(&gFlingFriction, "apz.fling_friction", gFlingFriction);
   Preferences::AddFloatVarCache(&gVelocityThreshold, "apz.velocity_threshold", gVelocityThreshold);
   Preferences::AddFloatVarCache(&gAccelerationMultiplier, "apz.acceleration_multiplier", gAccelerationMultiplier);
   Preferences::AddFloatVarCache(&gFlingStoppedThreshold, "apz.fling_stopped_threshold", gFlingStoppedThreshold);
-  Preferences::AddIntVarCache(&gMaxVelocityQueueSize, "apz.max_velocity_queue_size", gMaxVelocityQueueSize);
+  Preferences::AddUintVarCache(&gMaxVelocityQueueSize, "apz.max_velocity_queue_size", gMaxVelocityQueueSize);
 }
 
 class ReadAxisPref MOZ_FINAL : public nsRunnable {
 public:
   NS_IMETHOD Run()
   {
     ReadAxisPrefs();
     return NS_OK;
--- a/gfx/thebes/gfxAlphaRecovery.cpp
+++ b/gfx/thebes/gfxAlphaRecovery.cpp
@@ -7,86 +7,47 @@
 
 #include "gfxImageSurface.h"
 
 #define MOZILLA_SSE_INCLUDE_HEADER_FOR_SSE2
 #include "mozilla/SSE.h"
 
 /* static */ bool
 gfxAlphaRecovery::RecoverAlpha(gfxImageSurface* blackSurf,
-                               const gfxImageSurface* whiteSurf,
-                               Analysis* analysis)
+                               const gfxImageSurface* whiteSurf)
 {
     gfxIntSize size = blackSurf->GetSize();
 
     if (size != whiteSurf->GetSize() ||
         (blackSurf->Format() != gfxImageFormatARGB32 &&
          blackSurf->Format() != gfxImageFormatRGB24) ||
         (whiteSurf->Format() != gfxImageFormatARGB32 &&
          whiteSurf->Format() != gfxImageFormatRGB24))
         return false;
 
 #ifdef MOZILLA_MAY_SUPPORT_SSE2
-    if (!analysis && mozilla::supports_sse2() &&
+    if (mozilla::supports_sse2() &&
         RecoverAlphaSSE2(blackSurf, whiteSurf)) {
         return true;
     }
 #endif
 
     blackSurf->Flush();
     whiteSurf->Flush();
 
     unsigned char* blackData = blackSurf->Data();
     unsigned char* whiteData = whiteSurf->Data();
 
-    /* Get the alpha value of 'first' */
-    uint32_t first;
-    if (size.width == 0 || size.height == 0) {
-        first = 0;
-    } else {
-        if (!blackData || !whiteData)
-            return false;
-
-        first = RecoverPixel(*reinterpret_cast<uint32_t*>(blackData),
-                             *reinterpret_cast<uint32_t*>(whiteData));
-    }
-
-    uint32_t deltas = 0;
     for (int32_t i = 0; i < size.height; ++i) {
         uint32_t* blackPixel = reinterpret_cast<uint32_t*>(blackData);
         const uint32_t* whitePixel = reinterpret_cast<uint32_t*>(whiteData);
         for (int32_t j = 0; j < size.width; ++j) {
             uint32_t recovered = RecoverPixel(blackPixel[j], whitePixel[j]);
             blackPixel[j] = recovered;
-            deltas |= (first ^ recovered);
         }
         blackData += blackSurf->Stride();
         whiteData += whiteSurf->Stride();
     }
 
     blackSurf->MarkDirty();
-    
-    if (analysis) {
-        analysis->uniformAlpha = (deltas >> 24) == 0;
-        analysis->uniformColor = false;
-        if (analysis->uniformAlpha) {
-            double d_first_alpha = first >> 24;
-            analysis->alpha = d_first_alpha/255.0;
-            /* we only set uniformColor when the alpha is already uniform.
-               it's only useful in that case ... and if the alpha was nonuniform
-               then computing whether the color is uniform would require unpremultiplying
-               every pixel */
-            analysis->uniformColor = deltas == 0;
-            if (analysis->uniformColor) {
-                if (d_first_alpha == 0.0) {
-                    /* can't unpremultiply, this is OK */
-                    analysis->r = analysis->g = analysis->b = 0.0;
-                } else {
-                    analysis->r = (first & 0xFF)/d_first_alpha;
-                    analysis->g = ((first >> 8) & 0xFF)/d_first_alpha;
-                    analysis->b = ((first >> 16) & 0xFF)/d_first_alpha;
-                }
-            }
-        }
-    }
 
     return true;
 }
--- a/gfx/thebes/gfxAlphaRecovery.h
+++ b/gfx/thebes/gfxAlphaRecovery.h
@@ -10,23 +10,16 @@
 #include "gfxTypes.h"
 #include "nsRect.h"
 
 struct nsIntRect;
 class gfxImageSurface;
 
 class gfxAlphaRecovery {
 public:
-    struct Analysis {
-        bool uniformColor;
-        bool uniformAlpha;
-        gfxFloat alpha;
-        gfxFloat r, g, b;
-    };
-
     /**
      * Some SIMD fast-paths only can be taken if the relative
      * byte-alignment of images' pointers and strides meets certain
      * criteria.  Aligning image pointers and strides by
      * |GoodAlignmentLog2()| below will ensure that fast-paths aren't
      * skipped because of misalignment.  Fast-paths may still be taken
      * even if GoodAlignmentLog2() is not met, in some conditions.
      */
@@ -34,18 +27,17 @@ public:
 
     /* Given two surfaces of equal size with the same rendering, one onto a
      * black background and the other onto white, recovers alpha values from
      * the difference and sets the alpha values on the black surface.
      * The surfaces must have format RGB24 or ARGB32.
      * Returns true on success.
      */
     static bool RecoverAlpha (gfxImageSurface *blackSurface,
-                                const gfxImageSurface *whiteSurface,
-                                Analysis *analysis = nullptr);
+                                const gfxImageSurface *whiteSurface);
 
 #ifdef MOZILLA_MAY_SUPPORT_SSE2
     /* This does the same as the previous function, but uses SSE2
      * optimizations. Usually this should not be called directly.  Be sure to
      * check mozilla::supports_sse2() before calling this function.
      */
     static bool RecoverAlphaSSE2 (gfxImageSurface *blackSurface,
                                     const gfxImageSurface *whiteSurface);
--- a/gfx/thebes/gfxGdkNativeRenderer.cpp
+++ b/gfx/thebes/gfxGdkNativeRenderer.cpp
@@ -9,28 +9,29 @@
 
 #ifdef MOZ_X11
 #include <gdk/gdkx.h>
 #include "cairo-xlib.h"
 #include "gfxXlibSurface.h"
 
 #if (MOZ_WIDGET_GTK == 2)
 nsresult
-gfxGdkNativeRenderer::DrawWithXlib(gfxXlibSurface* surface,
+gfxGdkNativeRenderer::DrawWithXlib(cairo_surface_t* surface,
                                    nsIntPoint offset,
                                    nsIntRect* clipRects, uint32_t numClipRects)
 {
     GdkDrawable *drawable = gfxPlatformGtk::GetGdkDrawable(surface);
     if (!drawable) {
-        gfxIntSize size = surface->GetSize();
-        int depth = cairo_xlib_surface_get_depth(surface->CairoSurface());
+        int depth = cairo_xlib_surface_get_depth(surface);
         GdkScreen* screen = gdk_colormap_get_screen(mColormap);
         drawable =
-            gdk_pixmap_foreign_new_for_screen(screen, surface->XDrawable(),
-                                              size.width, size.height, depth);
+            gdk_pixmap_foreign_new_for_screen(screen, cairo_xlib_surface_get_drawable(surface),
+                                              cairo_xlib_surface_get_width(surface),
+                                              cairo_xlib_surface_get_height(surface),
+                                              depth);
         if (!drawable)
             return NS_ERROR_FAILURE;
 
         gdk_drawable_set_colormap(drawable, mColormap);
         gfxPlatformGtk::SetGdkDrawable(surface, drawable);
         g_object_unref(drawable); // The drawable now belongs to |surface|.
     }
     
@@ -53,16 +54,16 @@ gfxGdkNativeRenderer::Draw(gfxContext* c
 {
     mColormap = colormap;
 
     Visual* visual =
         gdk_x11_visual_get_xvisual(gdk_colormap_get_visual(colormap));
     Screen* screen =
         gdk_x11_screen_get_xscreen(gdk_colormap_get_screen(colormap));
 
-    gfxXlibNativeRenderer::Draw(ctx, size, flags, screen, visual, nullptr);
+    gfxXlibNativeRenderer::Draw(ctx, size, flags, screen, visual);
 }
 
 #else
 // TODO GTK3
 #endif
 
 #endif
--- a/gfx/thebes/gfxGdkNativeRenderer.h
+++ b/gfx/thebes/gfxGdkNativeRenderer.h
@@ -71,19 +71,19 @@ public:
 #if (MOZ_WIDGET_GTK == 2)
     void Draw(gfxContext* ctx, nsIntSize size,
               uint32_t flags, GdkColormap* colormap);
 #endif
 
 private:
 #ifdef MOZ_X11
     // for gfxXlibNativeRenderer:
-    virtual nsresult DrawWithXlib(gfxXlibSurface* surface,
+    virtual nsresult DrawWithXlib(cairo_surface_t* surface,
                                   nsIntPoint offset,
-                                  nsIntRect* clipRects, uint32_t numClipRects);
+                                  nsIntRect* clipRects, uint32_t numClipRects) MOZ_OVERRIDE;
 
 #if (MOZ_WIDGET_GTK == 2)
     GdkColormap *mColormap;
 #endif
 #endif
 };
 
 #endif /*GFXGDKNATIVERENDER_H_*/
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -859,17 +859,19 @@ gfxPlatform::InitializeSkiaCaches()
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
   if (aTarget->GetType() == BACKEND_CAIRO) {
     cairo_surface_t* csurf =
       static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
-    return gfxASurface::Wrap(csurf);
+    if (csurf) {
+      return gfxASurface::Wrap(csurf);
+    }
   }
 
   // The semantics of this part of the function are sort of weird. If we
   // don't have direct support for the backend, we snapshot the first time
   // and then return the snapshotted surface for the lifetime of the draw
   // target. Sometimes it seems like this works out, but it seems like it
   // might result in no updates ever.
   RefPtr<SourceSurface> source = aTarget->Snapshot();
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -717,51 +717,49 @@ void
 gfxPlatformGtk::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList)
 {
     gPrefFonts->Put(aKey, aFontEntryList);
 }
 #endif
 
 #if (MOZ_WIDGET_GTK == 2)
 void
-gfxPlatformGtk::SetGdkDrawable(gfxASurface *target,
+gfxPlatformGtk::SetGdkDrawable(cairo_surface_t *target,
                                GdkDrawable *drawable)
 {
-    if (target->CairoStatus())
+    if (cairo_surface_status(target))
         return;
 
     g_object_ref(drawable);
 
-    cairo_surface_set_user_data (target->CairoSurface(),
+    cairo_surface_set_user_data (target,
                                  &cairo_gdk_drawable_key,
                                  drawable,
                                  g_object_unref);
 }
 
 GdkDrawable *
-gfxPlatformGtk::GetGdkDrawable(gfxASurface *target)
+gfxPlatformGtk::GetGdkDrawable(cairo_surface_t *target)
 {
-    if (target->CairoStatus())
+    if (cairo_surface_status(target))
         return nullptr;
 
     GdkDrawable *result;
 
-    result = (GdkDrawable*) cairo_surface_get_user_data (target->CairoSurface(),
+    result = (GdkDrawable*) cairo_surface_get_user_data (target,
                                                          &cairo_gdk_drawable_key);
     if (result)
         return result;
 
 #ifdef MOZ_X11
-    if (target->GetType() != gfxSurfaceTypeXlib)
+    if (cairo_surface_get_type(target) != CAIRO_SURFACE_TYPE_XLIB)
         return nullptr;
 
-    gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(target);
-
     // try looking it up in gdk's table
-    result = (GdkDrawable*) gdk_xid_table_lookup(xs->XDrawable());
+    result = (GdkDrawable*) gdk_xid_table_lookup(cairo_xlib_surface_get_drawable(target));
     if (result) {
         SetGdkDrawable(target, result);
         return result;
     }
 #endif
 
     return nullptr;
 }
--- a/gfx/thebes/gfxPlatformGtk.h
+++ b/gfx/thebes/gfxPlatformGtk.h
@@ -86,19 +86,19 @@ public:
     void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList);
 #endif
 
 #ifndef MOZ_PANGO
     FT_Library GetFTLibrary();
 #endif
 
 #if (MOZ_WIDGET_GTK == 2)
-    static void SetGdkDrawable(gfxASurface *target,
+    static void SetGdkDrawable(cairo_surface_t *target,
                                GdkDrawable *drawable);
-    static GdkDrawable *GetGdkDrawable(gfxASurface *target);
+    static GdkDrawable *GetGdkDrawable(cairo_surface_t *target);
 #endif
 
     static int32_t GetDPI();
 
     bool UseXRender() {
 #if defined(MOZ_X11)
         if (GetContentBackend() != mozilla::gfx::BACKEND_NONE &&
             GetContentBackend() != mozilla::gfx::BACKEND_CAIRO)
--- a/gfx/thebes/gfxQtNativeRenderer.cpp
+++ b/gfx/thebes/gfxQtNativeRenderer.cpp
@@ -4,18 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gfxQtNativeRenderer.h"
 #include "gfxContext.h"
 #include "gfxXlibSurface.h"
 
 nsresult
 gfxQtNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
-                          uint32_t flags, Screen* screen, Visual* visual,
-                          DrawOutput* output)
+                          uint32_t flags, Screen* screen, Visual* visual)
 {
     Display *dpy = DisplayOfScreen(screen);
     bool isOpaque = (flags & DRAW_IS_OPAQUE) ? true : false;
     int screenNumber = screen - ScreenOfDisplay(dpy, 0);
 
     if (!isOpaque) {
         int depth = 32;
         XVisualInfo vinfo;
--- a/gfx/thebes/gfxQtNativeRenderer.h
+++ b/gfx/thebes/gfxQtNativeRenderer.h
@@ -49,31 +49,23 @@ public:
         // visual passed in must be the default visual for dpy's default screen
         DRAW_SUPPORTS_ALTERNATE_VISUAL = 0x10,
         // If set, then the Screen 'screen' in the callback can be different
         // from the default Screen of the display passed to 'Draw' and can be
         // on a different display.
         DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20
     };
 
-    struct DrawOutput {
-        nsRefPtr<gfxASurface> mSurface;
-        bool mUniformAlpha;
-        bool mUniformColor;
-        gfxRGBA      mColor;
-    };
-
     /**
      * @param flags see above
      * @param size Draw()'s drawing is guaranteed to be restricted to
      * the rectangle (offset.x,offset.y,size.width,size.height)
      * @param dpy a display to use for the drawing if ctx doesn't have one
      * @param resultSurface if non-null, we will try to capture a copy of the
      * rendered image into a surface similar to the surface of ctx; if
      * successful, a pointer to the new gfxASurface is stored in *resultSurface,
      * otherwise *resultSurface is set to nullptr.
      */
     nsresult Draw(gfxContext* ctx, nsIntSize size,
-                  uint32_t flags, Screen* screen, Visual* visual,
-                  DrawOutput* output);
+                  uint32_t flags, Screen* screen, Visual* visual);
 };
 
 #endif /*GFXQTNATIVERENDER_H_*/
--- a/gfx/thebes/gfxXlibNativeRenderer.cpp
+++ b/gfx/thebes/gfxXlibNativeRenderer.cpp
@@ -8,16 +8,17 @@
 #include "gfxXlibSurface.h"
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxAlphaRecovery.h"
 #include "cairo-xlib.h"
 #include "cairo-xlib-xrender.h"
 #include "mozilla/gfx/BorrowedContext.h"
+#include "gfx2DGlue.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 #if 0
 #include <stdio.h>
 #define NATIVE_DRAWING_NOTE(m) fprintf(stderr, m)
 #else
@@ -250,18 +251,17 @@ gfxXlibNativeRenderer::DrawCairo(cairo_t
             NATIVE_DRAWING_NOTE("FALLBACK: unsupported Visual");
             return false;
         }
     }
 
     /* we're good to go! */
     NATIVE_DRAWING_NOTE("TAKING FAST PATH\n");
     cairo_surface_flush (target);
-    nsRefPtr<gfxASurface> surface = gfxASurface::Wrap(target);
-    nsresult rv = DrawWithXlib(static_cast<gfxXlibSurface*>(surface.get()),
+    nsresult rv = DrawWithXlib(target,
                                offset, rectangles,
                                needs_clip ? rect_count : 0);
     if (NS_SUCCEEDED(rv)) {
         cairo_surface_mark_dirty (target);
         return true;
     }
     return false;
 }
@@ -304,74 +304,72 @@ FormatConversionIsExact(Screen *screen, 
 // The 3 non-direct strategies described above.
 // The surface format and strategy are inter-dependent.
 enum DrawingMethod {
     eSimple,
     eCopyBackground,
     eAlphaExtraction
 };
 
-static already_AddRefed<gfxXlibSurface>
-CreateTempXlibSurface (gfxASurface *destination, nsIntSize size,
+static cairo_surface_t*
+CreateTempXlibSurface (cairo_surface_t* cairoTarget,
+                       DrawTarget* drawTarget,
+                       nsIntSize size,
                        bool canDrawOverBackground,
                        uint32_t flags, Screen *screen, Visual *visual,
                        DrawingMethod *method)
 {
+    NS_ASSERTION(cairoTarget || drawTarget, "Must have some type");
+
     bool drawIsOpaque = (flags & gfxXlibNativeRenderer::DRAW_IS_OPAQUE) != 0;
     bool supportsAlternateVisual =
         (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_VISUAL) != 0;
     bool supportsAlternateScreen = supportsAlternateVisual &&
         (flags & gfxXlibNativeRenderer::DRAW_SUPPORTS_ALTERNATE_SCREEN);
 
-    cairo_surface_t *target = destination->CairoSurface();
-    cairo_surface_type_t target_type = cairo_surface_get_type (target);
-    cairo_content_t target_content = cairo_surface_get_content (target);
+    cairo_surface_type_t cairoTargetType =
+        cairoTarget ? cairo_surface_get_type (cairoTarget) : (cairo_surface_type_t)0xFF;
 
-    Screen *target_screen = target_type == CAIRO_SURFACE_TYPE_XLIB ?
-        cairo_xlib_surface_get_screen (target) : screen;
+    Screen *target_screen = cairoTargetType == CAIRO_SURFACE_TYPE_XLIB ?
+        cairo_xlib_surface_get_screen (cairoTarget) : screen;
 
     // When the background has an alpha channel, we need to draw with an alpha
     // channel anyway, so there is no need to copy the background.  If
     // doCopyBackground is set here, we'll also need to check below that the
     // background can copied without any loss in format conversions.
     bool doCopyBackground = !drawIsOpaque && canDrawOverBackground &&
-        target_content == CAIRO_CONTENT_COLOR;
+        cairoTarget && cairo_surface_get_content (cairoTarget) == CAIRO_CONTENT_COLOR;
 
     if (supportsAlternateScreen && screen != target_screen && drawIsOpaque) {
         // Prefer a visual on the target screen.
         // (If !drawIsOpaque, we'll need doCopyBackground or an alpha channel.)
         visual = DefaultVisualOfScreen(target_screen);
         screen = target_screen;
 
     } else if (doCopyBackground || (supportsAlternateVisual && drawIsOpaque)) {
         // Analyse the pixel formats either to check whether we can
         // doCopyBackground or to see if we can find a better visual for
         // opaque drawing.
         Visual *target_visual = nullptr;
         XRenderPictFormat *target_format = nullptr;
-        switch (target_type) {
-        case CAIRO_SURFACE_TYPE_XLIB:
-            target_visual = cairo_xlib_surface_get_visual (target);
-            target_format = cairo_xlib_surface_get_xrender_format (target);
-            break;
-        case CAIRO_SURFACE_TYPE_IMAGE: {
+        if (cairoTargetType == CAIRO_SURFACE_TYPE_XLIB) {
+            target_visual = cairo_xlib_surface_get_visual (cairoTarget);
+            target_format = cairo_xlib_surface_get_xrender_format (cairoTarget);
+        } else if (cairoTargetType == CAIRO_SURFACE_TYPE_IMAGE || drawTarget) {
             gfxImageFormat imageFormat =
-                static_cast<gfxImageSurface*>(destination)->Format();
+                drawTarget ? SurfaceFormatToImageFormat(drawTarget->GetFormat()) :
+                    (gfxImageFormat)cairo_image_surface_get_format(cairoTarget);
             target_visual = gfxXlibSurface::FindVisual(screen, imageFormat);
             Display *dpy = DisplayOfScreen(screen);
             if (target_visual) {
                 target_format = XRenderFindVisualFormat(dpy, target_visual);
             } else {
                 target_format =
                     gfxXlibSurface::FindRenderFormat(dpy, imageFormat);
             }                
-            break;
-        }
-        default:
-            break;
         }
 
         if (supportsAlternateVisual &&
             (supportsAlternateScreen || screen == target_screen)) {
             if (target_visual) {
                 visual = target_visual;
                 screen = target_screen;
             }
@@ -408,78 +406,75 @@ CreateTempXlibSurface (gfxASurface *dest
                                            gfxImageFormatRGB24);
             if (rgb24Visual) {
                 visual = rgb24Visual;
             }
         }
     }
 
     Drawable drawable =
-        (screen == target_screen && target_type == CAIRO_SURFACE_TYPE_XLIB) ?
-        cairo_xlib_surface_get_drawable (target) : RootWindowOfScreen(screen);
+        (screen == target_screen && cairoTargetType == CAIRO_SURFACE_TYPE_XLIB) ?
+        cairo_xlib_surface_get_drawable (cairoTarget) : RootWindowOfScreen(screen);
 
-    nsRefPtr<gfxXlibSurface> surface =
-        gfxXlibSurface::Create(screen, visual,
-                               gfxIntSize(size.width, size.height),
-                               drawable);
+    cairo_surface_t *surface =
+        gfxXlibSurface::CreateCairoSurface(screen, visual,
+                                           gfxIntSize(size.width, size.height),
+                                           drawable);
+    if (!surface) {
+        return nullptr;
+    }
 
     if (drawIsOpaque ||
-        surface->GetContentType() == GFX_CONTENT_COLOR_ALPHA) {
+        cairo_surface_get_content(surface) == CAIRO_CONTENT_COLOR_ALPHA) {
         NATIVE_DRAWING_NOTE(drawIsOpaque ?
                             ", SIMPLE OPAQUE\n" : ", SIMPLE WITH ALPHA");
         *method = eSimple;
     } else if (doCopyBackground) {
         NATIVE_DRAWING_NOTE(", COPY BACKGROUND\n");
         *method = eCopyBackground;
     } else {
         NATIVE_DRAWING_NOTE(", SLOW ALPHA EXTRACTION\n");
         *method = eAlphaExtraction;
     }
 
-    return surface.forget();
+    return surface;
 }
 
 bool
-gfxXlibNativeRenderer::DrawOntoTempSurface(gfxXlibSurface *tempXlibSurface,
+gfxXlibNativeRenderer::DrawOntoTempSurface(cairo_surface_t *tempXlibSurface,
                                            nsIntPoint offset)
 {
-    tempXlibSurface->Flush();
+    cairo_surface_flush(tempXlibSurface);
     /* no clipping is needed because the callback can't draw outside the native
        surface anyway */
     nsresult rv = DrawWithXlib(tempXlibSurface, offset, nullptr, 0);
-    tempXlibSurface->MarkDirty();
+    cairo_surface_mark_dirty(tempXlibSurface);
     return NS_SUCCEEDED(rv);
 }
 
 static already_AddRefed<gfxImageSurface>
-CopyXlibSurfaceToImage(gfxXlibSurface *tempXlibSurface,
+CopyXlibSurfaceToImage(cairo_surface_t *tempXlibSurface,
+                       gfxIntSize size,
                        gfxImageFormat format)
 {
-    nsRefPtr<gfxImageSurface> result =
-        new gfxImageSurface(tempXlibSurface->GetSize(), format);
+    nsRefPtr<gfxImageSurface> result = new gfxImageSurface(size, format);
 
-    gfxContext copyCtx(result);
-    copyCtx.SetSource(tempXlibSurface);
-    copyCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
-    copyCtx.Paint();
+    cairo_t* copyCtx = cairo_create(result->CairoSurface());
+    cairo_set_source_surface(copyCtx, tempXlibSurface, 0, 0);
+    cairo_set_operator(copyCtx, CAIRO_OPERATOR_SOURCE);
+    cairo_paint(copyCtx);
+    cairo_destroy(copyCtx);
 
     return result.forget();
 }
 
 void
 gfxXlibNativeRenderer::Draw(gfxContext* ctx, nsIntSize size,
-                            uint32_t flags, Screen *screen, Visual *visual,
-                            DrawOutput* result)
+                            uint32_t flags, Screen *screen, Visual *visual)
 {
-    if (result) {
-        result->mSurface = nullptr;
-        result->mUniformAlpha = false;
-        result->mUniformColor = false;
-    }
-
     gfxMatrix matrix = ctx->CurrentMatrix();
 
     // We can only draw direct or onto a copied background if pixels align and
     // native drawing is compatible with the current operator.  (The matrix is
     // actually also pixel-exact for flips and right-angle rotations, which
     // would permit copying the background but not drawing direct.)
     bool matrixIsIntegerTranslation = !matrix.HasNonIntegerTranslation();
     bool canDrawOverBackground = matrixIsIntegerTranslation &&
@@ -526,154 +521,115 @@ gfxXlibNativeRenderer::Draw(gfxContext* 
     clipExtents.RoundOut();
 
     nsIntRect intExtents(int32_t(clipExtents.X()),
                          int32_t(clipExtents.Y()),
                          int32_t(clipExtents.Width()),
                          int32_t(clipExtents.Height()));
     drawingRect.IntersectRect(drawingRect, intExtents);
 
-    if (ctx->IsCairo()) {
-        nsRefPtr<gfxASurface> target(ctx->CurrentSurface());
-        DrawFallback(nullptr, ctx, target, size, drawingRect, canDrawOverBackground,
-                     flags, screen, visual, result);
-    } else {
-        DrawTarget* drawTarget = ctx->GetDrawTarget();
-        if (!drawTarget) {
-            return;
-        }
-
-        nsRefPtr<gfxASurface> target = gfxPlatform::GetPlatform()->
-            GetThebesSurfaceForDrawTarget(drawTarget);
-        if (!target) {
-            return;
-        }
-        DrawFallback(drawTarget, ctx, target, size, drawingRect, canDrawOverBackground,
-                     flags, screen, visual, result);
-    }
-}
-
-void
-gfxXlibNativeRenderer::DrawFallback(DrawTarget* drawTarget, gfxContext* ctx, gfxASurface* target,
-                                    nsIntSize& size, nsIntRect& drawingRect,
-                                    bool canDrawOverBackground, uint32_t flags,
-                                    Screen* screen, Visual* visual, DrawOutput* result)
-{
     gfxPoint offset(drawingRect.x, drawingRect.y);
 
     DrawingMethod method;
-    nsRefPtr<gfxXlibSurface> tempXlibSurface = 
-        CreateTempXlibSurface(target, drawingRect.Size(),
+    cairo_surface_t* cairoTarget = nullptr;
+    DrawTarget* drawTarget = nullptr;
+    if (ctx->IsCairo()) {
+        cairoTarget = cairo_get_group_target(ctx->GetCairo());
+    } else {
+        drawTarget = ctx->GetDrawTarget();
+        cairoTarget = static_cast<cairo_surface_t*>
+            (drawTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
+    }
+
+    cairo_surface_t* tempXlibSurface =
+        CreateTempXlibSurface(cairoTarget, drawTarget, size,
                               canDrawOverBackground, flags, screen, visual,
                               &method);
     if (!tempXlibSurface)
         return;
 
-    if (drawingRect.Size() != size || method == eCopyBackground) {
-        // Only drawing a portion, or copying background,
-        // so won't return a result.
-        result = nullptr;
-    }
-  
-    nsRefPtr<gfxContext> tmpCtx;
     bool drawIsOpaque = (flags & DRAW_IS_OPAQUE) != 0;
     if (!drawIsOpaque) {
-        tmpCtx = new gfxContext(tempXlibSurface);
+        cairo_t* tmpCtx = cairo_create(tempXlibSurface);
         if (method == eCopyBackground) {
-            tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
-            tmpCtx->SetSource(target, -(offset + ctx->CurrentMatrix().GetTranslation()));
+            NS_ASSERTION(cairoTarget, "eCopyBackground only used when there's a cairoTarget");
+            cairo_set_operator(tmpCtx, CAIRO_OPERATOR_SOURCE);
+            gfxPoint pt = -(offset + ctx->CurrentMatrix().GetTranslation());
+            cairo_set_source_surface(tmpCtx, cairoTarget, pt.x, pt.y);
             // The copy from the tempXlibSurface to the target context should
             // use operator SOURCE, but that would need a mask to bound the
             // operation.  Here we only copy opaque backgrounds so operator
             // OVER will behave like SOURCE masked by the surface.
-            NS_ASSERTION(tempXlibSurface->GetContentType()
-                         == GFX_CONTENT_COLOR,
+            NS_ASSERTION(cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR,
                          "Don't copy background with a transparent surface");
         } else {
-            tmpCtx->SetOperator(gfxContext::OPERATOR_CLEAR);
+            cairo_set_operator(tmpCtx, CAIRO_OPERATOR_CLEAR);
         }
-        tmpCtx->Paint();
+        cairo_paint(tmpCtx);
+        cairo_destroy(tmpCtx);
     }
 
     if (!DrawOntoTempSurface(tempXlibSurface, -drawingRect.TopLeft())) {
+        cairo_surface_destroy(tempXlibSurface);
         return;
     }
   
+    SurfaceFormat moz2DFormat =
+        cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR ?
+            FORMAT_B8G8R8A8 : FORMAT_B8G8R8X8;
     if (method != eAlphaExtraction) {
         if (drawTarget) {
-            RefPtr<SourceSurface> sourceSurface = gfxPlatform::GetPlatform()->
-                GetSourceSurfaceForSurface(drawTarget, tempXlibSurface);
-            drawTarget->DrawSurface(sourceSurface,
-                Rect(offset.x, offset.y, size.width, size.height),
-                Rect(0, 0, size.width, size.height));
+            // It doesn't matter if moz2DFormat doesn't exactly match the format
+            // of tempXlibSurface, since this DrawTarget just wraps the cairo
+            // drawing.
+            RefPtr<SourceSurface> sourceSurface =
+                Factory::CreateSourceSurfaceForCairoSurface(tempXlibSurface,
+                                                            moz2DFormat);
+            if (sourceSurface) {
+                drawTarget->DrawSurface(sourceSurface,
+                    Rect(offset.x, offset.y, size.width, size.height),
+                    Rect(0, 0, size.width, size.height));
+            }
         } else {
-            ctx->SetSource(tempXlibSurface, offset);
+            nsRefPtr<gfxASurface> tmpSurf = gfxASurface::Wrap(tempXlibSurface);
+            ctx->SetSource(tmpSurf, offset);
             ctx->Paint();
         }
-        if (result) {
-            result->mSurface = tempXlibSurface;
-            /* fill in the result with what we know, which is really just what our
-               assumption was */
-            result->mUniformAlpha = true;
-            result->mColor.a = 1.0;
-        }
+        cairo_surface_destroy(tempXlibSurface);
         return;
     }
     
     nsRefPtr<gfxImageSurface> blackImage =
-        CopyXlibSurfaceToImage(tempXlibSurface, gfxImageFormatARGB32);
+        CopyXlibSurfaceToImage(tempXlibSurface, size, gfxImageFormatARGB32);
     
-    tmpCtx->SetDeviceColor(gfxRGBA(1.0, 1.0, 1.0));
-    tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
-    tmpCtx->Paint();
+    cairo_t* tmpCtx = cairo_create(tempXlibSurface);
+    cairo_set_source_rgba(tmpCtx, 1.0, 1.0, 1.0, 1.0);
+    cairo_set_operator(tmpCtx, CAIRO_OPERATOR_SOURCE);
+    cairo_paint(tmpCtx);
+    cairo_destroy(tmpCtx);
     DrawOntoTempSurface(tempXlibSurface, -drawingRect.TopLeft());
     nsRefPtr<gfxImageSurface> whiteImage =
-        CopyXlibSurfaceToImage(tempXlibSurface, gfxImageFormatRGB24);
+        CopyXlibSurfaceToImage(tempXlibSurface, size, gfxImageFormatRGB24);
   
     if (blackImage->CairoStatus() == CAIRO_STATUS_SUCCESS &&
         whiteImage->CairoStatus() == CAIRO_STATUS_SUCCESS) {
-        gfxAlphaRecovery::Analysis analysis;
-        if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage,
-                                            result ? &analysis : nullptr))
+        if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
+            cairo_surface_destroy(tempXlibSurface);
             return;
+        }
 
         gfxASurface* paintSurface = blackImage;
-        /* if the caller wants to retrieve the rendered image, put it into
-           a 'similar' surface, and use that as the source for the drawing right
-           now. This means we always return a surface similar to the surface
-           used for 'cr', which is ideal if it's going to be cached and reused.
-           We do not return an image if the result has uniform color (including
-           alpha). */
-        if (result) {
-            if (analysis.uniformAlpha) {
-                result->mUniformAlpha = true;
-                result->mColor.a = analysis.alpha;
+        if (drawTarget) {
+            RefPtr<SourceSurface> sourceSurface =
+                Factory::CreateSourceSurfaceForCairoSurface(paintSurface->CairoSurface(),
+                                                            moz2DFormat);
+            if (sourceSurface) {
+                drawTarget->DrawSurface(sourceSurface,
+                    Rect(offset.x, offset.y, size.width, size.height),
+                    Rect(0, 0, size.width, size.height));
             }
-            if (analysis.uniformColor) {
-                result->mUniformColor = true;
-                result->mColor.r = analysis.r;
-                result->mColor.g = analysis.g;
-                result->mColor.b = analysis.b;
-            } else {
-                result->mSurface = target->
-                    CreateSimilarSurface(GFX_CONTENT_COLOR_ALPHA,
-                                         gfxIntSize(size.width, size.height));
-
-                gfxContext copyCtx(result->mSurface);
-                copyCtx.SetSource(blackImage);
-                copyCtx.SetOperator(gfxContext::OPERATOR_SOURCE);
-                copyCtx.Paint();
-
-                paintSurface = result->mSurface;
-            }
-        }
-        if (drawTarget) {
-            RefPtr<SourceSurface> sourceSurface = gfxPlatform::GetPlatform()->
-                GetSourceSurfaceForSurface(drawTarget, paintSurface);
-            drawTarget->DrawSurface(sourceSurface,
-                Rect(offset.x, offset.y, size.width, size.height),
-                Rect(0, 0, size.width, size.height));
         } else {
             ctx->SetSource(paintSurface, offset);
             ctx->Paint();
         }
     }
+    cairo_surface_destroy(tempXlibSurface);
 }
--- a/gfx/thebes/gfxXlibNativeRenderer.h
+++ b/gfx/thebes/gfxXlibNativeRenderer.h
@@ -1,57 +1,56 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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 GFXXLIBNATIVERENDER_H_
 #define GFXXLIBNATIVERENDER_H_
 
-#include "gfxColor.h"
-#include "nsAutoPtr.h"
+#include "nsPoint.h"
+#include "nsRect.h"
 #include <X11/Xlib.h>
 
 namespace mozilla {
 namespace gfx {
   class DrawTarget;
 }
 }
 
 class gfxASurface;
-class gfxXlibSurface;
 class gfxContext;
 struct nsIntRect;
 struct nsIntPoint;
 struct nsIntSize;
 typedef struct _cairo cairo_t;
+typedef struct _cairo_surface cairo_surface_t;
 
 /**
  * This class lets us take code that draws into an X drawable and lets us
  * use it to draw into any Thebes context. The user should subclass this class,
  * override DrawWithXib, and then call Draw(). The drawing will be subjected
  * to all Thebes transformations, clipping etc.
  */
 class gfxXlibNativeRenderer {
 public:
     /**
      * Perform the native drawing.
-     * @param surface the drawable for drawing.
+     * @param surface the cairo_surface_t for drawing. Must be a cairo_xlib_surface_t.
      *                The extents of this surface do not necessarily cover the
      *                entire rectangle with size provided to Draw().
-     * @param offsetX draw at this offset into the given drawable
-     * @param offsetY draw at this offset into the given drawable
+     * @param offset  draw at this offset into the given drawable
      * @param clipRects an array of rectangles; clip to the union.
      *                  Any rectangles provided will be contained by the
      *                  rectangle with size provided to Draw and by the
      *                  surface extents.
      * @param numClipRects the number of rects in the array, or zero if
      *                     no clipping is required.
      */
-    virtual nsresult DrawWithXlib(gfxXlibSurface* surface,
+    virtual nsresult DrawWithXlib(cairo_surface_t* surface,
                                   nsIntPoint offset,
                                   nsIntRect* clipRects, uint32_t numClipRects) = 0;
   
     enum {
         // If set, then Draw() is opaque, i.e., every pixel in the intersection
         // of the clipRect and (offset.x,offset.y,bounds.width,bounds.height)
         // will be set and there is no dependence on what the existing pixels
         // in the drawable are set to.
@@ -66,50 +65,41 @@ public:
         // passed to 'Draw'.
         DRAW_SUPPORTS_ALTERNATE_VISUAL = 0x10,
         // If set, then the Screen 'screen' in the callback can be different
         // from the default Screen of the display passed to 'Draw' and can be
         // on a different display.
         DRAW_SUPPORTS_ALTERNATE_SCREEN = 0x20
     };
 
-    struct DrawOutput {
-        nsRefPtr<gfxASurface> mSurface;
-        bool mUniformAlpha;
-        bool mUniformColor;
-        gfxRGBA      mColor;
-    };
-
     /**
      * @param flags see above
      * @param size the size of the rectangle being drawn;
      * the caller guarantees that drawing will not extend beyond the rectangle
      * (0,0,size.width,size.height).
      * @param screen a Screen to use for the drawing if ctx doesn't have one.
      * @param visual a Visual to use for the drawing if ctx doesn't have one.
      * @param result if non-null, we will try to capture a copy of the
      * rendered image into a surface similar to the surface of ctx; if
      * successful, a pointer to the new gfxASurface is stored in *resultSurface,
      * otherwise *resultSurface is set to nullptr.
      */
     void Draw(gfxContext* ctx, nsIntSize size,
-              uint32_t flags, Screen *screen, Visual *visual,
-              DrawOutput* result);
+              uint32_t flags, Screen *screen, Visual *visual);
 
 private:
     bool DrawDirect(gfxContext *ctx, nsIntSize bounds,
                     uint32_t flags, Screen *screen, Visual *visual);
 
     bool DrawCairo(cairo_t* cr, nsIntSize size,
                    uint32_t flags, Screen *screen, Visual *visual);
 
     void DrawFallback(mozilla::gfx::DrawTarget* dt, gfxContext* ctx,
                       gfxASurface* aSurface, nsIntSize& size,
                       nsIntRect& drawingRect, bool canDrawOverBackground,
-                      uint32_t flags, Screen* screen, Visual* visual,
-                      DrawOutput* result);
+                      uint32_t flags, Screen* screen, Visual* visual);
 
-    bool DrawOntoTempSurface(gfxXlibSurface *tempXlibSurface,
+    bool DrawOntoTempSurface(cairo_surface_t *tempXlibSurface,
                              nsIntPoint offset);
 
 };
 
 #endif /*GFXXLIBNATIVERENDER_H_*/
--- a/gfx/thebes/gfxXlibSurface.cpp
+++ b/gfx/thebes/gfxXlibSurface.cpp
@@ -130,16 +130,58 @@ gfxXlibSurface::TakePixmap()
 Drawable
 gfxXlibSurface::ReleasePixmap() {
     NS_ASSERTION(mPixmapTaken, "I don't own the Pixmap!");
     mPixmapTaken = false;
     RecordMemoryFreed();
     return mDrawable;
 }
 
+static cairo_user_data_key_t gDestroyPixmapKey;
+
+struct DestroyPixmapClosure {
+    DestroyPixmapClosure(Drawable d, Screen *s) : mPixmap(d), mScreen(s) {}
+    Drawable mPixmap;
+    Screen *mScreen;
+};
+
+static void
+DestroyPixmap(void *data)
+{
+    DestroyPixmapClosure *closure = static_cast<DestroyPixmapClosure*>(data);
+    XFreePixmap(DisplayOfScreen(closure->mScreen), closure->mPixmap);
+    delete closure;
+}
+
+/* static */
+cairo_surface_t *
+gfxXlibSurface::CreateCairoSurface(Screen *screen, Visual *visual,
+                                   const gfxIntSize& size, Drawable relatedDrawable)
+{
+    Drawable drawable =
+        CreatePixmap(screen, size, DepthOfVisual(screen, visual),
+                     relatedDrawable);
+    if (!drawable)
+        return nullptr;
+
+    cairo_surface_t* surface =
+        cairo_xlib_surface_create(DisplayOfScreen(screen), drawable, visual,
+                                  size.width, size.height);
+    if (cairo_surface_status(surface)) {
+        cairo_surface_destroy(surface);
+        XFreePixmap(DisplayOfScreen(screen), drawable);
+        return nullptr;
+    }
+
+    DestroyPixmapClosure *closure = new DestroyPixmapClosure(drawable, screen);
+    cairo_surface_set_user_data(surface, &gDestroyPixmapKey,
+                                closure, DestroyPixmap);
+    return surface;
+}
+
 /* static */
 already_AddRefed<gfxXlibSurface>
 gfxXlibSurface::Create(Screen *screen, Visual *visual,
                        const gfxIntSize& size, Drawable relatedDrawable)
 {
     Drawable drawable =
         CreatePixmap(screen, size, DepthOfVisual(screen, visual),
                      relatedDrawable);
@@ -396,29 +438,37 @@ DisplayTable::DisplayClosing(Display *di
     sDisplayTable->mDisplays.RemoveElement(display, FindDisplay());
     if (sDisplayTable->mDisplays.Length() == 0) {
         delete sDisplayTable;
         sDisplayTable = nullptr;
     }
     return 0;
 }
 
+/* static */
+bool
+gfxXlibSurface::GetColormapAndVisual(cairo_surface_t* aXlibSurface,
+                                     Colormap* aColormap, Visual** aVisual)
+{
+    XRenderPictFormat* format =
+        cairo_xlib_surface_get_xrender_format(aXlibSurface);
+    Screen* screen = cairo_xlib_surface_get_screen(aXlibSurface);
+    Visual* visual = cairo_xlib_surface_get_visual(aXlibSurface);
+
+    return DisplayTable::GetColormapAndVisual(screen, format, visual,
+                                              aColormap, aVisual);
+}
+
 bool
 gfxXlibSurface::GetColormapAndVisual(Colormap* aColormap, Visual** aVisual)
 {
     if (!mSurfaceValid)
         return false;
 
-    XRenderPictFormat* format =
-        cairo_xlib_surface_get_xrender_format(CairoSurface());
-    Screen* screen = cairo_xlib_surface_get_screen(CairoSurface());
-    Visual* visual = cairo_xlib_surface_get_visual(CairoSurface());
-
-    return DisplayTable::GetColormapAndVisual(screen, format, visual,
-                                              aColormap, aVisual);
+    return GetColormapAndVisual(CairoSurface(), aColormap, aVisual);
 }
 
 /* static */
 int
 gfxXlibSurface::DepthOfVisual(const Screen* screen, const Visual* visual)
 {
     for (int d = 0; d < screen->ndepths; d++) {
         const Depth& d_info = screen->depths[d];
--- a/gfx/thebes/gfxXlibSurface.h
+++ b/gfx/thebes/gfxXlibSurface.h
@@ -36,16 +36,19 @@ public:
 
     // create a new Pixmap and wrapper surface.
     // |relatedDrawable| provides a hint to the server for determining whether
     // the pixmap should be in video or system memory.  It must be on
     // |screen| (if specified).
     static already_AddRefed<gfxXlibSurface>
     Create(Screen *screen, Visual *visual, const gfxIntSize& size,
            Drawable relatedDrawable = None);
+    static cairo_surface_t *
+    CreateCairoSurface(Screen *screen, Visual *visual, const gfxIntSize& size,
+                       Drawable relatedDrawable = None);
     static already_AddRefed<gfxXlibSurface>
     Create(Screen* screen, XRenderPictFormat *format, const gfxIntSize& size,
            Drawable relatedDrawable = None);
 
     virtual ~gfxXlibSurface();
 
     virtual already_AddRefed<gfxASurface>
     CreateSimilarSurface(gfxContentType aType, const gfxIntSize& aSize);
@@ -56,16 +59,17 @@ public:
     Display* XDisplay() { return mDisplay; }
     Screen* XScreen();
     Drawable XDrawable() { return mDrawable; }
     XRenderPictFormat* XRenderFormat();
 
     static int DepthOfVisual(const Screen* screen, const Visual* visual);
     static Visual* FindVisual(Screen* screen, gfxImageFormat format);
     static XRenderPictFormat *FindRenderFormat(Display *dpy, gfxImageFormat format);
+    static bool GetColormapAndVisual(cairo_surface_t* aXlibSurface, Colormap* colormap, Visual **visual);
 
     // take ownership of a passed-in Pixmap, calling XFreePixmap on it
     // when the gfxXlibSurface is destroyed.
     void TakePixmap();
 
     // Release ownership of this surface's Pixmap.  This is only valid
     // on gfxXlibSurfaces for which the user called TakePixmap(), or
     // on those created by a Create() factory method.
--- a/ipc/ipdl/Makefile.in
+++ b/ipc/ipdl/Makefile.in
@@ -3,18 +3,16 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 GARBAGE_DIRS += _ipdlheaders
 GARBAGE += ipdl_lextab.py ipdl_yacctab.py $(wildcard *.pyc $(srcdir)/ipdl/*.pyc $(srcdir)/ipdl/cxx/*.pyc)
 
 # This file is generated by the moz.build backend.
 include ipdlsrcs.mk
 
-GARBAGE += $(CPPSRCS)
-
 LOCAL_INCLUDES += -I$(DEPTH)/ipc/ipdl/_ipdlheaders
 
 
 include $(topsrcdir)/config/rules.mk
 
 
 # NB: the IPDL compiler manages .ipdl-->.h/.cpp dependencies itself,
 # which is why we don't have explicit .h/.cpp targets here
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -364,17 +364,17 @@ ifndef HAVE_DTRACE
 endif
 endif
 
 DIST_GARBAGE = config.cache config.log config.status* \
    config/autoconf.mk config/emptyvars.mk \
    $(JS_CONFIG_NAME) js-config.h js-confdefs.h \
    backend.mk config/backend.mk devtools/backend.mk editline/backend.mk \
    gdb/backend.mk jsapi-tests/backend.mk shell/backend.mk tests/backend.mk \
-   backend.RecursiveMakeBackend.built backend.RecursiveMakeBackend.built.pp \
+   backend.RecursiveMakeBackend backend.RecursiveMakeBackend.pp \
    devtools/rootAnalysis/Makefile
 
 distclean::
 	$(RM) $(DIST_GARBAGE)
 
 DEFINES		+= -DEXPORT_JS_API
 
 INCLUDES	+= -I$(srcdir)
--- a/js/src/build/ConfigStatus.py
+++ b/js/src/build/ConfigStatus.py
@@ -20,64 +20,51 @@ from mozbuild.backend.recursivemake impo
 from mozbuild.frontend.emitter import TreeMetadataEmitter
 from mozbuild.frontend.reader import BuildReader
 from mozbuild.mozinfo import write_mozinfo
 
 
 log_manager = LoggingManager()
 
 
-def config_status(topobjdir = '.', topsrcdir = '.',
-                  defines = [], non_global_defines = [], substs = [],
-                  files = [], headers = []):
+def config_status(topobjdir='.', topsrcdir='.',
+        defines=[], non_global_defines=[], substs=[]):
     '''Main function, providing config.status functionality.
 
     Contrary to config.status, it doesn't use CONFIG_FILES or CONFIG_HEADERS
-    variables, but like config.status from autoconf 2.6, single files may be
-    generated with the --file and --header options. Several such options can
-    be given to generate several files at the same time.
+    variables.
 
     Without the -n option, this program acts as config.status and considers
     the current directory as the top object directory, even when config.status
     is in a different directory. It will, however, treat the directory
-    containing config.status as the top object directory with the -n option,
-    while files given to the --file and --header arguments are considered
-    relative to the current directory.
+    containing config.status as the top object directory with the -n option.
 
     The --recheck option, like with the original config.status, runs configure
     again, with the options given in the "ac_configure_args" subst.
 
     The options to this function are passed when creating the
-    ConfigEnvironment, except for files and headers, which contain the list
-    of files and headers to be generated by default. These lists, as well as
-    the actual wrapper script around this function, are meant to be generated
-    by configure. See build/autoconf/config.status.m4.
-
-    Unlike config.status behaviour with CONFIG_FILES and CONFIG_HEADERS,
-    but like config.status behaviour with --file and --header, providing
-    files or headers on the command line inhibits the default generation of
-    files when given headers and headers when given files.
-
-    Unlike config.status, the FILE:TEMPLATE syntax is not supported for
-    files and headers. The template is always the filename suffixed with
-    '.in', in the corresponding directory under the top source directory.
+    ConfigEnvironment. These lists, as well as the actual wrapper script
+    around this function, are meant to be generated by configure.
+    See build/autoconf/config.status.m4.
     '''
 
     if 'CONFIG_FILES' in os.environ:
-        raise Exception, 'Using the CONFIG_FILES environment variable is not supported. Use --file instead.'
+        raise Exception('Using the CONFIG_FILES environment variable is not '
+            'supported.')
     if 'CONFIG_HEADERS' in os.environ:
-        raise Exception, 'Using the CONFIG_HEADERS environment variable is not supported. Use --header instead.'
+        raise Exception('Using the CONFIG_HEADERS environment variable is not '
+            'supported.')
+
+    if not os.path.isabs(topsrcdir):
+        raise Exception('topsrcdir must be defined as an absolute directory: '
+            '%s' % topsrcdir)
 
     parser = OptionParser()
     parser.add_option('--recheck', dest='recheck', action='store_true',
                       help='update config.status by reconfiguring in the same conditions')
-    parser.add_option('--file', dest='files', metavar='FILE', action='append',
-                      help='instantiate the configuration file FILE')
-    parser.add_option('--header', dest='headers', metavar='FILE', action='append',
-                      help='instantiate the configuration header FILE')
     parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
                       help='display verbose output')
     parser.add_option('-n', dest='not_topobjdir', action='store_true',
                       help='do not consider current directory as top object directory')
     (options, args) = parser.parse_args()
 
     # Without -n, the current directory is meant to be the top object directory
     if not options.not_topobjdir:
@@ -94,44 +81,20 @@ def config_status(topobjdir = '.', topsr
     reader = BuildReader(env)
     emitter = TreeMetadataEmitter(env)
     backend = RecursiveMakeBackend(env)
     # This won't actually do anything because of the magic of generators.
     definitions = emitter.emit(reader.read_topsrcdir())
 
     if options.recheck:
         # Execute configure from the top object directory
-        if not os.path.isabs(topsrcdir):
-            topsrcdir = relpath(topsrcdir, topobjdir)
         os.chdir(topobjdir)
         os.execlp('sh', 'sh', '-c', ' '.join([os.path.join(topsrcdir, 'configure'), env.substs['ac_configure_args'], '--no-create', '--no-recursion']))
 
-    if options.files:
-        files = options.files
-        headers = []
-    if options.headers:
-        headers = options.headers
-        if not options.files:
-            files = []
-    # Default to display messages when giving --file or --headers on the
-    # command line.
-    log_level = logging.INFO
-
-    if options.files or options.headers or options.verbose:
-        log_level = logging.DEBUG
-
+    log_level = logging.DEBUG if options.verbose else logging.INFO
     log_manager.add_terminal_logging(level=log_level)
     log_manager.enable_unstructured()
 
-    if not options.files and not options.headers:
-        print('Reticulating splines...', file=sys.stderr)
-        summary = backend.consume(definitions)
-
-        for line in summary.summaries():
-            print(line, file=sys.stderr)
+    print('Reticulating splines...', file=sys.stderr)
+    summary = backend.consume(definitions)
 
-        files = [os.path.join(topobjdir, f) for f in files]
-        headers = [os.path.join(topobjdir, f) for f in headers]
-
-    for file in files:
-        env.create_config_file(file)
-    for header in headers:
-        env.create_config_header(header)
+    for line in summary.summaries():
+        print(line, file=sys.stderr)
--- a/js/src/build/autoconf/config.status.m4
+++ b/js/src/build/autoconf/config.status.m4
@@ -37,17 +37,17 @@ define([_MOZ_AC_DEFINE_UNQUOTED], defn([
 define([AC_DEFINE_UNQUOTED],
 [cat >> confdefs.pytmp <<EOF
     (''' $1 ''', ifelse($#, 2, [r''' $2 '''], $#, 3, [r''' $2 '''], ' 1 '))
 EOF
 ifelse($#, 2, _MOZ_AC_DEFINE_UNQUOTED($1, $2), $#, 3, _MOZ_AC_DEFINE_UNQUOTED($1, $2, $3),_MOZ_AC_DEFINE_UNQUOTED($1))dnl
 ])
 
 dnl Replace AC_OUTPUT to create and call a python config.status
-define([AC_OUTPUT],
+define([_MOZ_AC_OUTPUT],
 [dnl Top source directory in Windows format (as opposed to msys format).
 WIN_TOP_SRC=
 encoding=utf-8
 case "$host_os" in
 mingw*)
     WIN_TOP_SRC=`cd $srcdir; pwd -W`
     encoding=mbcs
     ;;
@@ -116,57 +116,30 @@ dnl Add in the output from the subconfig
 for ac_subst_arg in $_subconfigure_ac_subst_args; do
   variable='$'$ac_subst_arg
   echo "    (''' $ac_subst_arg ''', r''' `eval echo $variable` ''')," >> $CONFIG_STATUS
 done
 
 cat >> $CONFIG_STATUS <<\EOF
 ] ]
 
-dnl List of files to apply AC_SUBSTs to. This is the list of files given
-dnl as an argument to AC_OUTPUT ($1)
-files = [
-EOF
-
-for out in $1; do
-  echo "    '$out'," >> $CONFIG_STATUS
-done
-
-cat >> $CONFIG_STATUS <<\EOF
-]
-
-dnl List of header files to apply AC_DEFINEs to. This is stored in the
-dnl AC_LIST_HEADER m4 macro by AC_CONFIG_HEADER.
-headers = [
-EOF
-
-ifdef(<<<AC_LIST_HEADER>>>, <<<
-HEADERS="AC_LIST_HEADER"
-for header in $HEADERS; do
-  echo "    '$header'," >> $CONFIG_STATUS
-done
->>>)dnl
-
-cat >> $CONFIG_STATUS <<\EOF
-]
-
 dnl List of AC_DEFINEs that aren't to be exposed in ALLDEFINES
 non_global_defines = [
 EOF
 
 if test -n "$_NON_GLOBAL_ACDEFINES"; then
   for var in $_NON_GLOBAL_ACDEFINES; do
     echo "    '$var'," >> $CONFIG_STATUS
   done
 fi
 
 cat >> $CONFIG_STATUS <<EOF
 ]
 
-__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs', 'files', 'headers']
+__all__ = ['topobjdir', 'topsrcdir', 'defines', 'non_global_defines', 'substs']
 
 dnl Do the actual work
 if __name__ == '__main__':
     args = dict([(name, globals()[name]) for name in __all__])
     import sys
 dnl Don't rely on virtualenv here. Standalone js doesn't use it.
     sys.path.append(os.path.join(topsrcdir, ${extra_python_path}'build'))
     from ConfigStatus import config_status
@@ -177,9 +150,23 @@ chmod +x $CONFIG_STATUS
 rm -fr confdefs* $ac_clean_files
 dnl Execute config.status, unless --no-create was passed to configure.
 if test "$no_create" != yes && ! ${PYTHON} $CONFIG_STATUS; then
     trap '' EXIT
     exit 1
 fi
 ])
 
+define([m4_fatal],[
+errprint([$1
+])
+m4exit(1)
+])
+
+define([AC_OUTPUT], [ifelse($#_$1, 1_, [_MOZ_AC_OUTPUT()],
+[m4_fatal([Use CONFIGURE_SUBST_FILES in moz.build files to create substituted files.])]
+)])
+
+define([AC_CONFIG_HEADER],
+[m4_fatal([Use CONFIGURE_DEFINE_FILES in moz.build files to produce header files.])
+])
+
 AC_SUBST([MOZ_PSEUDO_DERECURSE])
--- a/js/src/config/moz.build
+++ b/js/src/config/moz.build
@@ -1,14 +1,19 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+CONFIGURE_SUBST_FILES += [
+    'autoconf.mk',
+    'emptyvars.mk',
+]
+
 NO_DIST_INSTALL = True
 # For sanity's sake, we compile nsinstall without the wrapped system
 # headers, so that we can use it to set up the wrapped system headers.
 NO_VISIBILITY_FLAGS = True
 
 if CONFIG['HOST_OS_ARCH'] != 'WINNT':
     HOST_SOURCES += [
         'nsinstall.c',
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -597,36 +597,31 @@ ifndef MOZBUILD_BACKEND_CHECKED
 
 # Since Makefile is listed as a global dependency, this has the
 # unfortunate side-effect of invalidating all targets if it is executed.
 # So e.g. if you are in /dom/bindings and /foo/moz.build changes,
 # /dom/bindings will get invalidated. The upside is if the current
 # Makefile/backend.mk is updated as a result of backend regeneration, we
 # actually pick up the changes. This should reduce the amount of
 # required clobbers and is thus the lesser evil.
-Makefile: $(DEPTH)/backend.RecursiveMakeBackend.built
+Makefile: $(DEPTH)/backend.RecursiveMakeBackend
 	@$(TOUCH) $@
 
-$(DEPTH)/backend.RecursiveMakeBackend.built:
+$(DEPTH)/backend.RecursiveMakeBackend:
 	@echo "Build configuration changed. Regenerating backend."
 	@cd $(DEPTH) && $(PYTHON) ./config.status
 	@$(TOUCH) $@
 
-include $(DEPTH)/backend.RecursiveMakeBackend.built.pp
+include $(DEPTH)/backend.RecursiveMakeBackend.pp
 
-default:: $(DEPTH)/backend.RecursiveMakeBackend.built
+default:: $(DEPTH)/backend.RecursiveMakeBackend
 
 export MOZBUILD_BACKEND_CHECKED=1
 endif
 
-
-# SUBMAKEFILES: List of Makefiles for next level down.
-#   This is used to update or create the Makefiles before invoking them.
-SUBMAKEFILES += $(addsuffix /Makefile, $(DIRS) $(TOOL_DIRS) $(PARALLEL_DIRS))
-
 # The root makefile doesn't want to do a plain export/libs, because
 # of the tiers and because of libxul. Suppress the default rules in favor
 # of something else. Makefiles which use this var *must* provide a sensible
 # default rule before including rules.mk
 ifndef SUPPRESS_DEFAULT_RULES
 default all::
 	$(MAKE) export
 ifdef MOZ_PSEUDO_DERECURSE
@@ -644,35 +639,24 @@ ECHO := true
 QUIET := -q
 endif
 
 # Do everything from scratch
 everything::
 	$(MAKE) clean
 	$(MAKE) all
 
-# Target to only regenerate makefiles
-makefiles: $(SUBMAKEFILES)
-ifneq (,$(DIRS)$(TOOL_DIRS)$(PARALLEL_DIRS))
-	$(LOOP_OVER_PARALLEL_DIRS)
-	$(LOOP_OVER_DIRS)
-	$(LOOP_OVER_TOOL_DIRS)
-endif
-
 ifneq (,$(filter-out %.$(LIB_SUFFIX),$(SHARED_LIBRARY_LIBS)))
 $(error SHARED_LIBRARY_LIBS must contain .$(LIB_SUFFIX) files only)
 endif
 
 HOST_LIBS_DEPS = $(filter %.$(LIB_SUFFIX),$(HOST_LIBS))
 
 # Dependencies which, if modified, should cause everything to rebuild
 GLOBAL_DEPS += Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk
-ifndef NO_MAKEFILE_RULE
-GLOBAL_DEPS += Makefile.in
-endif
 
 ##############################################
 OBJ_TARGETS = $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)
 
 compile:: $(OBJ_TARGETS)
 
 include $(topsrcdir)/config/makefiles/target_libs.mk
 
@@ -737,30 +721,30 @@ endif
 
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
 ##############################################
 
 checkout:
 	$(MAKE) -C $(topsrcdir) -f client.mk checkout
 
-clean clobber realclean clobber_all:: $(SUBMAKEFILES)
+clean clobber realclean clobber_all::
 	-$(RM) $(ALL_TRASH)
 	-$(RM) -r $(ALL_TRASH_DIRS)
 
 ifdef TIERS
 clean clobber realclean clobber_all distclean::
 	$(foreach dir, \
 		$(foreach tier, $(TIERS), $(tier_$(tier)_staticdirs) $(tier_$(tier)_dirs)), \
 		-$(call SUBMAKE,$@,$(dir)))
 else
 clean clobber realclean clobber_all distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 
-distclean:: $(SUBMAKEFILES)
+distclean::
 	$(foreach dir,$(PARALLEL_DIRS) $(DIRS) $(TOOL_DIRS),-$(call SUBMAKE,$@,$(dir)))
 endif
 
 distclean::
 	-$(RM) -r $(ALL_TRASH_DIRS)
 	-$(RM) $(ALL_TRASH)  \
 	Makefile .HSancillary \
 	$(wildcard *.$(OBJ_SUFFIX)) $(wildcard *.ho) $(wildcard host_*.o*) \
@@ -1158,44 +1142,16 @@ endif
 ###############################################################################
 # Java rules
 ###############################################################################
 ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS))
   include $(topsrcdir)/config/makefiles/java-build.mk
 endif
 
 ###############################################################################
-# Update Files Managed by Build Backend
-###############################################################################
-
-ifndef NO_MAKEFILE_RULE
-Makefile: Makefile.in
-	@$(PYTHON) $(DEPTH)/config.status -n --file=Makefile
-	@$(TOUCH) $@
-endif
-
-ifndef NO_SUBMAKEFILES_RULE
-ifdef SUBMAKEFILES
-# VPATH does not work on some machines in this case, so add $(srcdir)
-$(SUBMAKEFILES): % : $(srcdir)/%.in
-	$(PYTHON) $(DEPTH)$(addprefix /,$(subsrcdir))/config.status -n --file="$@"
-	@$(TOUCH) "$@"
-endif
-endif
-
-ifdef AUTOUPDATE_CONFIGURE
-$(topsrcdir)/configure: $(topsrcdir)/configure.in
-	(cd $(topsrcdir) && $(AUTOCONF)) && $(PYTHON) $(DEPTH)/config.status -n --recheck
-endif
-
-$(DEPTH)/config/autoconf.mk: $(topsrcdir)/config/autoconf.mk.in
-	$(PYTHON) $(DEPTH)/config.status -n --file=$(DEPTH)/config/autoconf.mk
-	$(TOUCH) $@
-
-###############################################################################
 # Bunch of things that extend the 'export' rule (in order):
 ###############################################################################
 
 ifneq ($(XPI_NAME),)
 $(FINAL_TARGET):
 	$(NSINSTALL) -D $@
 
 export:: $(FINAL_TARGET)
@@ -1620,34 +1576,34 @@ endif
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
 tags: TAGS
 
-TAGS: $(SUBMAKEFILES) $(CSRCS) $(CPPSRCS) $(wildcard *.h)
+TAGS: $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	-etags $(CSRCS) $(CPPSRCS) $(wildcard *.h)
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 
 ifndef INCLUDED_DEBUGMAKE_MK #{
   ## Only parse when an echo* or show* target is requested
   ifneq (,$(call isTargetStem,echo,show))
     include $(topsrcdir)/config/makefiles/debugmake.mk
   endif #}
 endif #}
 
 documentation:
 	@cd $(DEPTH)
 	$(DOXYGEN) $(DEPTH)/config/doxygen.cfg
 
 ifdef ENABLE_TESTS
-check:: $(SUBMAKEFILES)
+check::
 	$(LOOP_OVER_PARALLEL_DIRS)
 	$(LOOP_OVER_DIRS)
 	$(LOOP_OVER_TOOL_DIRS)
 endif
 
 
 FREEZE_VARIABLES = \
   CSRCS \
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -5,17 +5,16 @@ dnl License, v. 2.0. If a copy of the MP
 dnl file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 dnl Process this file with autoconf to produce a configure script.
 dnl ========================================================
 
 AC_PREREQ(2.13)
 AC_INIT(jsapi.h)
 AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
-AC_CONFIG_HEADER(js-config.h)
 AC_CANONICAL_SYSTEM
 TARGET_CPU="${target_cpu}"
 TARGET_VENDOR="${target_vendor}"
 TARGET_OS="${target_os}"
 
 dnl ========================================================
 dnl =
 dnl = Don't change the following two lines.  Doing so breaks:
@@ -4262,17 +4261,17 @@ AC_HAVE_FUNCS(localeconv)
 
 AC_SUBST(MOZILLA_VERSION)
 
 AC_SUBST(ac_configure_args)
 
 dnl Spit out some output
 dnl ========================================================
 
-AC_OUTPUT([js-confdefs.h config/autoconf.mk config/emptyvars.mk])
+AC_OUTPUT()
 
 # Produce the js-config script at configure time; see the comments for
 # 'js*-config' in Makefile.in.
 AC_MSG_RESULT(invoking $MAKE to create $JS_CONFIG_NAME script)
 $MAKE $JS_CONFIG_NAME
 
 # Build jsctypes if it's enabled.
 if test "$JS_HAS_CTYPES" -a -z "$MOZ_NATIVE_FFI"; then
--- a/js/src/devtools/rootAnalysis/analyze.py
+++ b/js/src/devtools/rootAnalysis/analyze.py
@@ -119,27 +119,32 @@ JOBS = { 'dbs':
              (('%(js)s', '%(analysis_scriptdir)s/computeGCTypes.js',),
               'gcTypes.txt'),
 
          'allFunctions':
              (('%(sixgill_bin)s/xdbkeys', 'src_body.xdb',),
               'allFunctions.txt'),
 
          'hazards':
-             (generate_hazards, 'rootingHazards.txt')
+             (generate_hazards, 'rootingHazards.txt'),
+
+         'explain':
+             (('python', '%(analysis_scriptdir)s/explain.py',
+               '--expect-file=%(analysis_scriptdir)s/expect.json',
+               '%(hazards)s', '%(gcFunctions)s',
+               '[explained_hazards]', '[unnecessary]', '[refs]'),
+              ('hazards.txt', 'unnecessary.txt', 'refs.txt'))
          }
 
-
 def out_indexes(command):
     for i in range(len(command)):
         m = re.match(r'^\[(.*)\]$', command[i])
         if m:
             yield (i, m.group(1))
 
-
 def run_job(name, config):
     cmdspec, outfiles = JOBS[name]
     print("Running " + name + " to generate " + str(outfiles))
     if hasattr(cmdspec, '__call__'):
         cmdspec(config, outfiles)
     else:
         temp_map = {}
         cmdspec = fill(cmdspec, config)
@@ -227,17 +232,18 @@ if 'ANALYZED_OBJDIR' in os.environ:
 if 'SOURCE' in os.environ:
     data['source'] = os.environ['SOURCE']
 
 steps = [ 'dbs',
           'callgraph',
           'gcTypes',
           'gcFunctions',
           'allFunctions',
-          'hazards' ]
+          'hazards',
+          'explain' ]
 
 if args.list:
     for step in steps:
         command, outfilename = JOBS[step]
         if outfilename:
             print("%s -> %s" % (step, outfilename))
         else:
             print(step)
@@ -247,17 +253,17 @@ for step in steps:
     command, outfiles = JOBS[step]
     if isinstance(outfiles, basestring):
         data[step] = outfiles
     else:
         outfile = 0
         for (i, name) in out_indexes(command):
             data[name] = outfiles[outfile]
             outfile += 1
-        assert len(outfiles) == outfile, 'step %s: mismatched number of output files and params' % step
+        assert len(outfiles) == outfile, 'step \'%s\': mismatched number of output files and params' % step
 
 if args.step:
     steps = steps[steps.index(args.step):]
 
 if args.upto:
     steps = steps[:steps.index(args.upto)+1]
 
 for step in steps:
--- a/js/src/devtools/rootAnalysis/annotations.js
+++ b/js/src/devtools/rootAnalysis/annotations.js
@@ -60,16 +60,17 @@ var ignoreClasses = {
 // Ignore calls through TYPE.FIELD, where TYPE is the class or struct name containing
 // a function pointer field named FIELD.
 var ignoreCallees = {
     "js::Class.trace" : true,
     "js::Class.finalize" : true,
     "JSRuntime.destroyPrincipals" : true,
     "nsISupports.AddRef" : true,
     "nsISupports.Release" : true, // makes me a bit nervous; this is a bug but can happen
+    "nsIGlobalObject.GetGlobalJSObject" : true, // virtual but no implementation can GC
     "nsAXPCNativeCallContext.GetJSContext" : true,
     "js::jit::MDefinition.op" : true, // macro generated virtuals just return a constant
     "js::jit::MDefinition.opName" : true, // macro generated virtuals just return a constant
     "js::jit::LInstruction.getDef" : true, // virtual but no implementation can GC
     "js::jit::IonCache.kind" : true, // macro generated virtuals just return a constant
     "icu_50::UObject.__deleting_dtor" : true, // destructors in ICU code can't cause GC
     "mozilla::CycleCollectedJSRuntime.DescribeCustomObjects" : true, // During tracing, cannot GC.
     "mozilla::CycleCollectedJSRuntime.NoteCustomGCThingXPCOMChildren" : true, // During tracing, cannot GC.
new file mode 100644
--- /dev/null
+++ b/js/src/devtools/rootAnalysis/expect.json
@@ -0,0 +1,3 @@
+{
+  "expect-hazards": 13
+}
new file mode 100755
--- /dev/null
+++ b/js/src/devtools/rootAnalysis/explain.py
@@ -0,0 +1,120 @@
+#!/usr/bin/python
+
+import re
+import argparse
+import sys
+
+parser = argparse.ArgumentParser(description='Process some integers.')
+parser.add_argument('rootingHazards', nargs='?', default='rootingHazards.txt')
+parser.add_argument('gcFunctions', nargs='?', default='gcFunctions.txt')
+parser.add_argument('hazards', nargs='?', default='hazards.txt')
+parser.add_argument('extra', nargs='?', default='unnecessary.txt')
+parser.add_argument('refs', nargs='?', default='refs.txt')
+parser.add_argument('--expect-hazards', type=int, default=None)
+parser.add_argument('--expect-refs', type=int, default=None)
+parser.add_argument('--expect-file', type=str, default=None)
+args = parser.parse_args()
+
+if args.expect_file:
+    import json
+    data = json.load(file(args.expect_file, 'r'))
+    args.expect_hazards = args.expect_hazards or data.get('expect-hazards')
+    args.expect_refs = args.expect_refs or data.get('expect-refs')
+
+num_hazards = 0
+num_refs = 0
+try:
+    with open(args.rootingHazards) as rootingHazards, \
+        open(args.hazards, 'w') as hazards, \
+        open(args.extra, 'w') as extra, \
+        open(args.refs, 'w') as refs:
+        current_gcFunction = None
+
+        # Map from a GC function name to the list of hazards resulting from
+        # that GC function
+        hazardousGCFunctions = {}
+
+        # List of tuples (gcFunction, index of hazard) used to maintain the
+        # ordering of the hazards
+        hazardOrder = []
+
+        for line in rootingHazards:
+            m = re.match(r'^Time: (.*)', line)
+            mm = re.match(r'^Run on:', line)
+            if m or mm:
+                print >>hazards, line
+                print >>extra, line
+                print >>refs, line
+                continue
+
+            m = re.match(r'^Function.*has unnecessary root', line)
+            if m:
+                print >>extra, line
+                continue
+
+            m = re.match(r'^Function.*takes unsafe address of unrooted', line)
+            if m:
+                num_refs += 1
+                print >>refs, line
+                continue
+
+            m = re.match(r"^Function.*has unrooted.*of type.*live across GC call '(.*?)'", line)
+            if m:
+                current_gcFunction = m.group(1)
+                hazardousGCFunctions.setdefault(current_gcFunction, []).append(line);
+                hazardOrder.append((current_gcFunction, len(hazardousGCFunctions[current_gcFunction]) - 1))
+                num_hazards += 1
+                continue
+
+            if current_gcFunction:
+                if not line.strip():
+                    # Blank line => end of this hazard
+                    current_gcFunction = None
+                else:
+                    hazardousGCFunctions[current_gcFunction][-1] += line
+
+        with open(args.gcFunctions) as gcFunctions:
+            gcExplanations = {} # gcFunction => stack showing why it can GC
+
+            current_func = None
+            for line in gcFunctions:
+                m = re.match(r'^GC Function: (.*)', line)
+                if m:
+                    if current_func:
+                        gcExplanations[current_func] = explanation
+                    current_func = None
+                    if m.group(1) in hazardousGCFunctions:
+                        current_func = m.group(1)
+                        explanation = line
+                elif current_func:
+                    explanation += line
+            if current_func:
+                gcExplanations[current_func] = explanation
+
+            for gcFunction, index in hazardOrder:
+                gcHazards = hazardousGCFunctions[gcFunction]
+                print >>hazards, (gcHazards[index] + gcExplanations[gcFunction])
+
+except IOError as e:
+    print 'Failed: %s' % str(e)
+
+print("Wrote %s" % args.hazards)
+print("Wrote %s" % args.extra)
+print("Wrote %s" % args.refs)
+print("Found %d hazards and %d unsafe references" % (num_hazards, num_refs))
+
+if args.expect_hazards is not None and args.expect_hazards != num_hazards:
+    if args.expect_hazards < num_hazards:
+        print("TEST-UNEXPECTED-FAILURE: %d more hazards than expected (expected %d, saw %d)" % (num_hazards - args.expect_hazards, args.expect_hazards, num_hazards))
+        sys.exit(1)
+    else:
+        print("%d fewer hazards than expected! (expected %d, saw %d)" % (args.expect_hazards - num_hazards, args.expect_hazards, num_hazards))
+
+if args.expect_refs is not None and args.expect_refs != num_refs:
+    if args.expect_refs < num_refs:
+        print("TEST-UNEXPECTED-FAILURE: %d more unsafe refs than expected (expected %d, saw %d)" % (num_refs - args.expect_refs, args.expect_refs, num_refs))
+        sys.exit(1)
+    else:
+        print("%d fewer unsafe refs than expected! (expected %d, saw %d)" % (args.expect_refs - num_refs, args.expect_refs, num_refs))
+
+sys.exit(0)
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -236,34 +236,16 @@ class SourceHook {
  */
 extern JS_FRIEND_API(void)
 SetSourceHook(JSRuntime *rt, SourceHook *hook);
 
 /* Remove |rt|'s source hook, and return it. The caller now owns the hook. */
 extern JS_FRIEND_API(SourceHook *)
 ForgetSourceHook(JSRuntime *rt);
 
-inline JSRuntime *
-GetRuntime(const JSContext *cx)
-{
-    return ContextFriendFields::get(cx)->runtime_;
-}
-
-inline JSCompartment *
-GetContextCompartment(const JSContext *cx)
-{
-    return ContextFriendFields::get(cx)->compartment_;
-}
-
-inline JS::Zone *
-GetContextZone(const JSContext *cx)
-{
-    return ContextFriendFields::get(cx)->zone_;
-}
-
 extern JS_FRIEND_API(JS::Zone *)
 GetCompartmentZone(JSCompartment *comp);
 
 typedef bool
 (* PreserveWrapperCallback)(JSContext *cx, JSObject *obj);
 
 typedef enum  {
     CollectNurseryBeforeDump,
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -354,16 +354,44 @@ struct ContextFriendFields
     /* Stack of thread-stack-allocated GC roots. */
     JS::AutoGCRooter   *autoGCRooters;
 
     friend JSRuntime *GetRuntime(const JSContext *cx);
     friend JSCompartment *GetContextCompartment(const JSContext *cx);
     friend JS::Zone *GetContextZone(const JSContext *cx);
 };
 
+/*
+ * Inlinable accessors for JSContext.
+ *
+ * - These must not be available on the more restricted superclasses of
+ *   JSContext, so we can't simply define them on ContextFriendFields.
+ *
+ * - They're perfectly ordinary JSContext functionality, so ought to be
+ *   usable without resorting to jsfriendapi.h, and when JSContext is an
+ *   incomplete type.
+ */
+inline JSRuntime *
+GetRuntime(const JSContext *cx)
+{
+    return ContextFriendFields::get(cx)->runtime_;
+}
+
+inline JSCompartment *
+GetContextCompartment(const JSContext *cx)
+{
+    return ContextFriendFields::get(cx)->compartment_;
+}
+
+inline JS::Zone *
+GetContextZone(const JSContext *cx)
+{
+    return ContextFriendFields::get(cx)->zone_;
+}
+
 class PerThreadData;
 
 struct PerThreadDataFriendFields
 {
   private:
     // Note: this type only exists to permit us to derive the offset of
     // the perThread data within the real JSRuntime* type in a portable
     // way.
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -20,17 +20,24 @@ TEST_DIRS += ['jsapi-tests', 'tests', 'g
 
 MODULE = 'js'
 
 if CONFIG['JS_STANDALONE']:
     LIBRARY_NAME = 'mozjs-%s.%s%s' % (CONFIG['MOZJS_MAJOR_VERSION'], CONFIG['MOZJS_MINOR_VERSION'], CONFIG['MOZJS_ALPHA'])
 else:
     LIBRARY_NAME = 'mozjs'
 
-CONFIGURE_SUBST_FILES += ['devtools/rootAnalysis/Makefile']
+CONFIGURE_SUBST_FILES += [
+    'devtools/rootAnalysis/Makefile',
+    'js-confdefs.h',
+]
+
+CONFIGURE_DEFINE_FILES += [
+    'js-config.h',
+]
 
 # Changes to internal header files, used externally, massively slow down
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
 EXPORTS += [
     'js.msg',
     'jsalloc.h',
     'jsapi.h',
--- a/js/src/vm/OldDebugAPI.cpp
+++ b/js/src/vm/OldDebugAPI.cpp
@@ -1024,21 +1024,29 @@ class AutoPropertyDescArray
 
 } /* anonymous namespace */
 
 static const char *
 FormatValue(JSContext *cx, const Value &vArg, JSAutoByteString &bytes)
 {
     RootedValue v(cx, vArg);
 
-    mozilla::Maybe<AutoCompartment> ac;
-    if (v.isObject())
-        ac.construct(cx, &v.toObject());
+    /*
+     * We could use Maybe<AutoCompartment> here, but G++ can't quite follow
+     * that, and warns about uninitialized members being used in the
+     * destructor.
+     */
+    RootedString str(cx);
+    if (v.isObject()) {
+        AutoCompartment ac(cx, &v.toObject());
+        str = ToString<CanGC>(cx, v);
+    } else {
+        str = ToString<CanGC>(cx, v);
+    }
 
-    JSString *str = ToString<CanGC>(cx, v);
     if (!str)
         return nullptr;
     const char *buf = bytes.encodeLatin1(cx, str);
     if (!buf)
         return nullptr;
     const char *found = strstr(buf, "function ");
     if (found && (found - buf <= 2))
         return "[function]";
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1626,23 +1626,27 @@ JS_StructuredClone(JSContext *cx, JS::Ha
 
     const JSStructuredCloneCallbacks *callbacks =
         optionalCallbacks ?
         optionalCallbacks :
         cx->runtime()->structuredCloneCallbacks;
 
     JSAutoStructuredCloneBuffer buf;
     {
-        mozilla::Maybe<AutoCompartment> ac;
+        // If we use Maybe<AutoCompartment> here, G++ can't tell that the
+        // destructor is only called when Maybe::construct was called, and
+        // we get warnings about using uninitialized variables.
         if (value.isObject()) {
-            ac.construct(cx, &value.toObject());
+            AutoCompartment ac(cx, &value.toObject());
+            if (!buf.write(cx, value, callbacks, closure))
+                return false;
+        } else {
+            if (!buf.write(cx, value, callbacks, closure))
+                return false;
         }
-
-        if (!buf.write(cx, value, callbacks, closure))
-            return false;
     }
 
     return buf.read(cx, vp, callbacks, closure);
 }
 
 void
 JSAutoStructuredCloneBuffer::clear()
 {
--- a/layout/base/PositionedEventTargeting.cpp
+++ b/layout/base/PositionedEventTargeting.cpp
@@ -169,16 +169,26 @@ IsElementClickable(nsIFrame* aFrame, nsI
     if (content->IsHTML()) {
       if (tag == nsGkAtoms::button ||
           tag == nsGkAtoms::input ||
           tag == nsGkAtoms::select ||
           tag == nsGkAtoms::textarea ||
           tag == nsGkAtoms::label) {
         return true;
       }
+      // Bug 921928: we don't have access to the content of remote iframe.
+      // So fluffing won't go there. We do an optimistic assumption here:
+      // that the content of the remote iframe needs to be a target.
+      if (tag == nsGkAtoms::iframe &&
+          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::mozbrowser,
+                               nsGkAtoms::_true, eIgnoreCase) &&
+          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::Remote,
+                               nsGkAtoms::_true, eIgnoreCase)) {
+        return true;
+      }
     } else if (content->IsXUL()) {
       nsIAtom* tag = content->Tag();
       // See nsCSSFrameConstructor::FindXULTagData. This code is not
       // really intended to be used with XUL, though.
       if (tag == nsGkAtoms::button ||
           tag == nsGkAtoms::checkbox ||
           tag == nsGkAtoms::radio ||
           tag == nsGkAtoms::autorepeatbutton ||
--- a/layout/base/tests/Makefile.in
+++ b/layout/base/tests/Makefile.in
@@ -110,16 +110,18 @@ MOCHITEST_FILES =	\
 		test_bug582181-2.html \
 		test_bug588174.html \
 		test_bug607529.html \
 		file_bug607529.html \
 		test_bug667512.html \
 		test_bug677878.html \
 		test_bug696020.html \
 		test_event_target_radius.html \
+		test_event_target_iframe_oop.html \
+		bug921928_event_target_iframe_apps_oop.html \
 		test_mozPaintCount.html \
 		test_scroll_event_ordering.html \
 		test_scroll_selection_into_view.html \
 		test_bug583889.html \
 		bug583889_inner1.html \
 		bug583889_inner2.html \
 		test_bug582771.html \
 		test_bug603550.html \
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/bug921928_event_target_iframe_apps_oop.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test companion for bug 921928</title>
+</head>
+<body>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/base/tests/test_event_target_iframe_oop.html
@@ -0,0 +1,178 @@
+<!DOCTYPE HTML>
+<html id="html" style="height:100%">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=921928
+-->
+<head>
+  <title>Test for bug 921928</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style>
+  #dialer {
+    position: absolute;
+    left: 0;
+    top: 0;
+    width: 100%;
+    height: 50px;
+    background: green;
+  }
+
+  #apps {
+    position: absolute;
+    left: 0;
+    top: 51px;
+    width: 100%;
+    height: 100px;
+    background: blue;
+  }
+
+  .hit {
+    position: absolute;
+    width: 3px;
+    height: 3px;
+    z-index: 20;
+    background: red;
+    border: 1px solid red;
+  }
+  </style>
+</head>
+<body id="body" style="margin:0; width:100%; height:100%">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var prefs = [
+  ["ui.mouse.radius.enabled", true],
+  ["ui.mouse.radius.inputSource.touchOnly", false],
+  ["ui.mouse.radius.leftmm", 12],
+  ["ui.mouse.radius.topmm", 8],
+  ["ui.mouse.radius.rightmm", 4],
+  ["ui.mouse.radius.bottommm", 4],
+  ["ui.mouse.radius.visitedweight", 50],
+  ["dom.mozBrowserFramesEnabled", true]
+];
+
+var eventTarget;
+var debugHit = [];
+
+function endTest() {
+  SimpleTest.finish();
+  SpecialPowers.removePermission("browser", location.href);
+  for (var pref in prefs) {
+    SpecialPowers.pushPrefEnv({"clear": pref[0]}, function() {});
+  }
+}
+
+function testMouseClick(idPosition, dx, dy, idTarget, msg, options) {
+  eventTarget = null;
+  synthesizeMouse(document.getElementById(idPosition), dx, dy, options || {});
+  try {
+    is(eventTarget.id, idTarget,
+       "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]");
+  } catch (ex) {
+    ok(false, "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]; got " + eventTarget);
+  }
+}
+
+function showDebug() {
+  for (var i = 0; i < debugHit.length; i++) {
+    document.body.appendChild(debugHit[i]);
+  }
+
+  var screenshot = SpecialPowers.snapshotWindow(window, true);
+  dump('IMAGE:' + screenshot.toDataURL() + '\n');
+}
+
+/*
+  Setup the test environment: enabling event fluffing (all ui.* preferences),
+  and enabling remote process.
+*/
+function setupTest(cont) {
+  SpecialPowers.addPermission("browser", true, document);
+  SpecialPowers.pushPrefEnv({"set": prefs}, cont);
+}
+
+function execTest() {
+  /*
+     Creating two iframes that mimics the attention screen behavior on the
+     device:
+       - the 'dialer' iframe is the attention screen you have when a call is
+         in place. it is a green bar, so we copy it as green here too
+       - the 'apps' iframe mimics another application that is being run, be it
+         dialer, sms, ..., anything that the user might want to trigger during
+         a call
+
+     The bug we intent to reproduce here is that in this case, if the user taps
+     onto the top of the 'apps', the event fluffing code will in fact redirect
+     the event to the 'dialer' iframe. In practice, this is bug 921928 where
+     during a call the user wants to place a second call, and while typing the
+     phone number, wants to tap onto the 'delete' key to erase a digit, but ends
+     tapping and activating the dialer.
+   */
+  var dialer = document.createElement('iframe');
+  dialer.id = 'dialer';
+  dialer.src = '';
+  // Force OOP
+  dialer.setAttribute('mozbrowser', 'true');
+  dialer.setAttribute('remote', 'true');
+  document.body.appendChild(dialer);
+
+  var apps = document.createElement('iframe');
+  apps.id = 'apps';
+  apps.src = 'bug921928_event_target_iframe_apps_oop.html';
+  // Force OOP
+  apps.setAttribute('mozbrowser', 'true');
+  apps.setAttribute('remote', 'true');
+  document.body.appendChild(apps);
+
+  var handleEvent = function(event) {
+    eventTarget = event.target;
+
+    // We draw a small red div to show where the event has tapped
+    var hit = document.createElement('div');
+    hit.style.left = (event.clientX - 1.5) + 'px';
+    hit.style.top = (event.clientY - 1.5) + 'px';
+    hit.classList.add('hit');
+    debugHit.push(hit);
+  };
+
+  // In real life, the 'dialer' has a 'mousedown', so we mimic one too,
+  // to reproduce the same behavior
+  dialer.addEventListener('mousedown', function(e) {});
+
+  // This event listener is just here to record what iframe has been hit,
+  // and sets the 'eventTarget' to the iframe's id value so that the
+  // testMouseClick() code can correctly check. We cannot add it on the
+  // 'apps' otherwise it will alter the behavior of the test.
+  document.addEventListener('mousedown', handleEvent);
+
+  // In the following, the coordinates are relative to the iframe
+
+  // First, we check that tapping onto the 'dialer' correctly triggers the
+  // dialer.
+  testMouseClick("dialer", 20, 1, "dialer", "correct hit on dialer with mouse input");
+  testMouseClick("dialer", 20, 1, "dialer", "correct hit on dialer with touch input", {
+    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+  });
+
+  // Now this is it: we tap inside 'apps', but very close to the border between
+  // 'apps' and 'dialer'. Without the fix from this bug, this test will fail.
+  testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for mouse input");
+  testMouseClick("apps", 20, 1, "apps", "apps <iframe mozbrowser remote> hit for touch input", {
+    inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH
+  });
+
+  // Show small red spots of where the click happened
+  // showDebug();
+
+  endTest();
+}
+
+function runTest() {
+  setupTest(execTest);
+}
+
+addEventListener('load', function() { SimpleTest.executeSoon(runTest); });
+</script>
+</body>
+</html>
--- a/layout/reftests/forms/input/color/custom-style-1.html
+++ b/layout/reftests/forms/input/color/custom-style-1.html
@@ -1,11 +1,10 @@
 <!DOCTYPE html>
 <html>
-  <link rel='stylesheet' type='text/css' href='testcase-style.css'>
   <style>
     input[type="color"] {
       -moz-appearance: button;
     }
     input[type="color"]::-moz-color-swatch {
       margin-top: 3px;
       margin-bottom: 3px;
     }
--- a/layout/reftests/forms/input/color/input-color-1.html
+++ b/layout/reftests/forms/input/color/input-color-1.html
@@ -1,10 +1,9 @@
 <!DOCTYPE html>
 <html>
-  <link rel='stylesheet' type='text/css' href='testcase-style.css'>
   <body>
     <input type="color" />
     <input type="color" value="#000000" />
     <input type="color" value="#00ff00" />
     <input type="color" value="#123456" />
   </body>
 </html>
--- a/layout/reftests/forms/input/color/reference-style.css
+++ b/layout/reftests/forms/input/color/reference-style.css
@@ -1,21 +1,9 @@
-button.input-color {
-  /* For now, input[type="color"] is styled like a textfield, because it takes
-     the default 'input' styles in forms.css. Once we're ready to enable it by
-     default, that will change (and so should these styles here). */ 
-  -moz-appearance: textfield;
-  padding: 1px 0px 1px 0px;
-}
-button.input-color::-moz-focus-inner {
- padding: 0;
- border: 0;
-}
-
 div.input-color-swatch {
   /* This should match the styling for ::-moz-color-swatch in forms.css. */
   width: 100%;
   height: 100%;
-  min-width: 50px;
-  min-height: 1em;
+  min-width: 40px;
+  min-height: 15px;
   display: block;
   background-color:#000000; /* default color for input type color */
 }
--- a/layout/reftests/forms/input/color/reftest.list
+++ b/layout/reftests/forms/input/color/reftest.list
@@ -1,7 +1,13 @@
+# Simple test. Should fail on platforms where input type color isn't activated
+# yet. Missing platforms are B2G (bug 875751), Android (bug 875750) and Metro
+# (bug 895464).
+fails-if(B2G||Android) == input-color-1.html input-color-1-ref.html
+
 default-preferences pref(dom.forms.color,true)
 
-fails-if(B2G) == input-color-1.html input-color-1-ref.html # bug 928877
-fails-if(B2G) == margin-padding-1.html margin-padding-1-ref.html # bug 928877
+# Despite the "default-preferences" line above, B2G and Android are still
+# excluded from some style in forms.css, which makes the following tests fail.
+fails-if(B2G||Android) == margin-padding-1.html margin-padding-1-ref.html
 == block-invalidate-1.html block-invalidate-1-ref.html
-fails-if(B2G) == transformations-1.html transformations-1-ref.html # bug 928877
-fails-if(B2G) == custom-style-1.html custom-style-1-ref.html # bug 928877
+fails-if(B2G||Android) == transformations-1.html transformations-1-ref.html
+fails-if(B2G||Android) == custom-style-1.html custom-style-1-ref.html
deleted file mode 100644
--- a/layout/reftests/forms/input/color/testcase-style.css
+++ /dev/null
@@ -1,17 +0,0 @@
-input[type=color] {
-  /* This matches the "padding" declaration for 'input' in forms.css, but we
-     need to specify it here as well in order for the testcases to match the
-     reference cases' renderings on Windows. This is because
-     nsNativeThemeWin.cpp checks HasAuthorSpecifiedRules() when deciding
-     whether to apply some bonus theme-dependent widget padding. (And that
-     function only considers *author* style rules - not forms.css.) So, to make
-     sure the testcase and reference case get equivalent amounts of bonus
-     padding, we need to specify an *author*-level declaration for "padding"
-     for any testcase whose reference case has such a declaration.
-
-     Ultimately, when we pref on input[type="color"] by default, we can just
-     ensure that it uses the same padding as <button> in forms.css, at which
-     point we can drop the "padding" declaration from the testcases and the
-     reference cases (and probably drop this file altogether). */
-  padding: 1px 0px 1px 0px;
-}
--- a/layout/reftests/forms/input/color/transformations-1.html
+++ b/layout/reftests/forms/input/color/transformations-1.html
@@ -1,11 +1,10 @@
 <!DOCTYPE html>
 <html>
-  <link rel='stylesheet' type='text/css' href='testcase-style.css'>
   <style>
     input[type=color]:nth-child(1) { -moz-transform: matrix(1, -0.2, 0, 1, 0, 0); }
     input[type=color]:nth-child(2) { -moz-transform: translateX(15em) matrix(1, 0, 0.6, 1, 0, 0); }
     input[type=color]:nth-child(3) { -moz-transform: rotate(30deg); }
     input[type=color]:nth-child(4) { -moz-transform: scale(2, 4); }
     input[type=color]:nth-child(5) { -moz-transform: scale(0.1, 0.4); }
     input[type=color]:nth-child(6) { -moz-transform: scale(1, 0.4); }
     input[type=color]:nth-child(7) { -moz-transform: scale(0.1, 1); }
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -5,16 +5,22 @@
 /** 
   Styles for old GFX form widgets
  **/ 
  
 
 @namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */
 @namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
 
+%ifdef ANDROID
+%define INPUT_TYPE_COLOR_UNSUPPORTED
+%elifdef MOZ_WIDGET_GONK
+%define INPUT_TYPE_COLOR_UNSUPPORTED
+%endif
+
 *|*::-moz-fieldset-content {
   display: block;
   unicode-bidi: inherit;
   text-overflow: inherit;
   overflow: inherit;
   padding: inherit;
   position: inherit;
   height: 100%;   /* Need this so percentage heights of kids work right */
@@ -451,18 +457,18 @@ input[type="file"] > button[type="button
   letter-spacing: inherit;
   cursor: inherit;
 }
 
 /* colored part of the color selector button */
 input[type="color"]::-moz-color-swatch {
   width: 100%;
   height: 100%;
-  min-width: 50px;
-  min-height: 1em;
+  min-width: 40px;
+  min-height: 15px;
   margin-left: auto;
   margin-right: auto;
   display: block;
 }
 
 /* Try to make RTL <input type='file'> look nicer. */
 /* TODO: use text-align: match-parent when bug 645642 is fixed. */
 input[type="file"]:-moz-dir(rtl) > xul|label {
@@ -533,38 +539,48 @@ input[type="radio"]:hover:active {
   border-style: inset !important;
 }
 
 /* buttons */
 
 /* Note: Values in nsNativeTheme IsWidgetStyled function 
    need to match button background/border values here */
 
-/* TODO: Once we're getting ready to turn on 'dom.forms.color' by default, we
-   probably want to add input[type="color"] to this selector list, so that it
-   gets the same styling as other form buttons. */
-button, 
+/* Non text-related properties for buttons: these ones are shared with
+   input[type="color"] */
+button,
+%ifndef INPUT_TYPE_COLOR_UNSUPPORTED
+input[type="color"],
+%endif
 input[type="reset"],
 input[type="button"],
-input[type="submit"] { 
+input[type="submit"] {
   -moz-appearance: button;
   /* The sum of border-top, border-bottom, padding-top, padding-bottom
      must be the same here, for text inputs, and for <select>.  For
      buttons, make sure to include the -moz-focus-inner border/padding. */
   padding: 0px 6px 0px 6px;
   border: 2px outset ButtonFace;
   background-color: ButtonFace;
+  cursor: default;
+  -moz-box-sizing: border-box;
+  -moz-user-select: none;
+  -moz-binding: none;
+}
+
+/* Text-related properties for buttons: these ones are not shared with
+   input[type="color"] */
+button,
+input[type="reset"],
+input[type="button"],
+input[type="submit"] {
   color: ButtonText; 
   font: -moz-button;
   line-height: normal;
   white-space: pre;
-  cursor: default;
-  -moz-box-sizing: border-box;
-  -moz-user-select: none;
-  -moz-binding: none;
   text-align: center;
   text-shadow: none;
 }
 
 button {
   /* Buttons should lay out like "normal" html, mostly */
   white-space: inherit;
   text-indent: 0;
@@ -572,65 +588,103 @@ button {
   display: inline-block;
 }
 
 *|*::-moz-button-content {
   display: block;
 }
 
 button:hover,
+%ifndef INPUT_TYPE_COLOR_UNSUPPORTED
+input[type="color"]:hover,
+%endif
 input[type="reset"]:hover,
 input[type="button"]:hover,
 input[type="submit"]:hover {
   background-color: -moz-buttonhoverface;
+}
+
+button:hover,
+input[type="reset"]:hover,
+input[type="button"]:hover,
+input[type="submit"]:hover {
   color: -moz-buttonhovertext;
 }
 
 button:active:hover,
+%ifndef INPUT_TYPE_COLOR_UNSUPPORTED
+input[type="color"]:active:hover,
+%endif
+input[type="reset"]:active:hover,
+input[type="button"]:active:hover,
+input[type="submit"]:active:hover {
+  padding: 0px 5px 0px 7px;
+  border-style: inset;
+  background-color: ButtonFace;
+}
+
+button:active:hover,
 input[type="reset"]:active:hover,
 input[type="button"]:active:hover,
 input[type="submit"]:active:hover {
-  padding: 0px 5px 0px 7px;
-  border-style: inset;
-  background-color: ButtonFace;
   color: ButtonText;
 }
 
 button::-moz-focus-inner,
+%ifndef INPUT_TYPE_COLOR_UNSUPPORTED
+input[type="color"]::-moz-focus-inner,
+%endif
 input[type="reset"]::-moz-focus-inner,
 input[type="button"]::-moz-focus-inner,
 input[type="submit"]::-moz-focus-inner,
 input[type="file"] > button[type="button"]::-moz-focus-inner {
   padding: 0px 2px 0px 2px;
   border: 1px dotted transparent;
 }
 
 button:-moz-focusring::-moz-focus-inner,
+%ifndef INPUT_TYPE_COLOR_UNSUPPORTED
+input[type="color"]:-moz-focusring::-moz-focus-inner,
+%endif
 input[type="reset"]:-moz-focusring::-moz-focus-inner,
 input[type="button"]:-moz-focusring::-moz-focus-inner,
 input[type="submit"]:-moz-focusring::-moz-focus-inner,
 input[type="file"] > button[type="button"]:-moz-focusring::-moz-focus-inner {
   border-color: ButtonText;
 }
 
 button:disabled:active, button:disabled,
+%ifndef INPUT_TYPE_COLOR_UNSUPPORTED
+input[type="color"]:disabled:active,
+input[type="color"]:disabled,
+%endif
 input[type="reset"]:disabled:active,
 input[type="reset"]:disabled,
 input[type="button"]:disabled:active,
 input[type="button"]:disabled,
 select:disabled > button,
 select:disabled > button,
 input[type="submit"]:disabled:active,
 input[type="submit"]:disabled {
   /* The sum of border-top, border-bottom, padding-top, padding-bottom
      must be the same here and for text inputs */
   padding: 0px 6px 0px 6px;
   border: 2px outset ButtonFace;
+  cursor: inherit; 
+}
+
+input[type="reset"]:disabled:active,
+input[type="reset"]:disabled,
+input[type="button"]:disabled:active,
+input[type="button"]:disabled,
+select:disabled > button,
+select:disabled > button,
+input[type="submit"]:disabled:active,
+input[type="submit"]:disabled {
   color: GrayText;
-  cursor: inherit; 
 }
 
  /*
   * Make form controls inherit 'unicode-bidi' transparently as required by
   *  their various anonymous descendants and pseudo-elements:
   *
   * <textarea> and <input type="text">:
   *  inherit into the XULScroll frame with class 'anonymous-div' which is a
deleted file mode 100644
--- a/media/mtransport/third_party/Makefile.in
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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/.
-
-
-NO_SUBMAKEFILES_RULE = 1
deleted file mode 100644
--- a/media/webrtc/Makefile.in
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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/.
-
-# These Makefiles don't have corresponding Makefile.ins
-NO_SUBMAKEFILES_RULE = 1
--- a/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
+++ b/media/webrtc/trunk/tools/gyp/pylib/gyp/generator/mozmake.py
@@ -34,19 +34,16 @@ topsrcdir	= %(topsrcdir)s
 srcdir          = %(srcdir)s
 VPATH           = %(srcdir)s
 
 EXTERNALLY_MANAGED_MAKE_FILE := 1
 
 """
 
 COMMON_FOOTER = """
-# Skip rules that deal with regenerating Makefiles from Makefile.in files.
-NO_MAKEFILE_RULE = 1
-NO_SUBMAKEFILES_RULE = 1
 
 include %(common_mk_path)s
 """
 
 COMMON_MK = """# This file was generated by mozmake.py. Do not edit it directly.
 ifndef COMMON_MK_INCLUDED
 COMMON_MK_INCLUDED := 1
 
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -159,16 +159,19 @@ pref("findhelper.autozoom", true);
 pref("browser.formfill.enable", true);
 
 /* spellcheck */
 pref("layout.spellcheckDefault", 0);
 
 /* new html5 forms */
 pref("dom.experimental_forms", true);
 pref("dom.forms.number", true);
+// Don't enable <input type=color> yet as we don't have a color picker
+// implemented for Android (bug 875750)
+pref("dom.forms.color", false);
 
 /* extension manager and xpinstall */
 pref("xpinstall.whitelist.add", "addons.mozilla.org");
 pref("xpinstall.whitelist.add.180", "marketplace.firefox.com");
 
 pref("extensions.enabledScopes", 1);
 pref("extensions.autoupdate.enabled", true);
 pref("extensions.autoupdate.interval", 86400);
--- a/mobile/android/base/db/LocalBrowserDB.java
+++ b/mobile/android/base/db/LocalBrowserDB.java
@@ -1156,36 +1156,28 @@ public class LocalBrowserDB implements B
         final long now = System.currentTimeMillis();
         values.put(Bookmarks.TITLE, title);
         values.put(Bookmarks.URL, url);
         values.put(Bookmarks.PARENT, Bookmarks.FIXED_PINNED_LIST_ID);
         values.put(Bookmarks.DATE_MODIFIED, now);
         values.put(Bookmarks.POSITION, position);
         values.put(Bookmarks.IS_DELETED, 0);
 
-        // If this site is already pinned, unpin it
-        cr.delete(mBookmarksUriWithProfile,
-                  Bookmarks.PARENT + " == ? AND " + Bookmarks.URL + " == ?",
-                  new String[] {
-                      String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID),
-                      url
-                  });
-
-        // If something is already pinned in this spot update it
-        int updated = cr.update(mBookmarksUriWithProfile,
-                                values,
-                                Bookmarks.POSITION + " = ? AND " +
-                                Bookmarks.PARENT + " = ?",
-                                new String[] { Integer.toString(position),
-                                               String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) });
-
-        // Otherwise just insert a new item
-        if (updated == 0) {
-            cr.insert(mBookmarksUriWithProfile, values);
-        }
+        // We do an update-and-replace here without deleting any existing pins for the given URL.
+        // That means if the user pins a URL, then edits another thumbnail to use the same URL,
+        // we'll end up with two pins for that site. This is the intended behavior, which
+        // incidentally saves us a delete query.
+        Uri uri = mBookmarksUriWithProfile.buildUpon()
+                .appendQueryParameter(BrowserContract.PARAM_INSERT_IF_NEEDED, "true").build();
+        cr.update(uri,
+                  values,
+                  Bookmarks.POSITION + " = ? AND " +
+                  Bookmarks.PARENT + " = ?",
+                  new String[] { Integer.toString(position),
+                                 String.valueOf(Bookmarks.FIXED_PINNED_LIST_ID) });
     }
 
     @Override
     public Cursor getPinnedSites(ContentResolver cr, int limit) {
         return cr.query(bookmarksUriWithLimit(limit),
                         new String[] { Bookmarks._ID,
                                        Bookmarks.URL,
                                        Bookmarks.TITLE,
--- a/mobile/android/components/SessionStore.idl
+++ b/mobile/android/components/SessionStore.idl
@@ -9,17 +9,17 @@ interface nsIDOMNode;
 
 /**
  * nsISessionStore keeps track of the current browsing state.
  *
  * The nsISessionStore API operates mostly on browser windows and the browser
  * tabs contained in them.
  */
 
-[scriptable, uuid(15152edf-6c99-4277-9020-076be4653c69)]
+[scriptable, uuid(fe116b56-0226-4562-b52a-a623dad07ead)]
 interface nsISessionStore : nsISupports
 {
   /**
    * Get the current browsing state.
    * @returns a JSON string representing the session state.
    */
   AString getBrowserState();
 
--- a/mobile/android/config/mozconfigs/android-armv6/release
+++ b/mobile/android/config/mozconfigs/android-armv6/release
@@ -1,32 +1,18 @@
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
-# Build Fennec
-ac_add_options --enable-application=mobile/android
-
-# Android
 ac_add_options --target=arm-linux-androideabi
 ac_add_options --with-arch=armv6
 
-if test `uname -m` = 'x86_64'; then
-  ac_add_options --with-android-ndk="$topsrcdir/android-ndk"
-  ac_add_options --with-android-sdk="$topsrcdir/android-sdk-linux/platforms/android-16"
-else
-  ac_add_options --with-android-ndk="/tools/android-ndk-r8c"
-  ac_add_options --with-android-sdk="/tools/android-sdk-r16/platforms/android-16"
-fi
+export MOZ_PKG_SPECIAL=armv6
 
-ac_add_options --with-android-gnu-compiler-version=4.7
-ac_add_options --with-android-version=9
-ac_add_options --with-system-zlib
+ac_add_options --with-branding=mobile/android/branding/beta
+
 ac_add_options --enable-updater
-ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
 
 export JAVA_HOME=/tools/jdk6
 export MOZILLA_OFFICIAL=1
 export MOZ_TELEMETRY_REPORTING=1
-export MOZ_PKG_SPECIAL=armv6
 
 ac_add_options --enable-official-branding
-ac_add_options --with-branding=mobile/android/branding/beta
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android-x86/release
+++ b/mobile/android/config/mozconfigs/android-x86/release
@@ -1,30 +1,16 @@
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
-# Build Fennec
-ac_add_options --enable-application=mobile/android
-
 # Android
 ac_add_options --target=i386-linux-android
 
-if test `uname -m` = 'x86_64'; then
-  ac_add_options --with-android-ndk="$topsrcdir/android-ndk"
-  ac_add_options --with-android-sdk="$topsrcdir/android-sdk-linux/platforms/android-16"
-else
-  ac_add_options --with-android-ndk="/tools/android-ndk-r8c"
-  ac_add_options --with-android-sdk="/tools/android-sdk-r16/platforms/android-16"
-fi
+ac_add_options --enable-updater
 
-ac_add_options --with-android-gnu-compiler-version=4.7
-ac_add_options --with-android-version=9
-ac_add_options --with-system-zlib
-ac_add_options --enable-updater
-ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
+ac_add_options --with-branding=mobile/android/branding/beta
 
 export JAVA_HOME=/tools/jdk6
 export MOZILLA_OFFICIAL=1
 export MOZ_TELEMETRY_REPORTING=1
 
 ac_add_options --enable-official-branding
-ac_add_options --with-branding=mobile/android/branding/beta
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/config/mozconfigs/android/release
+++ b/mobile/android/config/mozconfigs/android/release
@@ -1,30 +1,13 @@
 . "$topsrcdir/mobile/android/config/mozconfigs/common"
 
-# Build Fennec
-ac_add_options --enable-application=mobile/android
-
-# Android
-ac_add_options --target=arm-linux-androideabi
+ac_add_options --enable-updater
 
-if test `uname -m` = 'x86_64'; then
-  ac_add_options --with-android-ndk="$topsrcdir/android-ndk"
-  ac_add_options --with-android-sdk="$topsrcdir/android-sdk-linux/platforms/android-16"
-else
-  ac_add_options --with-android-ndk="/tools/android-ndk-r8c"
-  ac_add_options --with-android-sdk="/tools/android-sdk-r16/platforms/android-16"
-fi
-
-ac_add_options --with-android-gnu-compiler-version=4.7
-ac_add_options --with-android-version=9
-ac_add_options --with-system-zlib
-ac_add_options --enable-updater
-ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
+ac_add_options --with-branding=mobile/android/branding/beta
 
 export JAVA_HOME=/tools/jdk6
 export MOZILLA_OFFICIAL=1
 export MOZ_TELEMETRY_REPORTING=1
 
 ac_add_options --enable-official-branding
-ac_add_options --with-branding=mobile/android/branding/beta
 
 . "$topsrcdir/mobile/android/config/mozconfigs/common.override"
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -382,18 +382,16 @@
 @BINPATH@/components/nsPrompter.manifest
 @BINPATH@/components/nsPrompter.js
 @BINPATH@/components/TelemetryPing.js
 @BINPATH@/components/TelemetryPing.manifest
 @BINPATH@/components/Webapps.js
 @BINPATH@/components/Webapps.manifest
 @BINPATH@/components/AppsService.js
 @BINPATH@/components/AppsService.manifest
-@BINPATH@/components/AppProtocolHandler.js
-@BINPATH@/components/AppProtocolHandler.manifest
 
 @BINPATH@/components/Push.js
 @BINPATH@/components/Push.manifest
 
 @BINPATH@/components/SystemMessageInternal.js
 @BINPATH@/components/SystemMessageManager.js
 @BINPATH@/components/SystemMessageManager.manifest
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -848,18 +848,19 @@ pref("dom.send_after_paint_to_content", 
 pref("dom.min_timeout_value", 4);
 // And for background windows
 pref("dom.min_background_timeout_value", 1000);
 
 // Don't use new input types
 pref("dom.experimental_forms", false);
 pref("dom.forms.number", false);
 
-// Don't enable <input type=color> yet:
-pref("dom.forms.color", false);
+// Enable <input type=color> by default. It will be turned off for remaining
+// platforms which don't have a color picker implemented yet.
+pref("dom.forms.color", true);
 
 // Enables system messages and activities
 pref("dom.sysmsg.enabled", false);
 
 // Enable pre-installed applications.
 pref("dom.webapps.useCurrentProfile", false);
 
 // Parsing perf prefs. For now just mimic what the old code did.
--- a/moz.build
+++ b/moz.build
@@ -1,15 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-CONFIGURE_SUBST_FILES += ['tools/update-packaging/Makefile']
+CONFIGURE_SUBST_FILES += [
+    'mozilla-config.h',
+    'tools/update-packaging/Makefile',
+]
 
 if CONFIG['ENABLE_CLANG_PLUGIN']:
   add_tier_dir('base', 'build/clang-plugin', external=True)
 
 add_tier_dir('base', ['config', 'build', 'probes', 'mfbt', 'python'])
 
 if not CONFIG['LIBXUL_SDK']:
     if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
--- a/netwerk/base/public/security-prefs.js
+++ b/netwerk/base/public/security-prefs.js
@@ -1,14 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 pref("security.tls.version.min", 0);
-pref("security.tls.version.max", 1);
+pref("security.tls.version.max", 2);
 pref("security.enable_md5_signatures", false);
 
 pref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", false);
 pref("security.ssl.renego_unrestricted_hosts", "");
 pref("security.ssl.treat_unsafe_negotiation_as_broken", false);
 pref("security.ssl.require_safe_negotiation",  false);
 pref("security.ssl.warn_missing_rfc5746",  1);
 pref("security.ssl.enable_ocsp_stapling", true);
--- a/netwerk/build/Makefile.in
+++ b/netwerk/build/Makefile.in
@@ -64,16 +64,17 @@ LOCAL_INCLUDES = \
   -I$(srcdir)/../base/src \
   -I$(srcdir)/../dns \
   -I$(srcdir)/../socket \
   -I$(srcdir)/../streamconv/src \
   -I$(srcdir)/../streamconv/converters \
   -I$(srcdir)/../mime \
   -I$(srcdir)/../cache \
   -I$(srcdir)/../protocol/about \
+  -I$(srcdir)/../protocol/app \
   -I../dns \
   $(foreach d,$(filter-out about,$(NECKO_PROTOCOLS)), \
     -I$(srcdir)/../protocol/$(d)) \
   $(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
     LOCAL_INCLUDES += -I$(srcdir)/../system/win32
 endif
--- a/netwerk/build/nsNetCID.h
+++ b/netwerk/build/nsNetCID.h
@@ -609,16 +609,28 @@
 { /* fbc81170-1f69-11d3-9344-00104ba0fd40 */         \
     0xfbc81170,                                      \
     0x1f69,                                          \
     0x11d3,                                          \
     {0x93, 0x44, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
 }
 
 /******************************************************************************
+ * netwerk/protocol/app/ classes
+ */
+
+#define NS_APPPROTOCOLHANDLER_CID                    \
+{ /* {B6ED3030-9999-11d3-A178-0050041CAF44} */       \
+    0xb6ed3030,                                      \
+    0x9999,                                          \
+    0x11d3,                                          \
+    {0xa1, 0x78, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \
+}
+
+/******************************************************************************
  * netwerk/protocol/data/ classes
  */
 
 #define NS_DATAPROTOCOLHANDLER_CID                   \
 { /* {B6ED3030-6183-11d3-A178-0050041CAF44} */       \
     0xb6ed3030,                                      \
     0x6183,                                          \
     0x11d3,                                          \
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -239,16 +239,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHttpDig
 #endif // !NECKO_PROTOCOL_http
 
 #include "mozilla/net/Dashboard.h"
 namespace mozilla {
 namespace net {
   NS_GENERIC_FACTORY_CONSTRUCTOR(Dashboard)
 }
 }
+#include "AppProtocolHandler.h"
 
 #ifdef NECKO_PROTOCOL_res
 // resource
 #include "nsResProtocolHandler.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsResProtocolHandler, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsResURL)
 #endif
 
@@ -768,16 +769,17 @@ NS_DEFINE_NAMED_CID(NS_ABOUT_CACHE_ENTRY
 #endif
 NS_DEFINE_NAMED_CID(NS_SOCKSSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_SOCKS4SOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_UDPSOCKETPROVIDER_CID);
 NS_DEFINE_NAMED_CID(NS_CACHESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHESERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHENAMESPACE_CID);
 NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHE_CID);
+NS_DEFINE_NAMED_CID(NS_APPPROTOCOLHANDLER_CID);
 #ifdef NECKO_COOKIES
 NS_DEFINE_NAMED_CID(NS_COOKIEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_COOKIESERVICE_CID);
 #endif
 #ifdef NECKO_WIFI
 NS_DEFINE_NAMED_CID(NS_WIFI_MONITOR_COMPONENT_CID);
 #endif
 #ifdef NECKO_PROTOCOL_data
@@ -907,16 +909,17 @@ static const mozilla::Module::CIDEntry k
 #endif
     { &kNS_SOCKSSOCKETPROVIDER_CID, false, nullptr, nsSOCKSSocketProvider::CreateV5 },
     { &kNS_SOCKS4SOCKETPROVIDER_CID, false, nullptr, nsSOCKSSocketProvider::CreateV4 },
     { &kNS_UDPSOCKETPROVIDER_CID, false, nullptr, nsUDPSocketProviderConstructor },
     { &kNS_CACHESERVICE_CID, false, nullptr, nsCacheService::Create },
     { &kNS_APPLICATIONCACHESERVICE_CID, false, nullptr, nsApplicationCacheServiceConstructor },
     { &kNS_APPLICATIONCACHENAMESPACE_CID, false, nullptr, nsApplicationCacheNamespaceConstructor },
     { &kNS_APPLICATIONCACHE_CID, false, nullptr, nsApplicationCacheConstructor },
+    { &kNS_APPPROTOCOLHANDLER_CID, false, nullptr, AppProtocolHandler::Create },
 #ifdef NECKO_COOKIES
     { &kNS_COOKIEMANAGER_CID, false, nullptr, nsICookieServiceConstructor },
     { &kNS_COOKIESERVICE_CID, false, nullptr, nsICookieServiceConstructor },
 #endif
 #ifdef NECKO_WIFI
     { &kNS_WIFI_MONITOR_COMPONENT_CID, false, nullptr, nsWifiMonitorConstructor },
 #endif
 #ifdef NECKO_PROTOCOL_data
@@ -1053,16 +1056,17 @@ static const mozilla::Module::ContractID
 #endif
     { NS_NETWORK_SOCKET_CONTRACTID_PREFIX "socks", &kNS_SOCKSSOCKETPROVIDER_CID },
     { NS_NETWORK_SOCKET_CONTRACTID_PREFIX "socks4", &kNS_SOCKS4SOCKETPROVIDER_CID },
     { NS_NETWORK_SOCKET_CONTRACTID_PREFIX "udp", &kNS_UDPSOCKETPROVIDER_CID },
     { NS_CACHESERVICE_CONTRACTID, &kNS_CACHESERVICE_CID },
     { NS_APPLICATIONCACHESERVICE_CONTRACTID, &kNS_APPLICATIONCACHESERVICE_CID },
     { NS_APPLICATIONCACHENAMESPACE_CONTRACTID, &kNS_APPLICATIONCACHENAMESPACE_CID },
     { NS_APPLICATIONCACHE_CONTRACTID, &kNS_APPLICATIONCACHE_CID },
+    { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "app", &kNS_APPPROTOCOLHANDLER_CID },
 #ifdef NECKO_COOKIES
     { NS_COOKIEMANAGER_CONTRACTID, &kNS_COOKIEMANAGER_CID },
     { NS_COOKIESERVICE_CONTRACTID, &kNS_COOKIESERVICE_CID },
 #endif
 #ifdef NECKO_WIFI
     { NS_WIFI_MONITOR_CONTRACTID, &kNS_WIFI_MONITOR_COMPONENT_CID },
 #endif
 #ifdef NECKO_PROTOCOL_data
--- a/netwerk/moz.build
+++ b/netwerk/moz.build
@@ -31,8 +31,10 @@ PARALLEL_DIRS += ['locales']
 
 if CONFIG['MOZ_DASH']:
     PARALLEL_DIRS += ['dash']
 
 DIRS += ['build']
 TEST_TOOL_DIRS += ['test']
 
 MODULE = 'necko'
+
+CONFIGURE_DEFINE_FILES += ['necko-config.h']
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/app/AppProtocolHandler.cpp
@@ -0,0 +1,423 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set expandtab ts=2 sw=2 sts=2 cin: */
+/* 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 "AppProtocolHandler.h"
+#include "nsBaseChannel.h"
+#include "nsJARChannel.h"
+#include "nsNetCID.h"
+#include "nsIAppsService.h"
+#include "nsCxPusher.h"
+#include "nsXULAppAPI.h"
+
+/**
+  * This dummy channel implementation only provides enough functionality
+  * to return a fake 404 error when the caller asks for an app:// URL
+  * containing an unknown appId.
+  */
+class DummyChannel : public nsIJARChannel
+                          , nsRunnable
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIREQUEST
+  NS_DECL_NSICHANNEL
+  NS_DECL_NSIJARCHANNEL
+
+  DummyChannel();
+
+  NS_IMETHODIMP Run();
+
+private:
+  bool                        mPending;
+  uint32_t                    mSuspendCount;
+  nsCOMPtr<nsISupports>       mListenerContext;
+  nsCOMPtr<nsIStreamListener> mListener;
+  nsCOMPtr<nsILoadGroup>      mLoadGroup;
+  nsLoadFlags                 mLoadFlags;
+};
+
+NS_IMPL_ISUPPORTS3(DummyChannel, nsIRequest, nsIChannel, nsIJARChannel)
+
+DummyChannel::DummyChannel() : mPending(false)
+                             , mSuspendCount(0)
+                             , mLoadFlags(LOAD_NORMAL)
+{
+}
+
+NS_IMETHODIMP DummyChannel::GetName(nsACString &result)
+{
+  result = "dummy_app_channel";
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::GetStatus(nsresult *aStatus)
+{
+  *aStatus = NS_ERROR_FILE_NOT_FOUND;
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::IsPending(bool *aResult)
+{
+  *aResult = mPending;
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::Suspend()
+{
+  mSuspendCount++;
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::Resume()
+{
+  if (mSuspendCount <= 0) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (--mSuspendCount == 0) {
+    NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::Open(nsIInputStream**)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext)
+{
+  mListener = aListener;
+  mListenerContext = aContext;
+  mPending = true;
+
+  if (mLoadGroup) {
+    mLoadGroup->AddRequest(this, aContext);
+  }
+
+  if (mSuspendCount == 0) {
+    NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
+  }
+
+  return NS_OK;
+}
+
+// nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into
+// a 404 error.
+NS_IMETHODIMP DummyChannel::GetIsUnsafe(bool *aResult)
+{
+  *aResult = false;
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::SetAppURI(nsIURI *aURI)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::Run()
+{
+  nsresult rv = mListener->OnStartRequest(this, mListenerContext);
+  NS_ENSURE_SUCCESS(rv, rv);
+  mPending = false;
+  rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (mLoadGroup) {
+    mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
+  }
+
+  mListener = nullptr;
+  mListenerContext = nullptr;
+  rv = SetNotificationCallbacks(nullptr);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::Cancel(nsresult)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
+{
+  *aLoadGroup = mLoadGroup;
+  NS_IF_ADDREF(*aLoadGroup);
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
+{
+  mLoadGroup = aLoadGroup;
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
+{
+  *aLoadFlags = mLoadFlags;
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+  mLoadFlags = aLoadFlags;
+  return NS_OK;
+}
+
+NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI**)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI*)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetOwner(nsISupports**)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetOwner(nsISupports*)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor**)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor*)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports**)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetContentType(nsACString&)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetContentType(const nsACString&)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetContentCharset(nsACString&)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetContentCharset(const nsACString&)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetContentLength(int64_t*)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetContentLength(int64_t)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetContentDisposition(uint32_t*)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetContentDisposition(uint32_t)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetURI(nsIURI**)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetContentDispositionFilename(nsAString&)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::SetContentDispositionFilename(nsAString const &)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/**
+  * app:// protocol implementation.
+  */
+
+AppProtocolHandler::AppProtocolHandler() {
+}
+
+AppProtocolHandler::~AppProtocolHandler() {
+  mAppInfoCache.Clear();
+}
+
+NS_IMPL_ISUPPORTS1(AppProtocolHandler, nsIProtocolHandler)
+
+/* static */
+nsresult
+AppProtocolHandler::Create(nsISupports* aOuter,
+                           const nsIID& aIID,
+                           void* *aResult)
+{
+  // Instantiate the service here since that intializes gJarHandler, which we
+  // use indirectly (via our new JarChannel) in NewChannel.
+  nsCOMPtr<nsIProtocolHandler> jarInitializer(
+    do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar"));
+  AppProtocolHandler* ph = new AppProtocolHandler();
+  if (ph == nullptr) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+  NS_ADDREF(ph);
+  nsresult rv = ph->QueryInterface(aIID, aResult);
+  NS_RELEASE(ph);
+  return rv;
+}
+
+NS_IMETHODIMP
+AppProtocolHandler::GetScheme(nsACString &aResult)
+{
+  aResult.AssignLiteral("app");
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AppProtocolHandler::GetDefaultPort(int32_t *aResult)
+{
+  // No ports for the app protocol.
+  *aResult = -1;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AppProtocolHandler::GetProtocolFlags(uint32_t *aResult)
+{
+  *aResult = URI_NOAUTH |
+             URI_DANGEROUS_TO_LOAD |
+             URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AppProtocolHandler::NewURI(const nsACString &aSpec,
+                           const char *aCharset, // ignore charset info
+                           nsIURI *aBaseURI,
+                           nsIURI **result)
+{
+  nsresult rv;
+  nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  url.forget(result);
+  return NS_OK;
+}
+
+// We map app://ABCDEF/path/to/file.ext to
+// jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext
+NS_IMETHODIMP
+AppProtocolHandler::NewChannel(nsIURI* aUri, nsIChannel* *aResult)
+{
+  NS_ENSURE_ARG_POINTER(aUri);
+  nsRefPtr<nsJARChannel> channel = new nsJARChannel();
+
+  nsAutoCString host;
+  nsresult rv = aUri->GetHost(host);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString fileSpec;
+  nsCOMPtr<nsIURL> url = do_QueryInterface(aUri);
+  rv = url->GetFilePath(fileSpec);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mozilla::dom::AppInfo *appInfo;
+
+  if (!mAppInfoCache.Get(host, &appInfo)) {
+    nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
+    if (!appsService) {
+      return NS_ERROR_FAILURE;
+    }
+
+    mozilla::AutoSafeJSContext cx;
+    JS::RootedValue jsInfo(cx);
+    rv = appsService->GetAppInfo(NS_ConvertUTF8toUTF16(host), jsInfo.address());
+    if (NS_FAILED(rv) || !jsInfo.isObject()) {
+      // Return a DummyChannel.
+      printf_stderr("!! Creating a dummy channel for %s (no appInfo)\n", host.get());
+      NS_IF_ADDREF(*aResult = new DummyChannel());
+      return NS_OK;
+    }
+
+    appInfo = new mozilla::dom::AppInfo();
+    JSAutoCompartment ac(cx, &jsInfo.toObject());
+    if (!appInfo->Init(cx, jsInfo) || appInfo->mPath.IsEmpty()) {
+      // Return a DummyChannel.
+      printf_stderr("!! Creating a dummy channel for %s (invalid appInfo)\n", host.get());
+      NS_IF_ADDREF(*aResult = new DummyChannel());
+      return NS_OK;
+    }
+    mAppInfoCache.Put(host, appInfo);
+  }
+
+  bool noRemote = (appInfo->mIsCoreApp ||
+                   XRE_GetProcessType() == GeckoProcessType_Default);
+
+  // In-parent and CoreApps can directly access files, so use jar:file://
+  nsAutoCString jarSpec(noRemote ? "jar:file://"
+                                 : "jar:remoteopenfile://");
+  jarSpec += NS_ConvertUTF16toUTF8(appInfo->mPath) +
+             NS_LITERAL_CSTRING("/application.zip!") +
+             fileSpec;
+
+  nsCOMPtr<nsIURI> jarURI;
+  rv = NS_NewURI(getter_AddRefs(jarURI),
+                 jarSpec, nullptr, nullptr);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = channel->Init(jarURI);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = channel->SetAppURI(aUri);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = channel->SetOriginalURI(aUri);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  channel.forget(aResult);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AppProtocolHandler::AllowPort(int32_t aPort, const char *aScheme, bool *aRetval)
+{
+  // No port allowed for this scheme.
+  *aRetval = false;
+  return NS_OK;
+}
+
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/app/AppProtocolHandler.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim:set expandtab ts=4 sw=4 sts=4 cin: */
+/* 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 AppProtocolHandler_
+#define AppProtocolHandler_
+
+#include "nsIProtocolHandler.h"
+#include "nsClassHashtable.h"
+#include "mozilla/dom/AppInfoBinding.h"
+
+class AppProtocolHandler : public nsIProtocolHandler
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  // nsIProtocolHandler methods:
+  NS_DECL_NSIPROTOCOLHANDLER
+
+  // AppProtocolHandler methods:
+  AppProtocolHandler();
+  virtual ~AppProtocolHandler();
+
+  // Define a Create method to be used with a factory:
+  static nsresult Create(nsISupports* aOuter,
+                         const nsIID& aIID,
+                         void* *aResult);
+
+private:
+  nsClassHashtable<nsCStringHashKey, mozilla::dom::AppInfo> mAppInfoCache;
+};
+
+#endif /* AppProtocolHandler_ */
deleted file mode 100644
--- a/netwerk/protocol/app/AppProtocolHandler.js
+++ /dev/null
@@ -1,197 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-const Cc = Components.classes;
-const Ci = Components.interfaces;
-const Cu = Components.utils;
-const Cr = Components.results;
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "appsService",
-                                   "@mozilla.org/AppsService;1",
-                                   "nsIAppsService");
-
-function AppProtocolHandler() {
-  this._appInfo = [];
-  this._runningInParent = Cc["@mozilla.org/xre/runtime;1"]
-                            .getService(Ci.nsIXULRuntime)
-                            .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-}
-
-AppProtocolHandler.prototype = {
-  classID: Components.ID("{b7ad6144-d344-4687-b2d0-b6b9dce1f07f}"),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),
-
-  scheme: "app",
-  defaultPort: -1,
-  // Don't allow loading from other protocols, and only from app:// if webapps is granted
-  protocolFlags: Ci.nsIProtocolHandler.URI_NOAUTH |
-                 Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
-                 Ci.nsIProtocolHandler.URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM,
-
-  getAppInfo: function app_phGetAppInfo(aId) {
-
-    if (!this._appInfo[aId]) {
-      this._appInfo[aId] = appsService.getAppInfo(aId);
-    }
-    return this._appInfo[aId];
-  },
-
-  newURI: function app_phNewURI(aSpec, aOriginCharset, aBaseURI) {
-    let uri = Cc["@mozilla.org/network/standard-url;1"]
-              .createInstance(Ci.nsIStandardURL);
-    uri.init(Ci.nsIStandardURL.URLTYPE_STANDARD, -1, aSpec, aOriginCharset,
-             aBaseURI);
-    return uri.QueryInterface(Ci.nsIURI);
-  },
-
-  newChannel: function app_phNewChannel(aURI) {
-    // We map app://ABCDEF/path/to/file.ext to
-    // jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext
-    let url = aURI.QueryInterface(Ci.nsIURL);
-    let appId = aURI.host;
-    let fileSpec = url.filePath;
-
-    // Build a jar channel and masquerade as an app:// URI.
-    let appInfo = this.getAppInfo(appId);
-    if (!appInfo) {
-      // That should not happen, so dump() inconditionnally.
-      // We create a dummy channel instead of throwing to let the
-      // downstream user get a 404 error.
-      dump("!! got no appInfo for " + appId + "\n");
-      return new DummyChannel();
-    }
-
-    let uri;
-    if (this._runningInParent || appInfo.isCoreApp) {
-      // In-parent and CoreApps can directly access files, so use jar:file://
-      uri = "jar:file://" + appInfo.path + "/application.zip!" + fileSpec;
-    } else {
-      // non-CoreApps in child need to ask parent for file handle, use jar:ipcfile://
-      uri = "jar:remoteopenfile://" + appInfo.path + "/application.zip!" + fileSpec;
-    }
-    let channel = Services.io.newChannel(uri, null, null);
-    channel.QueryInterface(Ci.nsIJARChannel).setAppURI(aURI);
-    channel.QueryInterface(Ci.nsIChannel).originalURI = aURI;
-
-    return channel;
-  },
-
-  allowPort: function app_phAllowPort(aPort, aScheme) {
-    return false;
-  }
-};
-
-/**
-  * This dummy channel implementation only provides enough functionality
-  * to return a fake 404 error when the caller asks for an app:// URL
-  * containing an unknown appId.
-  */
-function DummyChannel() {
-  this.originalURI = Services.io.newURI("app://unknown/nothing.html", null, null);
-  this.URI = Services.io.newURI("app://unknown/nothing.html", null, null);
-}
-
-DummyChannel.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequest,
-                                         Ci.nsIChannel,
-                                         Ci.nsIJARChannel]),
-
-  // nsIRequest
-  name: "dummy_app_channel",
-
-  isPending: function dc_isPending() {
-    return this._pending;
-  },
-
-  status: Cr.NS_ERROR_FILE_NOT_FOUND,
-
-  cancel: function dc_cancel() {
-  },
-
-  suspend: function dc_suspend() {
-    this._suspendCount++;
-  },
-
-  resume: function dc_resume() {
-    if (this._suspendCount <= 0)
-      throw Cr.NS_ERROR_UNEXPECTED;
-
-    if (--this._suspendCount == 0 && this._pending) {
-      this._dispatch();
-    }
-  },
-
-  loadGroup: null,
-  loadFlags: Ci.nsIRequest.LOAD_NORMAL,
-
-  // nsIChannel
-  owner: null,
-  notificationCallbacks: null,
-  securityInfo: null,
-  contentType: null,
-  contentCharset: null,
-  contentLength: 0,
-  contentDisposition: Ci.nsIChannel.DISPOSITION_INLINE,
-  contentDispositionFilename: "",
-
-  _pending: false,
-  _suspendCount: 0,
-  _listener: null,
-  _context: null,
-
-  open: function dc_open() {
-    return Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-
-  _dispatch: function dc_dispatch() {
-    let request = this;
-
-    Services.tm.currentThread.dispatch(
-    {
-      run: function dc_run() {
-        request._listener.onStartRequest(request, request._context);
-        request._listener.onStopRequest(request, request._context,
-                                        Cr.NS_ERROR_FILE_NOT_FOUND);
-        if (request.loadGroup) {
-          request.loadGroup.removeRequest(request, request._context,
-                                          Cr.NS_ERROR_FILE_NOT_FOUND);
-        }
-        request._pending = false;
-        request.notificationCallbacks = null;
-        request._listener = null;
-        request._context = null;
-      }
-    },
-    Ci.nsIThread.DISPATCH_NORMAL);
-  },
-
-  asyncOpen: function dc_asyncopenfunction(aListener, aContext) {
-    if (this.loadGroup) {
-      this.loadGroup.addRequest(this, aContext);
-    }
-
-    this._listener = aListener;
-    this._context = aContext;
-    this._pending = true;
-
-    if (!this._suspended) {
-      this._dispatch();
-    }
-  },
-
-  // nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into
-  // a 404 error.
-  isUnsafe: false,
-
-  setAppURI: function(aURI) {
-    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
-  }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AppProtocolHandler]);
deleted file mode 100644
--- a/netwerk/protocol/app/AppProtocolHandler.manifest
+++ /dev/null
@@ -1,3 +0,0 @@
-# AppProtocolHander.js
-component {b7ad6144-d344-4687-b2d0-b6b9dce1f07f} AppProtocolHandler.js
-contract @mozilla.org/network/protocol;1?name=app {b7ad6144-d344-4687-b2d0-b6b9dce1f07f}
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/app/Makefile.in
@@ -0,0 +1,9 @@
+#
+# 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/.
+
+LOCAL_INCLUDES = \
+  -I$(srcdir)/../../base/src \
+  -I$(srcdir)/../../../modules/libjar \
+  $(NULL)
--- a/netwerk/protocol/app/moz.build
+++ b/netwerk/protocol/app/moz.build
@@ -1,10 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-EXTRA_COMPONENTS += [
-    'AppProtocolHandler.js',
-    'AppProtocolHandler.manifest',
+MODULE = 'necko'
+
+SOURCES += [
+    'AppProtocolHandler.cpp',
 ]
+
+LIBRARY_NAME = 'nkapp_s'
+
+FAIL_ON_WARNINGS = True
+
+LIBXUL_LIBRARY = True
+
--- a/netwerk/protocol/http/HttpDataUsage.js
+++ b/netwerk/protocol/http/HttpDataUsage.js
@@ -30,18 +30,17 @@ var gDataUsage;
 function HttpDataUsage() {}
 HttpDataUsage.prototype = {
     classID: Components.ID("{6d72bfca-2747-4859-887f-6f06d4ce6787}"),
     QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
     contractID: "@mozilla.org/network/HttpDataUsage;1",
 
     _isIdleObserver: false,
     _locked : false,
-    _do_telemetry : false,
-    _idle_timeout : 60 * 3,
+    _idle_timeout : 15,
     _quanta : 86400000, // per day
 
     _logtime : new Date(),
     _ethernetRead : 0,
     _ethernetWritten : 0,
     _cellRead : 0,
     _cellWritten : 0,
 
@@ -69,34 +68,33 @@ HttpDataUsage.prototype = {
         // this isn't important enough to worry about getting a
         // runtime telemetry config change for
         if (!enabled)
             return;
 
         if (this._dataUsage == null)
             return;
 
+        Services.obs.addObserver(this, "quit-application", false);
         idleService.addIdleObserver(this, this._idle_timeout);
         this._isIdleObserver = true;
     },
     
     shutdown: function shutdown() {
-        if (this._isIdleObserver)
+        if (this._isIdleObserver) {
             idleService.removeIdleObserver(this, this._idle_timeout);
+            Services.obs.removeObserver(this, "quit-application");
+        }
         this._isIdleObserver = false;
     },
 
     sUpdateStats2: function sUpdateStats2(stream, result) {
         gDataUsage.updateStats2(stream, result);
     },
 
-    sGatherTelemetry2: function sGatherTelemetry2(stream, result) {
-        gDataUsage.gatherTelemetry2(stream, result);
-    },
-
     readCounters: function readCounters(stream, result) {
         if (Components.isSuccessCode(result)) {
             let count = stream.available();
             let data = NetUtil.readInputStreamToString(stream, count);
             var list = data.split(",");
             if (list.length == 5) {
                 this._logtime = new Date(Number(list[0]));
                 this._ethernetRead = Number(list[1]);
@@ -108,17 +106,16 @@ HttpDataUsage.prototype = {
 
         this._ethernetRead += this._dataUsage.ethernetBytesRead;
         this._ethernetWritten += this._dataUsage.ethernetBytesWritten;
         this._cellRead += this._dataUsage.cellBytesRead;
         this._cellWritten += this._dataUsage.cellBytesWritten;
         this._dataUsage.resetHttpDataUsage();
     },
 
-    // writeCounters also releases the lock
     writeCounters: function writeCounters() {
         var dataout = this._logtime.getTime().toString() + "," +
             this._ethernetRead.toString() + "," +
             this._ethernetWritten.toString() + "," +
             this._cellRead.toString() + "," +
             this._cellWritten.toString() + "\n";
 
         var buffer = new this._pipe(true, false, 4096, 1, null);
@@ -127,27 +124,25 @@ HttpDataUsage.prototype = {
         var fileOut = new this._outputStream(this._dataFile, -1, -1, 0);
 
         NetUtil.asyncCopy(buffer.inputStream, fileOut,
                           function (result) { gDataUsage.finishedWriting(); });
     },
 
     updateStats2: function updateStats2(stream, result) {
         this.readCounters(stream, result);
-        this.writeCounters();
+        this.submitTelemetry();
     },
 
-    gatherTelemetry2: function gatherTelemetry2(stream, result) {
-        this.readCounters(stream, result);
-
+    submitTelemetry: function submitTelemetry() {
         var now = new Date();
         var elapsed = now.getTime() - this._logtime.getTime();
-        // make sure we have at least 1 day of data
+        // make sure we have at least 1 day of data.. if not just write new data out
         if (elapsed < this._quanta) {
-            this.finishedWriting();
+            this.writeCounters();
             return;
         }
 
         var days = elapsed / this._quanta;
         var eInPerQuanta = Math.floor(this._ethernetRead / days);
         var eOutPerQuanta = Math.floor(this._ethernetWritten / days);
         var cInPerQuanta = Math.floor(this._cellRead / days);
         var cOutPerQuanta = Math.floor(this._cellWritten / days);
@@ -166,57 +161,42 @@ HttpDataUsage.prototype = {
 
             elapsed -= this._quanta;
             this._ethernetRead -= eInPerQuanta;
             this._ethernetWritten -= eOutPerQuanta;
             this._cellRead -= cInPerQuanta;
             this._cellWritten -= cOutPerQuanta;
         }
         this._logtime = new Date(now.getTime() - elapsed);
-        
+
+        // need to write back the decremented counters
         this.writeCounters();
     },
 
     finishedWriting : function finishedWriting() {
-        this._locked = false;
-        if (this._do_telemetry) {
-            this._do_telemetry = false;
-            this.gatherTelemetry();
-        }
+        this._locked = false; // all done
     },
 
     updateStats: function updateStats() {
         if (this._locked)
             return;
         this._locked = true;
         
         NetUtil.asyncFetch(this._dataFile, this.sUpdateStats2);
     },
 
-    gatherTelemetry: function gatherTelemetry() {
-        if (this._locked)
-            return; // oh well, maybe next time
-        this._locked = true;
-
-        NetUtil.asyncFetch(this._dataFile, this.sGatherTelemetry2);
-    },
-
     observe: function (aSubject, aTopic, aData) {
         switch (aTopic) {
         case "profile-after-change":
             this.setup();
             break;
-        case "gather-telemetry":
-            this._do_telemetry = true;
-            this.updateStats();
-            break;
         case "idle":
             this.updateStats();
             break;
-        case "profile-change-net-teardown":
+        case "quit-application":
+            this.updateStats();
             this.shutdown();
             break;
         }
     },
-
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([HttpDataUsage]);
--- a/parser/htmlparser/src/nsScanner.cpp
+++ b/parser/htmlparser/src/nsScanner.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et tw=78: */
 /* 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/. */
 
 //#define __INCREMENTAL 1
 
+#include "mozilla/DebugOnly.h"
+
 #include "nsScanner.h"
 #include "nsDebug.h"
 #include "nsIServiceManager.h"
 #include "nsICharsetConverterManager.h"
 #include "nsReadableUtils.h"
 #include "nsIInputStream.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
@@ -113,37 +115,34 @@ nsScanner::nsScanner(nsString& aFilename
   mHasInvalidCharacter = false;
   mReplacementCharacter = PRUnichar(0x0);
   // XML defaults to UTF-8 and about:blank is UTF-8, too.
   SetDocumentCharset(NS_LITERAL_CSTRING("UTF-8"), kCharsetFromDocTypeDefault);
 }
 
 nsresult nsScanner::SetDocumentCharset(const nsACString& aCharset , int32_t aSource)
 {
-  if (aSource < mCharsetSource) // priority is lower the the current one , just
+  if (aSource < mCharsetSource) // priority is lower than the current one
     return NS_OK;
 
+  mCharsetSource = aSource;
+
   nsCString charsetName;
-  bool valid = EncodingUtils::FindEncodingForLabel(aCharset, charsetName);
+  mozilla::DebugOnly<bool> valid =
+      EncodingUtils::FindEncodingForLabel(aCharset, charsetName);
   MOZ_ASSERT(valid, "Should never call with a bogus aCharset.");
-  if (!mCharset.IsEmpty())
-  {
-    if (charsetName.Equals(mCharset))
-    {
-      mCharsetSource = aSource;
-      return NS_OK; // no difference, don't change it
-    }
+
+  if (!mCharset.IsEmpty() && charsetName.Equals(mCharset)) {
+    return NS_OK; // no difference, don't change it
   }
 
   // different, need to change it
 
   mCharset.Assign(charsetName);
 
-  mCharsetSource = aSource;
-
   NS_ASSERTION(nsParser::GetCharsetConverterManager(),
                "Must have the charset converter manager!");
 
   nsresult res = nsParser::GetCharsetConverterManager()->
     GetUnicodeDecoderRaw(mCharset.get(), getter_AddRefs(mUnicodeDecoder));
   if (NS_SUCCEEDED(res) && mUnicodeDecoder)
   {
      // We need to detect conversion error of character to support XML
--- a/python/mozbuild/mozbuild/backend/base.py
+++ b/python/mozbuild/mozbuild/backend/base.py
@@ -4,16 +4,17 @@
 
 from __future__ import unicode_literals
 
 from abc import (
     ABCMeta,
     abstractmethod,
 )
 
+import errno
 import os
 import sys
 import time
 
 from contextlib import contextmanager
 
 from mach.mixin.logging import LoggingMixin
 
@@ -33,28 +34,28 @@ class BackendConsumeSummary(object):
     """
     def __init__(self):
         # How many moz.build files were read. This includes included files.
         self.mozbuild_count = 0
 
         # The number of derived objects from the read moz.build files.
         self.object_count = 0
 
-        # The number of backend files managed.
-        self.managed_count = 0
-
         # The number of backend files created.
         self.created_count = 0
 
         # The number of backend files updated.
         self.updated_count = 0
 
         # The number of unchanged backend files.
         self.unchanged_count = 0
 
+        # The number of deleted backend files.
+        self.deleted_count = 0
+
         # The total wall time this backend spent consuming objects. If
         # the iterable passed into consume() is a generator, this includes the
         # time spent to read moz.build files.
         self.wall_time = 0.0
 
         # CPU time spent by during the interval captured by wall_time.
         self.cpu_time = 0.0
 
@@ -118,16 +119,27 @@ class BuildBackend(LoggingMixin):
 
         self.environment = environment
         self.summary = BackendConsumeSummary()
 
         # Files whose modification should cause a new read and backend
         # generation.
         self.backend_input_files = set()
 
+        # Files generated by the backend.
+        self._backend_output_files = set()
+
+        # Previously generated files.
+        self._backend_output_list_file = os.path.join(environment.topobjdir,
+            'backend.%s' % self.__class__.__name__)
+        self._backend_output_list = set()
+        if os.path.exists(self._backend_output_list_file):
+            self._backend_output_list.update(open(self._backend_output_list_file) \
+                                               .read().split('\n'))
+
         # Pull in Python files for this package as dependencies so backend
         # regeneration occurs if any of the code affecting it changes.
         for name, module in sys.modules.items():
             if not module or not name.startswith('mozbuild'):
                 continue
 
             p = module.__file__
 
@@ -196,28 +208,44 @@ class BuildBackend(LoggingMixin):
 
             if isinstance(obj, SandboxDerived):
                 self.backend_input_files |= obj.sandbox_all_paths
 
             if isinstance(obj, ReaderSummary):
                 self.summary.mozbuild_count = obj.total_file_count
                 self.summary.mozbuild_execution_time = obj.total_execution_time
 
-        # Write out a file indicating when this backend was last generated.
-        age_file = os.path.join(self.environment.topobjdir,
-            'backend.%s.built' % self.__class__.__name__)
-        if self.summary.updated_count or self.summary.created_count or \
-                not os.path.exists(age_file):
-            with open(age_file, 'a'):
-                os.utime(age_file, None)
-
         finished_start = time.time()
         self.consume_finished()
         backend_time += time.time() - finished_start
 
+        # Purge backend files created in previous run, but not created anymore
+        delete_files = self._backend_output_list - self._backend_output_files
+        for path in delete_files:
+            try:
+                os.unlink(os.path.join(self.environment.topobjdir, path))
+                self.summary.deleted_count += 1
+            except OSError:
+                pass
+        # Remove now empty directories
+        for dir in set(os.path.dirname(d) for d in delete_files):
+            try:
+                os.removedirs(dir)
+            except OSError:
+                pass
+
+        # Write out the list of backend files generated, if it changed.
+        if self.summary.deleted_count or self.summary.created_count or \
+                not os.path.exists(self._backend_output_list_file):
+            with open(self._backend_output_list_file, 'w') as fh:
+                fh.write('\n'.join(sorted(self._backend_output_files)))
+        elif self.summary.updated_count:
+            with open(self._backend_output_list_file, 'a'):
+                os.utime(self._backend_output_list_file, None)
+
         self.summary.cpu_time = time.clock() - cpu_start
         self.summary.wall_time = time.time() - time_start
         self.summary.backend_execution_time = backend_time
         self.summary.other_time = self.summary.wall_time - \
             self.summary.mozbuild_execution_time - \
             self.summary.backend_execution_time
 
         return self.summary
@@ -229,30 +257,43 @@ class BuildBackend(LoggingMixin):
         This is the main method used by child classes to react to build
         metadata.
         """
 
     def consume_finished(self):
         """Called when consume() has completed handling all objects."""
 
     @contextmanager
-    def _write_file(self, path):
+    def _write_file(self, path=None, fh=None):
         """Context manager to write a file.
 
         This is a glorified wrapper around FileAvoidWrite with integration to
         update the BackendConsumeSummary on this instance.
 
         Example usage:
 
             with self._write_file('foo.txt') as fh:
                 fh.write('hello world')
         """
 
-        fh = FileAvoidWrite(path)
+        if path is not None:
+            assert fh is None
+            fh = FileAvoidWrite(path)
+        else:
+            assert fh is not None
+
+        dirname = os.path.dirname(fh.name)
+        try:
+            os.makedirs(dirname)
+        except OSError as error:
+            if error.errno != errno.EEXIST:
+                raise
+
         yield fh
 
+        self._backend_output_files.add(os.path.relpath(fh.name, self.environment.topobjdir))
         existed, updated = fh.close()
         if not existed:
             self.summary.created_count += 1
         elif updated:
             self.summary.updated_count += 1
         else:
             self.summary.unchanged_count += 1
--- a/python/mozbuild/mozbuild/backend/configenvironment.py
+++ b/python/mozbuild/mozbuild/backend/configenvironment.py
@@ -190,87 +190,86 @@ class ConfigEnvironment(object):
 
     def get_input(self, file):
         '''Returns the input file path in the source tree that can be used
         to create the given config file or header.
         '''
         assert(isinstance(file, basestring))
         return os.path.normpath(os.path.join(self.topsrcdir, "%s.in" % relpath(file, self.topobjdir)))
 
-    def create_config_file(self, path, extra=None):
+    def create_config_file(self, output, extra=None):
         '''Creates the given config file. A config file is generated by
         taking the corresponding source file and replacing occurences of
         "@VAR@" by the value corresponding to "VAR" in the substs dict.
 
         Additional substs are defined according to the file being treated:
             "srcdir" for its the path to its source directory
             "relativesrcdir" for its source directory relative to the top
             "DEPTH" for the path to the top object directory
         '''
+        path = output.name
         if os.path.basename(path) == 'Makefile':
-            return self.create_makefile(path, extra=extra)
-        pp = self._get_preprocessor(path, extra)
+            return self.create_makefile(output, extra=extra)
+        pp = self._get_preprocessor(output, extra)
         pp.do_include(self.get_input(path))
-        return pp.out.close()
 
-    def create_makefile(self, path, stub=False, extra=None):
+    def create_makefile(self, output, stub=False, extra=None):
         '''Creates the given makefile. Makefiles are treated the same as
         config files, but some additional header and footer is added to the
         output.
 
         When the stub argument is True, no source file is used, and a stub
         makefile with the default header and footer only is created.
         '''
-        pp = self._get_preprocessor(path, extra)
+        pp = self._get_preprocessor(output, extra)
         pp.handleLine('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
         pp.handleLine('DEPTH := @DEPTH@\n')
         pp.handleLine('topsrcdir := @top_srcdir@\n')
         pp.handleLine('srcdir := @srcdir@\n')
         pp.handleLine('VPATH := @srcdir@\n')
         pp.handleLine('relativesrcdir := @relativesrcdir@\n')
         pp.handleLine('include $(DEPTH)/config/autoconf.mk\n')
         if not stub:
-            pp.do_include(self.get_input(path))
+            pp.do_include(self.get_input(output.name))
         # Empty line to avoid failures when last line in Makefile.in ends
         # with a backslash.
         pp.handleLine('\n')
         pp.handleLine('include $(topsrcdir)/config/recurse.mk\n')
-        return pp.out.close()
 
-    def _get_preprocessor(self, path, extra):
+    def _get_preprocessor(self, output, extra):
         '''Returns a preprocessor for use by create_config_file and
         create_makefile.
         '''
+        path = output.name
         pp = Preprocessor()
         pp.context.update(self.substs)
         pp.context.update(top_srcdir = self.get_top_srcdir(path))
         pp.context.update(srcdir = self.get_file_srcdir(path))
         pp.context.update(relativesrcdir = self.get_relative_srcdir(path))
         pp.context.update(DEPTH = self.get_depth(path))
         if extra:
             pp.context.update(extra)
         pp.do_filter('attemptSubstitution')
         pp.setMarker(None)
 
-        pp.out = FileAvoidWrite(path)
+        pp.out = output
         return pp
 
-    def create_config_header(self, path):
+    def create_config_header(self, output):
         '''Creates the given config header. A config header is generated by
         taking the corresponding source file and replacing some #define/#undef
         occurences:
             "#undef NAME" is turned into "#define NAME VALUE"
             "#define NAME" is unchanged
             "#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE"
             "#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */"
             Whitespaces are preserved.
         '''
-        with open(self.get_input(path), 'rU') as input:
-            ensureParentDir(path)
-            output = FileAvoidWrite(path)
+        with open(self.get_input(output.name), 'rU') as input:
+            ensureParentDir(output.name)
             r = re.compile('^\s*#\s*(?P<cmd>[a-z]+)(?:\s+(?P<name>\S+)(?:\s+(?P<value>\S+))?)?', re.U)
             for l in input:
                 m = r.match(l)
                 if m:
                     cmd = m.group('cmd')
                     name = m.group('name')
                     value = m.group('value')
                     if name:
@@ -278,9 +277,8 @@ class ConfigEnvironment(object):
                             if cmd == 'define' and value:
                                 l = l[:m.start('value')] + str(self.defines[name]) + l[m.end('value'):]
                             elif cmd == 'undef':
                                 l = l[:m.start('cmd')] + 'define' + l[m.end('cmd'):m.end('name')] + ' ' + str(self.defines[name]) + l[m.end('name'):]
                         elif cmd == 'undef':
                            l = '/* ' + l[:m.end('name')] + ' */' + l[m.end('name'):]
 
                 output.write(l)
-            return output.close()
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1,15 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import unicode_literals
 
-import errno
 import itertools
 import logging
 import os
 import re
 import types
 
 from collections import namedtuple
 
@@ -24,16 +23,17 @@ from .common import CommonBackend
 from ..frontend.data import (
     ConfigFileSubstitution,
     Defines,
     DirectoryTraversal,
     Exports,
     GeneratedEventWebIDLFile,
     GeneratedInclude,
     GeneratedWebIDLFile,
+    HeaderFileSubstitution,
     InstallationTarget,
     IPDLFile,
     JavaJarData,
     LocalInclude,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     SandboxDerived,
@@ -45,17 +45,16 @@ from ..frontend.data import (
     WebIDLFile,
 )
 from ..util import (
     ensureParentDir,
     FileAvoidWrite,
 )
 from ..makeutil import Makefile
 
-
 class BackendMakeFile(object):
     """Represents a generated backend.mk file.
 
     This is both a wrapper around a file handle as well as a container that
     holds accumulated state.
 
     It's worth taking a moment to explain the make dependencies. The
     generated backend.mk as well as the Makefile.in (if it exists) are in the
@@ -77,40 +76,34 @@ class BackendMakeFile(object):
     actually change. We use FileAvoidWrite to accomplish this.
     """
 
     def __init__(self, srcdir, objdir, environment):
         self.srcdir = srcdir
         self.objdir = objdir
         self.relobjdir = objdir[len(environment.topobjdir) + 1:]
         self.environment = environment
-        self.path = os.path.join(objdir, 'backend.mk')
+        self.name = os.path.join(objdir, 'backend.mk')
 
         # XPIDLFiles attached to this file.
         self.idls = []
         self.xpt_name = None
 
-        self.fh = FileAvoidWrite(self.path)
+        self.fh = FileAvoidWrite(self.name)
         self.fh.write('# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT.\n')
         self.fh.write('\n')
         self.fh.write('MOZBUILD_DERIVED := 1\n')
 
-        # The global rule to incur backend generation generates Makefiles.
-        self.fh.write('NO_MAKEFILE_RULE := 1\n')
-
-        # We can't blindly have a SUBMAKEFILES rule because some of the
-        # Makefile may not have a corresponding Makefile.in. For the case
-        # where a new directory is added, the mozbuild file referencing that
-        # new directory will need updated. This will cause a full backend
-        # scan and build, installing the new Makefile.
-        self.fh.write('NO_SUBMAKEFILES_RULE := 1\n')
-
     def write(self, buf):
         self.fh.write(buf)
 
+    # For compatibility with makeutil.Makefile
+    def add_statement(self, stmt):
+        self.write('%s\n' % stmt)
+
     def close(self):
         if self.xpt_name:
             self.fh.write('XPT_NAME := %s\n' % self.xpt_name)
 
             # We just recompile all xpidls because it's easier and less error
             # prone.
             self.fh.write('NONRECURSIVE_TARGETS += export\n')
             self.fh.write('NONRECURSIVE_TARGETS_export += xpidl\n')
@@ -274,19 +267,23 @@ class RecursiveMakeBackend(CommonBackend
         self._webidl_sources = set()
         self._generated_events_webidl_sources = set()
         self._test_webidl_sources = set()
         self._preprocessed_test_webidl_sources = set()
         self._preprocessed_webidl_sources = set()
         self._generated_webidl_sources = set()
 
         def detailed(summary):
-            return '{:d} total backend files. {:d} created; {:d} updated; {:d} unchanged'.format(
-                summary.managed_count, summary.created_count,
+            s = '{:d} total backend files. {:d} created; {:d} updated; {:d} unchanged'.format(
+                summary.created_count + summary.updated_count +
+                summary.unchanged_count, summary.created_count,
                 summary.updated_count, summary.unchanged_count)
+            if summary.deleted_count:
+                s+= '; {:d} deleted'.format(summary.deleted_count)
+            return s
 
         # This is a little kludgy and could be improved with a better API.
         self.summary.backend_detailed_summary = types.MethodType(detailed,
             self.summary)
 
         self._test_manifests = {}
 
         self.backend_input_files.add(os.path.join(self.environment.topobjdir,
@@ -315,51 +312,60 @@ class RecursiveMakeBackend(CommonBackend
 
         derecurse = self.environment.substs.get('MOZ_PSEUDO_DERECURSE', '').split(',')
         self._parallel_export = False
         self._no_skip = False
         if derecurse != ['']:
             self._parallel_export = 'no-parallel-export' not in derecurse
             self._no_skip = 'no-skip' in derecurse
 
-    def _update_from_avoid_write(self, result):
-        existed, updated = result
-
-        if not existed:
-            self.summary.created_count += 1
-        elif updated:
-            self.summary.updated_count += 1
-        else:
-            self.summary.unchanged_count += 1
-
     def consume_object(self, obj):
         """Write out build files necessary to build with recursive make."""
 
         CommonBackend.consume_object(self, obj)
 
         if not isinstance(obj, SandboxDerived):
             return
 
-        backend_file = self._backend_files.get(obj.srcdir,
-            BackendMakeFile(obj.srcdir, obj.objdir, self.get_environment(obj)))
+        if obj.srcdir not in self._backend_files:
+            self._backend_files[obj.srcdir] = \
+                BackendMakeFile(obj.srcdir, obj.objdir, self.get_environment(obj))
+        backend_file = self._backend_files[obj.srcdir]
 
         if isinstance(obj, DirectoryTraversal):
             self._process_directory_traversal(obj, backend_file)
         elif isinstance(obj, ConfigFileSubstitution):
-            self._update_from_avoid_write(
-                backend_file.environment.create_config_file(obj.output_path))
+            with self._write_file(obj.output_path) as fh:
+                backend_file.environment.create_config_file(fh)
             self.backend_input_files.add(obj.input_path)
-            self.summary.managed_count += 1
+        elif isinstance(obj, HeaderFileSubstitution):
+            with self._write_file(obj.output_path) as fh:
+                backend_file.environment.create_config_header(fh)
+            self.backend_input_files.add(obj.input_path)
         elif isinstance(obj, XPIDLFile):
             backend_file.idls.append(obj)
             backend_file.xpt_name = '%s.xpt' % obj.module
         elif isinstance(obj, VariablePassthru):
+            unified_suffixes = dict(
+                UNIFIED_CSRCS='c',
+                UNIFIED_CPPSRCS='cpp',
+            )
             # Sorted so output is consistent and we don't bump mtimes.
             for k, v in sorted(obj.variables.items()):
-                if isinstance(v, list):
+                if k in unified_suffixes.keys():
+                    self._add_unified_build_rules(backend_file, v,
+                                      backend_file.objdir,
+                                      unified_prefix='Unified_%s_%s' %
+                                      (unified_suffixes[k],
+                                      backend_file.relobjdir.replace('/', '_')),
+                                      unified_suffix=unified_suffixes[k],
+                                      unified_files_makefile_variable=k,
+                                      include_curdir_build_rules=False)
+                    backend_file.write('%s += $(%s)\n' % (k[len('UNIFIED_'):], k))
+                elif isinstance(v, list):
                     for item in v:
                         backend_file.write('%s += %s\n' % (k, item))
                 elif isinstance(v, bool):
                     if v:
                         backend_file.write('%s := 1\n' % k)
                 else:
                     backend_file.write('%s := %s\n' % (k, v))
 
@@ -539,38 +545,38 @@ class RecursiveMakeBackend(CommonBackend
 
                 else:
                     # Output the list of filtered directories for each tier/subtier
                     # pair.
                     root_mk.add_statement('%s_subtier_%s := %s' % (tier, subtier, ' '.join(subtier_dirs)))
 
         root_mk.add_statement('$(call include_deps,root-deps.mk)')
 
-        root = FileAvoidWrite(
-            os.path.join(self.environment.topobjdir, 'root.mk'))
-        root_deps = FileAvoidWrite(
-            os.path.join(self.environment.topobjdir, 'root-deps.mk'))
-        root_mk.dump(root, removal_guard=False)
-        root_deps_mk.dump(root_deps, removal_guard=False)
-        self._update_from_avoid_write(root.close())
-        self._update_from_avoid_write(root_deps.close())
+        with self._write_file(
+                os.path.join(self.environment.topobjdir, 'root.mk')) as root:
+            root_mk.dump(root, removal_guard=False)
+
+        with self._write_file(
+                os.path.join(self.environment.topobjdir, 'root-deps.mk')) as root_deps:
+            root_deps_mk.dump(root_deps, removal_guard=False)
 
     def _add_unified_build_rules(self, makefile, files, output_directory,
                                  unified_prefix='Unified',
+                                 unified_suffix='cpp',
                                  extra_dependencies=[],
                                  unified_files_makefile_variable='unified_files',
                                  include_curdir_build_rules=True):
         files_per_unified_file = 16
 
         explanation = "\n" \
             "# We build files in 'unified' mode by including several files\n" \
             "# together into a single source file.  This cuts down on\n" \
             "# compilation times and debug information size.  %d was chosen as\n" \
             "# a reasonable compromise between clobber rebuild time, incremental\n" \
-            "# rebuild time, and compiler memory usage.\n" % files_per_unified_file
+            "# rebuild time, and compiler memory usage." % files_per_unified_file
         makefile.add_statement(explanation)
 
         def unified_files():
             "Return an iterator of (unified_filename, source_filenames) tuples."
             # Our last returned list of source filenames may be short, and we
             # don't want the fill value inserted by izip_longest to be an
             # issue.  So we do a little dance to filter it out ourselves.
             dummy_fill_value = ("dummy",)
@@ -582,103 +588,89 @@ class RecursiveMakeBackend(CommonBackend
             def grouper(n, iterable):
                 "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
                 args = [iter(iterable)] * n
                 return itertools.izip_longest(fillvalue=dummy_fill_value, *args)
 
             for i, unified_group in enumerate(grouper(files_per_unified_file,
                                                       sorted(files))):
                 just_the_filenames = list(filter_out_dummy(unified_group))
-                yield '%s%d.cpp' % (unified_prefix, i), just_the_filenames
+                yield '%s%d.%s' % (unified_prefix, i, unified_suffix), just_the_filenames
 
         all_sources = ' '.join(source for source, _ in unified_files())
-        makefile.add_statement('%s := %s\n' % (unified_files_makefile_variable,
+        makefile.add_statement('%s := %s' % (unified_files_makefile_variable,
                                                all_sources))
 
-        regen_cmds = ['for f in $(filter %.cpp,$^); do echo "#include \\"$$f\\""; done > $@']
         for unified_file, source_filenames in unified_files():
-            rule = makefile.create_rule([unified_file])
-            rule.add_dependencies(extra_dependencies + source_filenames)
-            rule.add_commands(regen_cmds)
+            if extra_dependencies:
+                rule = makefile.create_rule([unified_file])
+                rule.add_dependencies(extra_dependencies)
 
             # The rule we just defined is only for cases where the cpp files get
             # blown away and we need to regenerate them.  The rule doesn't correctly
             # handle source files being added/removed/renamed.  Therefore, we
             # generate them here also to make sure everything's up-to-date.
-            with FileAvoidWrite(os.path.join(output_directory, unified_file)) as f:
+            with self._write_file(os.path.join(output_directory, unified_file)) as f:
                 f.write('\n'.join(['#include "%s"' % s for s in source_filenames]))
 
         if include_curdir_build_rules:
             makefile.add_statement('\n'
                 '# Make sometimes gets confused between "foo" and "$(CURDIR)/foo".\n'
                 '# Help it out by explicitly specifiying dependencies.')
             makefile.add_statement('all_absolute_unified_files := \\\n'
                                    '  $(addprefix $(CURDIR)/,$(%s))'
                                    % unified_files_makefile_variable)
             rule = makefile.create_rule(['$(all_absolute_unified_files)'])
             rule.add_dependencies(['$(CURDIR)/%: %'])
 
     def consume_finished(self):
         CommonBackend.consume_finished(self)
 
         for srcdir in sorted(self._backend_files.keys()):
-            bf = self._backend_files[srcdir]
-
-            if not os.path.exists(bf.objdir):
-                try:
-                    os.makedirs(bf.objdir)
-                except OSError as error:
-                    if error.errno != errno.EEXIST:
-                        raise
+            with self._write_file(fh=self._backend_files[srcdir]) as bf:
+                makefile_in = os.path.join(srcdir, 'Makefile.in')
+                makefile = os.path.join(bf.objdir, 'Makefile')
 
-            makefile_in = os.path.join(srcdir, 'Makefile.in')
-            makefile = os.path.join(bf.objdir, 'Makefile')
-
-            # If Makefile.in exists, use it as a template. Otherwise, create a
-            # stub.
-            stub = not os.path.exists(makefile_in)
-            if not stub:
-                self.log(logging.DEBUG, 'substitute_makefile',
-                    {'path': makefile}, 'Substituting makefile: {path}')
+                # If Makefile.in exists, use it as a template. Otherwise,
+                # create a stub.
+                stub = not os.path.exists(makefile_in)
+                if not stub:
+                    self.log(logging.DEBUG, 'substitute_makefile',
+                        {'path': makefile}, 'Substituting makefile: {path}')
 
-                # Adding the Makefile.in here has the desired side-effect that
-                # if the Makefile.in disappears, this will force moz.build
-                # traversal. This means that when we remove empty Makefile.in
-                # files, the old file will get replaced with the autogenerated
-                # one automatically.
-                self.backend_input_files.add(makefile_in)
+                    # Adding the Makefile.in here has the desired side-effect
+                    # that if the Makefile.in disappears, this will force
+                    # moz.build traversal. This means that when we remove empty
+                    # Makefile.in files, the old file will get replaced with
+                    # the autogenerated one automatically.
+                    self.backend_input_files.add(makefile_in)
 
-                for skiplist in self._may_skip.values():
-                    if bf.relobjdir in skiplist:
-                        skiplist.remove(bf.relobjdir)
-            else:
-                self.log(logging.DEBUG, 'stub_makefile',
-                    {'path': makefile}, 'Creating stub Makefile: {path}')
+                    for skiplist in self._may_skip.values():
+                        if bf.relobjdir in skiplist:
+                            skiplist.remove(bf.relobjdir)
+                else:
+                    self.log(logging.DEBUG, 'stub_makefile',
+                        {'path': makefile}, 'Creating stub Makefile: {path}')
 
-            # Can't skip directories with a jar.mn for the 'libs' tier.
-            if bf.relobjdir in self._may_skip['libs'] and \
-                    os.path.exists(os.path.join(srcdir, 'jar.mn')):
-                self._may_skip['libs'].remove(bf.relobjdir)
+                # Can't skip directories with a jar.mn for the 'libs' tier.
+                if bf.relobjdir in self._may_skip['libs'] and \
+                        os.path.exists(os.path.join(srcdir, 'jar.mn')):
+                    self._may_skip['libs'].remove(bf.relobjdir)
 
-            self._update_from_avoid_write(
-                bf.environment.create_makefile(makefile, stub=stub))
-            self.summary.managed_count += 1
-
-            self._update_from_avoid_write(bf.close())
-            self.summary.managed_count += 1
+                with self._write_file(makefile) as fh:
+                    bf.environment.create_makefile(fh, stub=stub)
 
         self._fill_root_mk()
 
         # Write out a master list of all IPDL source files.
         ipdl_dir = os.path.join(self.environment.topobjdir, 'ipc', 'ipdl')
-        ipdls = FileAvoidWrite(os.path.join(ipdl_dir, 'ipdlsrcs.mk'))
         mk = mozmakeutil.Makefile()
 
         sorted_ipdl_sources = list(sorted(self._ipdl_sources))
-        mk.add_statement('ALL_IPDLSRCS := %s\n' % ' '.join(sorted_ipdl_sources))
+        mk.add_statement('ALL_IPDLSRCS := %s' % ' '.join(sorted_ipdl_sources))
 
         def files_from(ipdl):
             base = os.path.basename(ipdl)
             root, ext = os.path.splitext(base)
 
             # Both .ipdl and .ipdlh become .cpp files
             files = ['%s.cpp' % root]
             if ext == '.ipdl':
@@ -687,33 +679,30 @@ class RecursiveMakeBackend(CommonBackend
                               '%sParent.cpp' % root])
             return files
 
         ipdl_cppsrcs = list(itertools.chain(*[files_from(p) for p in sorted_ipdl_sources]))
         self._add_unified_build_rules(mk, ipdl_cppsrcs, ipdl_dir,
                                       unified_prefix='UnifiedProtocols',
                                       unified_files_makefile_variable='CPPSRCS')
 
-        mk.add_statement('IPDLDIRS := %s\n' % ' '.join(sorted(set(os.path.dirname(p)
+        mk.add_statement('IPDLDIRS := %s' % ' '.join(sorted(set(os.path.dirname(p)
             for p in self._ipdl_sources))))
 
-        mk.dump(ipdls, removal_guard=False)
-
-        self._update_from_avoid_write(ipdls.close())
-        self.summary.managed_count += 1
+        with self._write_file(os.path.join(ipdl_dir, 'ipdlsrcs.mk')) as ipdls:
+            mk.dump(ipdls, removal_guard=False)
 
         # Write out master lists of WebIDL source files.
         bindings_dir = os.path.join(self.environment.topobjdir, 'dom', 'bindings')
-        webidls = FileAvoidWrite(os.path.join(bindings_dir, 'webidlsrcs.mk'))
 
         mk = mozmakeutil.Makefile()
 
         def write_var(variable, sources):
             files = [os.path.basename(f) for f in sorted(sources)]
-            mk.add_statement('%s += %s\n' % (variable, ' '.join(files)))
+            mk.add_statement('%s += %s' % (variable, ' '.join(files)))
         write_var('webidl_files', self._webidl_sources)
         write_var('generated_events_webidl_files', self._generated_events_webidl_sources)
         write_var('test_webidl_files', self._test_webidl_sources)
         write_var('preprocessed_test_webidl_files', self._preprocessed_test_webidl_sources)
         write_var('generated_webidl_files', self._generated_webidl_sources)
         write_var('preprocessed_webidl_files', self._preprocessed_webidl_sources)
 
         all_webidl_files = itertools.chain(iter(self._webidl_sources),
@@ -725,38 +714,31 @@ class RecursiveMakeBackend(CommonBackend
 
         self._add_unified_build_rules(mk, all_webidl_sources,
                                       bindings_dir,
                                       unified_prefix='UnifiedBindings',
                                       unified_files_makefile_variable='unified_binding_cpp_files')
 
         # Assume that Somebody Else has responsibility for correctly
         # specifying removal dependencies for |all_webidl_sources|.
-        mk.dump(webidls, removal_guard=False)
-
-        self._update_from_avoid_write(webidls.close())
-        self.summary.managed_count += 1
+        with self._write_file(os.path.join(bindings_dir, 'webidlsrcs.mk')) as webidls:
+            mk.dump(webidls, removal_guard=False)
 
         # Write out a dependency file used to determine whether a config.status
         # re-run is needed.
-        backend_built_path = os.path.join(self.environment.topobjdir,
-            'backend.%s.built' % self.__class__.__name__).replace(os.sep, '/')
-        backend_deps = FileAvoidWrite('%s.pp' % backend_built_path)
         inputs = sorted(p.replace(os.sep, '/') for p in self.backend_input_files)
 
         # We need to use $(DEPTH) so the target here matches what's in
         # rules.mk. If they are different, the dependencies don't get pulled in
         # properly.
-        backend_deps.write('$(DEPTH)/backend.RecursiveMakeBackend.built: %s\n' %
-            ' '.join(inputs))
-        for path in inputs:
-            backend_deps.write('%s:\n' % path)
-
-        self._update_from_avoid_write(backend_deps.close())
-        self.summary.managed_count += 1
+        with self._write_file('%s.pp' % self._backend_output_list_file) as backend_deps:
+            backend_deps.write('$(DEPTH)/backend.%s: %s\n' %
+                (self.__class__.__name__, ' '.join(inputs)))
+            for path in inputs:
+                backend_deps.write('%s:\n' % path)
 
         # Make the master test manifest files.
         for flavor, t in self._test_manifests.items():
             install_prefix, manifests = t
             manifest_stem = os.path.join(install_prefix, '%s.ini' % flavor)
             self._write_master_test_manifest(os.path.join(
                 self.environment.topobjdir, '_tests', manifest_stem),
                 manifests)
@@ -953,22 +935,21 @@ class RecursiveMakeBackend(CommonBackend
 
         # Create dependency for output header so we force regeneration if the
         # header was deleted. This ideally should not be necessary. However,
         # some processes (such as PGO at the time this was implemented) wipe
         # out dist/include without regard to our install manifests.
 
         out_path = os.path.join(self.environment.topobjdir, 'config',
             'makefiles', 'xpidl', 'Makefile')
-        result = self.environment.create_config_file(out_path, extra=dict(
-            xpidl_rules='\n'.join(rules),
-            xpidl_modules=' '.join(xpt_modules),
-        ))
-        self._update_from_avoid_write(result)
-        self.summary.managed_count += 1
+        with self._write_file(out_path) as fh:
+            self.environment.create_config_file(fh, extra=dict(
+                xpidl_rules='\n'.join(rules),
+                xpidl_modules=' '.join(xpt_modules),
+            ))
 
         # The Makefile can't regenerate itself because of custom substitution.
         # We need to list it here to ensure changes cause regeneration.
         self.backend_input_files.add(os.path.join(self.environment.topsrcdir,
             'config', 'makefiles', 'xpidl', 'Makefile.in'))
 
     def _process_program(self, program, backend_file):
         backend_file.write('PROGRAM = %s\n' % program)
@@ -1038,24 +1019,20 @@ class RecursiveMakeBackend(CommonBackend
 
         # We have a purger for the manifests themselves to ensure legacy
         # manifests are deleted.
         purger = FilePurger()
 
         for k, manifest in manifests.items():
             purger.add(k)
 
-            fh = FileAvoidWrite(os.path.join(man_dir, k))
-            manifest.write(fileobj=fh)
-            self._update_from_avoid_write(fh.close())
+            with self._write_file(os.path.join(man_dir, k)) as fh:
+                manifest.write(fileobj=fh)
 
         purger.purge(man_dir)
 
     def _write_master_test_manifest(self, path, manifests):
-        master = FileAvoidWrite(path)
-        master.write(
-            '; THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n\n')
+        with self._write_file(path) as master:
+            master.write(
+                '; THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n\n')
 
-        for manifest in sorted(manifests):
-            master.write('[include:%s]\n' % manifest)
-
-        self._update_from_avoid_write(master.close())
-        self.summary.managed_count += 1
+            for manifest in sorted(manifests):
+                master.write('[include:%s]\n' % manifest)
--- a/python/mozbuild/mozbuild/frontend/data.py
+++ b/python/mozbuild/mozbuild/frontend/data.py
@@ -99,36 +99,41 @@ class DirectoryTraversal(SandboxDerived)
         self.test_dirs = []
         self.test_tool_dirs = []
         self.tier_dirs = OrderedDict()
         self.tier_static_dirs = OrderedDict()
         self.external_make_dirs = []
         self.parallel_external_make_dirs = []
 
 
-class ConfigFileSubstitution(SandboxDerived):
-    """Describes a config file that will be generated using substitutions.
+class BaseConfigSubstitution(SandboxDerived):
+    """Base class describing autogenerated files as part of config.status."""
 
-    The output_path attribute defines the relative path from topsrcdir of the
-    output file to generate.
-    """
     __slots__ = (
         'input_path',
         'output_path',
         'relpath',
     )
 
     def __init__(self, sandbox):
         SandboxDerived.__init__(self, sandbox)
 
         self.input_path = None
         self.output_path = None
         self.relpath = None
 
 
+class ConfigFileSubstitution(BaseConfigSubstitution):
+    """Describes a config file that will be generated using substitutions."""
+
+
+class HeaderFileSubstitution(BaseConfigSubstitution):
+    """Describes a header file that will be generated using substitutions."""
+
+
 class VariablePassthru(SandboxDerived):
     """A dict of variables to pass through to backend.mk unaltered.
 
     The purpose of this object is to facilitate rapid transitioning of
     variables from Makefile.in to moz.build. In the ideal world, this class
     does not exist and every variable has a richer class representing it.
     As long as we rely on this class, we lose the ability to have flexibility
     in our build backends since we will continue to be tied to our rules.mk.
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -20,16 +20,17 @@ from mozpack.files import FileFinder
 from .data import (
     ConfigFileSubstitution,
     Defines,
     DirectoryTraversal,
     Exports,
     GeneratedEventWebIDLFile,
     GeneratedInclude,
     GeneratedWebIDLFile,
+    HeaderFileSubstitution,
     InstallationTarget,
     IPDLFile,
     LocalInclude,
     PreprocessedTestWebIDLFile,
     PreprocessedWebIDLFile,
     Program,
     ReaderSummary,
     SandboxWrapped,
@@ -94,24 +95,22 @@ class TreeMetadataEmitter(LoggingMixin):
 
         This is a generator of mozbuild.frontend.data.SandboxDerived instances.
         """
         # We always emit a directory traversal descriptor. This is needed by
         # the recursive make backend.
         for o in self._emit_directory_traversal_from_sandbox(sandbox): yield o
 
         for path in sandbox['CONFIGURE_SUBST_FILES']:
-            if os.path.isabs(path):
-                path = path[1:]
+            yield self._create_substitution(ConfigFileSubstitution, sandbox,
+                path)
 
-            sub = ConfigFileSubstitution(sandbox)
-            sub.input_path = os.path.join(sandbox['SRCDIR'], '%s.in' % path)
-            sub.output_path = os.path.join(sandbox['OBJDIR'], path)
-            sub.relpath = path
-            yield sub
+        for path in sandbox['CONFIGURE_DEFINE_FILES']:
+            yield self._create_substitution(HeaderFileSubstitution, sandbox,
+                path)
 
         # XPIDL source files get processed and turned into .h and .xpt files.
         # If there are multiple XPIDL files in a directory, they get linked
         # together into a final .xpt, which has the name defined by either
         # MODULE or XPIDL_MODULE (if the latter is defined).
         xpidl_module = sandbox['MODULE']
         if sandbox['XPIDL_MODULE']:
             xpidl_module = sandbox['XPIDL_MODULE']
@@ -124,17 +123,17 @@ class TreeMetadataEmitter(LoggingMixin):
             self.log(logging.WARN, 'mozbuild_warning', dict(
                 path=sandbox.main_path),
                 '{path}: NO_DIST_INSTALL has no effect on XPIDL_SOURCES.')
 
         for idl in sandbox['XPIDL_SOURCES']:
             yield XPIDLFile(sandbox, mozpath.join(sandbox['SRCDIR'], idl),
                 xpidl_module)
 
-        for symbol in ('SOURCES', 'GTEST_SOURCES', 'HOST_SOURCES'):
+        for symbol in ('SOURCES', 'GTEST_SOURCES', 'HOST_SOURCES', 'UNIFIED_SOURCES'):
             for src in (sandbox[symbol] or []):
                 if not os.path.exists(os.path.join(sandbox['SRCDIR'], src)):
                     raise SandboxValidationError('Reference to a file that '
                         'doesn\'t exist in %s (%s) in %s'
                         % (symbol, src, sandbox['RELATIVEDIR']))
 
         # Proxy some variables as-is until we have richer classes to represent
         # them. We should aim to keep this set small because it violates the
@@ -181,16 +180,18 @@ class TreeMetadataEmitter(LoggingMixin):
             CMMSRCS=('SOURCES', '.mm'),
             CPPSRCS=('SOURCES', ('.cc', '.cpp')),
             SSRCS=('SOURCES', '.S'),
             HOST_CPPSRCS=('HOST_SOURCES', ('.cc', '.cpp')),
             HOST_CSRCS=('HOST_SOURCES', '.c'),
             GTEST_CMMSRCS=('GTEST_SOURCES', '.mm'),
             GTEST_CPPSRCS=('GTEST_SOURCES', ('.cc', '.cpp')),
             GTEST_CSRCS=('GTEST_SOURCES', '.c'),
+            UNIFIED_CSRCS=('UNIFIED_SOURCES', '.c'),
+            UNIFIED_CPPSRCS=('UNIFIED_SOURCES', ('.cc', '.cpp')),
         )
         for mak, (moz, ext) in varmap.items():
             if sandbox[moz]:
                 filtered = [f for f in sandbox[moz] if f.endswith(ext)]
                 if filtered:
                     passthru.variables[mak] = filtered
 
         if passthru.variables:
@@ -261,16 +262,27 @@ class TreeMetadataEmitter(LoggingMixin):
         for prefix, info in test_manifests.items():
             for path in sandbox.get('%s_MANIFESTS' % prefix, []):
                 for obj in self._process_test_manifest(sandbox, info, path):
                     yield obj
 
         for name, jar in sandbox.get('JAVA_JAR_TARGETS', {}).items():
             yield SandboxWrapped(sandbox, jar)
 
+    def _create_substitution(self, cls, sandbox, path):
+        if os.path.isabs(path):
+            path = path[1:]
+
+        sub = cls(sandbox)
+        sub.input_path = os.path.join(sandbox['SRCDIR'], '%s.in' % path)
+        sub.output_path = os.path.join(sandbox['OBJDIR'], path)
+        sub.relpath = path
+
+        return sub
+
     def _process_test_manifest(self, sandbox, info, manifest_path):
         flavor, install_prefix, filter_inactive = info
 
         manifest_path = os.path.normpath(manifest_path)
         path = mozpath.normpath(mozpath.join(sandbox['SRCDIR'], manifest_path))
         manifest_dir = mozpath.dirname(path)
         manifest_reldir = mozpath.dirname(mozpath.relpath(path,
             sandbox['TOPSRCDIR']))
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -73,16 +73,25 @@ VARIABLES = {
 
     'SOURCES': (StrictOrderingOnAppendList, list, [],
         """Source code files.
 
         This variable contains a list of source code files to compile.
         Accepts assembler, C, C++, Objective C/C++.
         """, 'compile'),
 
+    'UNIFIED_SOURCES': (StrictOrderingOnAppendList, list, [],
+        """Source code files that can be compiled together.
+
+        This variable contains a list of source code files to compile,
+        that can be concatenated all together and built as a single source
+        file. This can help make the build faster and reduce the debug info
+        size.
+        """, 'compile'),
+
     'DEFINES': (OrderedDict, dict, OrderedDict(),
         """Dictionary of compiler defines to declare.
 
         These are passed in to the compiler as ``-Dkey='value'`` for string
         values, ``-Dkey=value`` for numeric values, or ``-Dkey`` if the
         value is True. Note that for string values, the outer-level of
         single-quotes will be consumed by the shell. If you want to have
         a string-literal in the program, the value needs to have
@@ -345,16 +354,24 @@ VARIABLES = {
 
         This is a substitute for ``AC_OUTPUT`` in autoconf. For each path in this
         list, we will search for a file in the srcdir having the name
         ``{path}.in``. The contents of this file will be read and variable
         patterns like ``@foo@`` will be substituted with the values of the
         ``AC_SUBST`` variables declared during configure.
         """, None),
 
+    'CONFIGURE_DEFINE_FILES': (StrictOrderingOnAppendList, list, [],
+        """Output files generated from configure/config.status.
+
+        This is a substitute for ``AC_CONFIG_HEADER`` in autoconf. This is very
+        similar to ``CONFIGURE_SUBST_FILES`` except the generation logic takes
+        into account the values of ``AC_DEFINE`` instead of ``AC_SUBST``.
+        """, None),
+
     'MODULE': (unicode, unicode, "",
         """Module name.
 
         Historically, this variable was used to describe where to install header
         files, but that feature is now handled by ``EXPORTS_NAMESPACES``.
         ``MODULE`` will likely be removed in the future.
         """, None),
 
--- a/python/mozbuild/mozbuild/test/backend/test_configenvironment.py
+++ b/python/mozbuild/mozbuild/test/backend/test_configenvironment.py
@@ -65,17 +65,18 @@ qux =''')
     def test_config_file(self):
         '''Test the creation of config files.
         '''
         with MockedOpen({'file.in': '''#ifdef foo
 @foo@
 @bar@
 '''}):
             env = ConfigEnvironment('.', '.', substs = [ ('foo', 'bar baz') ])
-            env.create_config_file('file')
+            with open('file', 'w') as fh:
+                env.create_config_file(fh)
             self.assertEqual(open('file', 'r').read(), '''#ifdef foo
 bar baz
 @bar@
 ''')
 
     def test_config_header(self):
         '''Test the creation of config headers.
         '''
@@ -92,17 +93,18 @@ bar baz
 
 #ifdef foo
 #   undef   foo
 #  define foo    42
   #     define   foo   42   
 #endif
 '''}):
             env = ConfigEnvironment('.', '.', defines = [ ('foo', 'baz qux'), ('baz', 1) ])
-            env.create_config_header('file')
+            with open('file', 'w') as fh:
+                env.create_config_header(fh)
             self.assertEqual(open('file','r').read(), '''
 /* Comment */
 #define foo
 #define foo baz qux
 #define foo baz qux
 #define bar
 #define bar 42
 /* #undef bar */
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -148,19 +148,19 @@ class TestRecursiveMakeTraversal(unittes
             'I': ('G', 'H'),
         })
 
 class TestRecursiveMakeBackend(BackendTester):
     def test_basic(self):
         """Ensure the RecursiveMakeBackend works without error."""
         env = self._consume('stub0', RecursiveMakeBackend)
         self.assertTrue(os.path.exists(os.path.join(env.topobjdir,
-            'backend.RecursiveMakeBackend.built')))
+            'backend.RecursiveMakeBackend')))
         self.assertTrue(os.path.exists(os.path.join(env.topobjdir,
-            'backend.RecursiveMakeBackend.built.pp')))
+            'backend.RecursiveMakeBackend.pp')))
 
     def test_output_files(self):
         """Ensure proper files are generated."""
         env = self._consume('stub0', RecursiveMakeBackend)
 
         expected = ['', 'dir1', 'dir2']
 
         for d in expected:
@@ -206,18 +206,16 @@ class TestRecursiveMakeBackend(BackendTe
         """Ensure backend.mk file is written out properly."""
         env = self._consume('stub0', RecursiveMakeBackend)
 
         p = os.path.join(env.topobjdir, 'backend.mk')
 
         lines = [l.strip() for l in open(p, 'rt').readlines()[2:]]
         self.assertEqual(lines, [
             'MOZBUILD_DERIVED := 1',
-            'NO_MAKEFILE_RULE := 1',
-            'NO_SUBMAKEFILES_RULE := 1',
             'DIRS := dir1',
             'PARALLEL_DIRS := dir2',
             'TEST_DIRS := dir3',
         ])
 
     def test_mtime_no_change(self):
         """Ensure mtime is not updated if file content does not change."""
 
@@ -239,18 +237,16 @@ class TestRecursiveMakeBackend(BackendTe
     def test_external_make_dirs(self):
         """Ensure we have make recursion into external make directories."""
         env = self._consume('external_make_dirs', RecursiveMakeBackend)
 
         backend_path = os.path.join(env.topobjdir, 'backend.mk')
         lines = [l.strip() for l in open(backend_path, 'rt').readlines()[2:]]
         self.assertEqual(lines, [
             'MOZBUILD_DERIVED := 1',
-            'NO_MAKEFILE_RULE := 1',
-            'NO_SUBMAKEFILES_RULE := 1',
             'DIRS := dir',
             'PARALLEL_DIRS := p_dir',
             'DIRS += external',
             'PARALLEL_DIRS += p_external',
         ])
 
     def test_substitute_config_files(self):
         """Ensure substituted config files are produced."""
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -113,44 +113,44 @@ class FileAvoidWrite(StringIO):
 
     We create an instance from an existing filename. New content is written to
     it. When we close the file object, if the content in the in-memory buffer
     differs from what is on disk, then we write out the new content. Otherwise,
     the original file is untouched.
     """
     def __init__(self, filename):
         StringIO.__init__(self)
-        self.filename = filename
+        self.name = filename
 
     def close(self):
         """Stop accepting writes, compare file contents, and rewrite if needed.
 
         Returns a tuple of bools indicating what action was performed:
 
             (file existed, file updated)
         """
         buf = self.getvalue()
         StringIO.close(self)
         existed = False
         try:
-            existing = open(self.filename, 'rU')
+            existing = open(self.name, 'rU')
             existed = True
         except IOError:
             pass
         else:
             try:
                 if existing.read() == buf:
                     return True, False
             except IOError:
                 pass
             finally:
                 existing.close()
 
-        ensureParentDir(self.filename)
-        with open(self.filename, 'w') as file:
+        ensureParentDir(self.name)
+        with open(self.name, 'w') as file:
             file.write(buf)
 
         return existed, True
 
     def __enter__(self):
         return self
     def __exit__(self, type, value, traceback):
         self.close()
--- a/security/manager/ssl/src/nsNSSComponent.cpp
+++ b/security/manager/ssl/src/nsNSSComponent.cpp
@@ -955,24 +955,25 @@ void nsNSSComponent::setValidationOption
 
   /*
     * The new defaults might change the validity of already established SSL sessions,
     * let's not reuse them.
     */
   SSL_ClearSessionCache();
 }
 
-// Enable the TLS versions given in the prefs, defaulting to SSL 3.0 and
-// TLS 1.0 when the prefs aren't set or when they are set to invalid values.
+// Enable the TLS versions given in the prefs, defaulting to SSL 3.0 (min
+// version) and TLS 1.1 (max version) when the prefs aren't set or set to
+// invalid values.
 nsresult
 nsNSSComponent::setEnabledTLSVersions()
 {
-  // keep these values in sync with security-prefs.js and firefox.js
+  // keep these values in sync with security-prefs.js
   static const int32_t PSM_DEFAULT_MIN_TLS_VERSION = 0;
-  static const int32_t PSM_DEFAULT_MAX_TLS_VERSION = 1;
+  static const int32_t PSM_DEFAULT_MAX_TLS_VERSION = 2;
 
   int32_t minVersion = Preferences::GetInt("security.tls.version.min",
                                            PSM_DEFAULT_MIN_TLS_VERSION);
   int32_t maxVersion = Preferences::GetInt("security.tls.version.max",
                                            PSM_DEFAULT_MAX_TLS_VERSION);
 
   // 0 means SSL 3.0, 1 means TLS 1.0, 2 means TLS 1.1, etc.
   minVersion += SSL_LIBRARY_VERSION_3_0;
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js
@@ -71,16 +71,18 @@ function run_test() {
   add_ocsp_test("ocsp-stapling-trylater.example.com", getXPCOMStatusFromNSS(122), true);
   // SEC_ERROR_OCSP_REQUEST_NEEDS_SIG = (SEC_ERROR_BASE + 123)
   add_ocsp_test("ocsp-stapling-needssig.example.com", getXPCOMStatusFromNSS(123), true);
   // SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST = (SEC_ERROR_BASE + 124)
   add_ocsp_test("ocsp-stapling-unauthorized.example.com", getXPCOMStatusFromNSS(124), true);
   // SEC_ERROR_OCSP_UNKNOWN_CERT = (SEC_ERROR_BASE + 126)
   add_ocsp_test("ocsp-stapling-unknown.example.com", getXPCOMStatusFromNSS(126), true);
   add_ocsp_test("ocsp-stapling-good-other.example.com", getXPCOMStatusFromNSS(126), true);
+  // If the server doesn't send an OCSP response, we continue as normal.
+  add_ocsp_test("ocsp-stapling-none.example.com", Cr.NS_OK, true);
   // SEC_ERROR_OCSP_MALFORMED_RESPONSE = (SEC_ERROR_BASE + 129)
-  add_ocsp_test("ocsp-stapling-none.example.com", getXPCOMStatusFromNSS(129), true);
+  add_ocsp_test("ocsp-stapling-empty.example.com", getXPCOMStatusFromNSS(129), true);
   // SEC_ERROR_OCSP_OLD_RESPONSE = (SEC_ERROR_BASE + 132)
   add_ocsp_test("ocsp-stapling-expired.example.com", getXPCOMStatusFromNSS(132), true);
   add_ocsp_test("ocsp-stapling-expired-fresh-ca.example.com", getXPCOMStatusFromNSS(132), true);
 
   run_next_test();
 }
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
@@ -26,16 +26,17 @@ enum OCSPStapleResponseType
   OSRTGood,             // the certificate is good
   OSRTRevoked,          // the certificate has been revoked
   OSRTUnknown,          // the responder doesn't know if the cert is good
   OSRTGoodOtherCert,    // the response references a different certificate
   OSRTGoodOtherCA,      // the wrong CA has signed the response
   OSRTExpired,          // the signature on the response has expired
   OSRTExpiredFreshCA,   // fresh signature, but old validity period
   OSRTNone,             // no stapled response
+  OSRTEmpty,            // an empty stapled response
   OSRTMalformed,        // the response from the responder was malformed
   OSRTSrverr,           // the response indicates there was a server error
   OSRTTryLater,         // the responder replied with "try again later"
   OSRTNeedsSig,         // the response needs a signature
   OSRTUnauthorized      // the responder is not authorized for this certificate
 };
 
 struct OCSPHost
@@ -49,28 +50,37 @@ const OCSPHost sOCSPHosts[] =
   { "ocsp-stapling-good.example.com", OSRTGood },
   { "ocsp-stapling-revoked.example.com", OSRTRevoked },
   { "ocsp-stapling-unknown.example.com", OSRTUnknown },
   { "ocsp-stapling-good-other.example.com", OSRTGoodOtherCert },
   { "ocsp-stapling-good-other-ca.example.com", OSRTGoodOtherCA },
   { "ocsp-stapling-expired.example.com", OSRTExpired },
   { "ocsp-stapling-expired-fresh-ca.example.com", OSRTExpiredFreshCA },
   { "ocsp-stapling-none.example.com", OSRTNone },
+  { "ocsp-stapling-empty.example.com", OSRTEmpty },
   { "ocsp-stapling-malformed.example.com", OSRTMalformed },
   { "ocsp-stapling-srverr.example.com", OSRTSrverr },
   { "ocsp-stapling-trylater.example.com", OSRTTryLater },
   { "ocsp-stapling-needssig.example.com", OSRTNeedsSig },
   { "ocsp-stapling-unauthorized.example.com", OSRTUnauthorized },
   { nullptr, OSRTNull }
 };
 
 SECItemArray *
 GetOCSPResponseForType(OCSPStapleResponseType aOSRT, CERTCertificate *aCert,
                        PLArenaPool *aArena)
 {
+  if (aOSRT == OSRTNone) {
+    if (gDebugLevel >= DEBUG_WARNINGS) {
+      fprintf(stderr, "GetOCSPResponseForType called with type OSRTNone, "
+                      "which makes no sense.\n");
+    }
+    return nullptr;
+  }
+
   PRTime now = PR_Now();
   ScopedCERTOCSPCertID id(CERT_CreateOCSPCertID(aCert, now));
   if (!id) {
     PrintPRError("CERT_CreateOCSPCertID failed");
     return nullptr;
   }
   PRTime nextUpdate = now + 10 * PR_USEC_PER_SEC;
   PRTime oneDay = 60*60*24 * (PRTime)PR_USEC_PER_SEC;
@@ -132,28 +142,28 @@ GetOCSPResponseForType(OCSPStapleRespons
       sr = CERT_CreateOCSPSingleResponseGood(aArena, otherID, now, &nextUpdate);
       if (!sr) {
         PrintPRError("CERT_CreateOCSPSingleResponseGood failed");
         return nullptr;
       }
       otherID.forget(); // owned by sr now
       break;
     }
-    case OSRTNone:
+    case OSRTEmpty:
     case OSRTMalformed:
     case OSRTSrverr:
     case OSRTTryLater:
     case OSRTNeedsSig:
     case OSRTUnauthorized:
       break;
     default:
       if (gDebugLevel >= DEBUG_ERRORS) {
         fprintf(stderr, "bad ocsp response type: %d\n", aOSRT);
       }
-      break;
+      return nullptr;
   }
 
   ScopedCERTCertificate ca;
   if (aOSRT == OSRTGoodOtherCA) {
     ca = PK11_FindCertFromNickname("otherCA", nullptr);
     if (!ca) {
       PrintPRError("PK11_FindCertFromNickname failed");
       return nullptr;
@@ -210,17 +220,17 @@ GetOCSPResponseForType(OCSPStapleRespons
     case OSRTUnauthorized:
       response = CERT_CreateEncodedOCSPErrorResponse(
         aArena, SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
       if (!response) {
         PrintPRError("CERT_CreateEncodedOCSPErrorResponse failed");
         return nullptr;
       }
       break;
-    case OSRTNone:
+    case OSRTEmpty:
       break;
     default:
       // responses is contained in aArena and will be freed when aArena is
       responses = PORT_ArenaNewArray(aArena, CERTOCSPSingleResponse *, 2);
       if (!responses) {
         PrintPRError("PORT_ArenaNewArray failed");
         return nullptr;
       }
@@ -258,16 +268,21 @@ DoSNISocketConfig(PRFileDesc *aFd, const
 
   ScopedCERTCertificate cert;
   SSLKEAType certKEA;
   if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, DEFAULT_CERT_NICKNAME,
                                                     &cert, &certKEA)) {
     return SSL_SNI_SEND_ALERT;
   }
 
+  // If the OCSP response type is "none", don't staple a response.
+  if (host->mOSRT == OSRTNone) {
+    return 0;
+  }
+
   PLArenaPool *arena = PORT_NewArena(1024);
   if (!arena) {
     PrintPRError("PORT_NewArena failed");
     return SSL_SNI_SEND_ALERT;
   }
 
   // response is contained by the arena - freeing the arena will free it
   SECItemArray *response = GetOCSPResponseForType(host->mOSRT, cert, arena);
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -31,17 +31,16 @@ include $(topsrcdir)/build/automation-bu
 		$(topsrcdir)/testing/mozbase/mozdevice/mozdevice/devicemanager.py \
 		$(topsrcdir)/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py \
 		$(topsrcdir)/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py \
 		$(topsrcdir)/testing/mozbase/manifestdestiny/manifestparser/manifestparser.py \
 		$(topsrcdir)/testing/mozbase/mozdevice/mozdevice/droid.py \
 		$(topsrcdir)/testing/mozbase/mozdevice/mozdevice/Zeroconf.py \
 		$(topsrcdir)/build/automationutils.py \
 		$(topsrcdir)/build/mobile/remoteautomation.py \
-		$(topsrcdir)/build/mobile/b2gautomation.py \
 		gen_template.pl \
 		server.js \
 		chunkifyTests.js \
 		manifestLibrary.js \
 		harness.xul \
 		browser-test-overlay.xul \
 		browser-test.js \
 		cc-analyzer.js \
--- a/testing/mochitest/browser-harness.xul
+++ b/testing/mochitest/browser-harness.xul
@@ -101,16 +101,21 @@
 
       // If MochiTest was started with the --test-path flag specifying a subset
       // of tests to run, put that path in the label of the "Run Tests" button
       // so the tester knows which tests will run when they press that button.
       if (gConfig.testPath)
         document.getElementById("runTestsButton").label =
           "Run " + gConfig.testPath + " tests";
 
+      // Similarly, update the title for --start-at and --end-at.
+      if (gConfig.startAt || gConfig.endAt)
+        document.getElementById("runTestsButton").label =
+          "Run subset of tests";
+
       if (gConfig.autorun)
         setTimeout(runTests, 0);
     }
 
     var gErrorCount = 0;
 
     function browserTest(aTestFile) {
       this.path = aTestFile;
@@ -185,16 +190,20 @@
       var srvScope = {};
       scriptLoader.loadSubScript('chrome://mochikit/content/server.js',
                                  srvScope);
 
       var fileNames = [];
       var fileNameRegexp = /browser_.+\.js$/;
       srvScope.arrayOfTestFiles(links, fileNames, fileNameRegexp);
 
+      if (gConfig.startAt || gConfig.endAt) {
+        fileNames = skipTests(fileNames, gConfig.startAt, gConfig.endAt);
+      }
+
       if (gConfig.totalChunks && gConfig.thisChunk) {
         fileNames = chunkifyTests(fileNames, gConfig.totalChunks,
                                   gConfig.thisChunk, gConfig.chunkByDir);
       }
 
       createTester(fileNames.map(function (f) { return new browserTest(f); }));
     }
 
--- a/testing/mochitest/chunkifyTests.js
+++ b/testing/mochitest/chunkifyTests.js
@@ -58,8 +58,24 @@ function chunkifyTests(tests, totalChunk
     var end = Math.round(this_chunk * tests_per_chunk);
     returnTests = tests.slice(start, end);
     if (logger)
       logger.log("Running tests " + (start+1) + "-" + end + "/" + tests.length);
   }
 
   return returnTests;
 }
+
+function skipTests(tests, startTestPattern, endTestPattern) {
+  var startIndex = 0, endIndex = tests.length - 1;
+  for (var i = 0; i < tests.length; ++i) {
+    var test_path = tests[i];
+    if (startTestPattern && test_path.endsWith(startTestPattern)) {
+      startIndex = i;
+    }
+
+    if (endTestPattern && test_path.endsWith(endTestPattern)) {
+      endIndex = i;
+    }
+  }
+
+  return tests.slice(startIndex, endIndex + 1);
+}
--- a/testing/mochitest/harness.xul
+++ b/testing/mochitest/harness.xul
@@ -17,16 +17,18 @@
           src="chrome://mochikit/content/tests/SimpleTest/ChromePowers.js"/>
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/TestRunner.js"/>
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/MozillaLogger.js"/>
   <script type="application/javascript"
           src="chrome://mochikit/content/chrome-harness.js" />
   <script type="application/javascript"
+          src="chrome://mochikit/content/chunkifyTests.js" />
+  <script type="application/javascript"
           src="chrome://mochikit/content/manifestLibrary.js" />
   <script type="text/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/setup.js" />
   <script type="application/javascript;version=1.7"><![CDATA[
 
 if (Cc === undefined) {
   var Cc = Components.classes;
   var Ci = Components.interfaces;
--- a/testing/mochitest/mach_commands.py
+++ b/testing/mochitest/mach_commands.py
@@ -180,17 +180,18 @@ class MochitestRunner(MozbuildObject):
         options.logcat_dir = self.mochitest_dir
         options.httpdPath = self.mochitest_dir
         options.xrePath = xre_path
         return mochitest.run_remote_mochitests(parser, options)
 
     def run_desktop_test(self, suite=None, test_file=None, debugger=None,
         debugger_args=None, shuffle=False, keep_open=False, rerun_failures=False,
         no_autorun=False, repeat=0, run_until_failure=False, slow=False,
-        chunk_by_dir=0, total_chunks=None, this_chunk=None, jsdebugger=False):
+        chunk_by_dir=0, total_chunks=None, this_chunk=None, jsdebugger=False,
+        start_at=None, end_at=None):
         """Runs a mochitest.
 
         test_file is a path to a test file. It can be a relative path from the
         top source directory, an absolute filename, or a directory containing
         test files.
 
         suite is the type of mochitest to run. It can be one of ('plain',
         'chrome', 'browser', 'metro', 'a11y').
@@ -281,16 +282,18 @@ class MochitestRunner(MozbuildObject):
         options.runSlower = slow
         options.testingModulesDir = os.path.join(self.tests_dir, 'modules')
         options.extraProfileFiles.append(os.path.join(self.distdir, 'plugins'))
         options.symbolsPath = os.path.join(self.distdir, 'crashreporter-symbols')
         options.chunkByDir = chunk_by_dir
         options.totalChunks = total_chunks
         options.thisChunk = this_chunk
         options.jsdebugger = jsdebugger
+        options.startAt = start_at
+        options.endAt = end_at
 
         options.failureFile = failure_file_path
 
         if test_path:
             test_root = runner.getTestRoot(options)
             test_root_file = mozpack.path.join(self.mochitest_dir, test_root, test_path)
             if not os.path.exists(test_root_file):
                 print('Specified test path does not exist: %s' % test_root_file)
@@ -458,16 +461,24 @@ def B2GCommand(func):
     chunk_total = CommandArgument('--total-chunks', type=int,
         help='Total number of chunks to split tests into.')
     func = chunk_total(func)
 
     this_chunk = CommandArgument('--this-chunk', type=int,
         help='If running tests by chunks, the number of the chunk to run.')
     func = this_chunk(func)
 
+    start_at = CommandArgument('--start-at', type=str,
+        help='Start running the test sequence at this test.')
+    func = start_at(func)
+
+    end_at = CommandArgument('--end-at', type=str,
+        help='Stop running the test sequence at this test.')
+    func = end_at(func)
+
     path = CommandArgument('test_file', default=None, nargs='?',
         metavar='TEST',
         help='Test to run. Can be specified as a single file, a ' \
             'directory, or omitted. If omitted, the entire test suite is ' \
             'executed.')
     func = path(func)
 
     return func
--- a/testing/mochitest/manifest.webapp
+++ b/testing/mochitest/manifest.webapp
@@ -22,17 +22,19 @@
     "camera":{},
     "geolocation":{},
     "wifi-manage":{},
     "wifi":{},
     "desktop-notification":{},
     "idle":{},
     "network-events":{},
     "embed-apps":{},
-    "systemXHR":{}
+    "systemXHR":{},
+    "audio-channel-content":{},
+    "audio-channel-alarm":{}
   },
   "locales": {
     "en-US": {
       "name": "Mochitest",
       "description": "Mochitests"
     }
   },
   "datastores-access" : {
--- a/testing/mochitest/mochitest_options.py
+++ b/testing/mochitest/mochitest_options.py
@@ -140,16 +140,30 @@ class MochitestOptions(optparse.OptionPa
         }],
         [["--test-path"],
         { "action": "store",
           "type": "string",
           "dest": "testPath",
           "help": "start in the given directory's tests",
           "default": "",
         }],
+        [["--start-at"],
+        { "action": "store",
+          "type": "string",
+          "dest": "startAt",
+          "help": "skip over tests until reaching the given test",
+          "default": "",
+        }],
+        [["--end-at"],
+        { "action": "store",
+          "type": "string",
+          "dest": "endAt",
+          "help": "don't run any tests after the given one",
+          "default": "",
+        }],
         [["--browser-chrome"],
         { "action": "store_true",
           "dest": "browserChrome",
           "help": "run browser chrome Mochitests",
           "default": False,
         }],
         [["--webapprt-content"],
         { "action": "store_true",
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -283,16 +283,18 @@ class MochitestUtilsMixin(object):
         URL parameters to test URL:
 
         autorun -- kick off tests automatically
         closeWhenDone -- closes the browser after the tests
         hideResultsTable -- hides the table of individual test results
         logFile -- logs test run to an absolute path
         totalChunks -- how many chunks to split tests into
         thisChunk -- which chunk to run
+        startAt -- name of test to start at
+        endAt -- name of test to end at
         timeout -- per-test timeout in seconds
         repeat -- How many times to repeat the test, ie: repeat=1 will run the test twice.
     """
 
     # allow relative paths for logFile
     if options.logFile:
       options.logFile = self.getLogFilePath(options.logFile)
     if options.browserChrome or options.chrome or options.a11y or options.webapprtChrome:
@@ -309,16 +311,20 @@ class MochitestUtilsMixin(object):
         self.urlOpts.append("fileLevel=" + encodeURIComponent(options.fileLevel))
       if options.consoleLevel:
         self.urlOpts.append("consoleLevel=" + encodeURIComponent(options.consoleLevel))
       if options.totalChunks:
         self.urlOpts.append("totalChunks=%d" % options.totalChunks)
         self.urlOpts.append("thisChunk=%d" % options.thisChunk)
       if options.chunkByDir:
         self.urlOpts.append("chunkByDir=%d" % options.chunkByDir)
+      if options.startAt:
+        self.urlOpts.append("startAt=%s" % options.startAt)
+      if options.endAt:
+        self.urlOpts.append("endAt=%s" % options.endAt)
       if options.shuffle:
         self.urlOpts.append("shuffle=1")
       if "MOZ_HIDE_RESULTS_TABLE" in env and env["MOZ_HIDE_RESULTS_TABLE"] == "1":
         self.urlOpts.append("hideResultsTable=1")
       if options.runUntilFailure:
         self.urlOpts.append("runUntilFailure=1")
       if options.repeat:
         self.urlOpts.append("repeat=%d" % options.repeat)
--- a/testing/mochitest/tests/SimpleTest/setup.js
+++ b/testing/mochitest/tests/SimpleTest/setup.js
@@ -137,16 +137,20 @@ RunSet.runall = function(e) {
     RunSet.runtests();
   }
 }
 
 RunSet.runtests = function(e) {
   // Which tests we're going to run
   var my_tests = gTestList;
 
+  if (params.startAt || params.endAt) {
+    my_tests = skipTests(my_tests, params.startAt, params.endAt);
+  }
+
   if (params.totalChunks && params.thisChunk) {
     my_tests = chunkifyTests(my_tests, params.totalChunks, params.thisChunk, params.chunkByDir, TestRunner.logger);
   }
 
   if (params.shuffle) {
     for (var i = my_tests.length-1; i > 0; --i) {
       var j = Math.floor(Math.random() * i);
       var tmp = my_tests[j];
--- a/toolkit/content/browser-child.js
+++ b/toolkit/content/browser-child.js
@@ -109,67 +109,68 @@ let WebNavigation =  {
 
   init: function() {
     addMessageListener("WebNavigation:GoBack", this);
     addMessageListener("WebNavigation:GoForward", this);
     addMessageListener("WebNavigation:GotoIndex", this);
     addMessageListener("WebNavigation:LoadURI", this);
     addMessageListener("WebNavigation:Reload", this);
     addMessageListener("WebNavigation:Stop", this);
+
+    // Send a CPOW for the sessionHistory object.
+    let history = this._webNavigation.sessionHistory;
+    sendAsyncMessage("WebNavigation:setHistory", {}, {history: history});
   },
 
   receiveMessage: function(message) {
     switch (message.name) {
       case "WebNavigation:GoBack":
         this.goBack();
         break;
       case "WebNavigation:GoForward":
         this.goForward();
         break;
       case "WebNavigation:GotoIndex":
-        this.gotoIndex(message);
+        this.gotoIndex(message.data.index);
         break;
       case "WebNavigation:LoadURI":
-        this.loadURI(message);
+        this.loadURI(message.data.uri, message.data.flags);
         break;
       case "WebNavigation:Reload":
-        this.reload(message);
+        this.reload(message.data.flags);
         break;
       case "WebNavigation:Stop":
-        this.stop(message);
+        this.stop(message.data.flags);
         break;
     }
   },
 
   goBack: function() {
     if (this._webNavigation.canGoBack)
       this._webNavigation.goBack();
   },
 
   goForward: function() {
     if (this._webNavigation.canGoForward)
       this._webNavigation.goForward();
   },
 
-  gotoIndex: function(message) {
-    this._webNavigation.gotoIndex(message.index);
+  gotoIndex: function(index) {
+    this._webNavigation.gotoIndex(index);
   },
 
-  loadURI: function(message) {
-    let flags = message.json.flags || this._webNavigation.LOAD_FLAGS_NONE;
-    this._webNavigation.loadURI(message.json.uri, flags, null, null, null);
+  loadURI: function(uri, flags) {
+    this._webNavigation.loadURI(uri, flags, null, null, null);
   },
 
-  reload: function(message) {
-    let flags = message.json.flags || this._webNavigation.LOAD_FLAGS_NONE;
+  reload: function(flags) {
     this._webNavigation.reload(flags);
   },
 
-  stop: function(message) {
-    let flags = message.json.flags || this._webNavigation.STOP_ALL;
+  stop: function(flags) {
     this._webNavigation.stop(flags);
   }
 };
 
 WebNavigation.init();
 
 let SecurityUI = {
   getSSLStatusAsString: function() {
@@ -222,8 +223,12 @@ addEventListener("ImageContentLoaded", f
     if (!req.image)
       return;
     sendAsyncMessage("ImageDocumentLoaded", { width: req.image.width,
                                               height: req.image.height });
   }
 }, false);
 
 RemoteAddonsChild.init(this);
+
+addMessageListener("History:UseGlobalHistory", function (aMessage) {
+  docShell.useGlobalHistory = aMessage.data.enabled;
+});
--- a/toolkit/content/widgets/remote-browser.xml
+++ b/toolkit/content/widgets/remote-browser.xml
@@ -28,28 +28,19 @@
                         createInstance(Ci.nsISupportsInterfacePointer);
           ptr.data = this._securityUI;
           return ptr.data.QueryInterface(Ci.nsISecureBrowserUI);
         ]]></getter>
       </property>
 
       <field name="_remoteWebNavigation">null</field>
 
-      <property name="webNavigation" readonly="true">
-        <getter>
-          <![CDATA[
-            if (!this._remoteWebNavigation) {
-              let jsm = "resource://gre/modules/RemoteWebNavigation.jsm";
-              let RemoteWebNavigation = Cu.import(jsm, {}).RemoteWebNavigation;
-              this._remoteWebNavigation = new RemoteWebNavigation(this);
-            }
-            return this._remoteWebNavigation;
-          ]]>
-        </getter>
-      </property>
+      <property name="webNavigation"
+                onget="return this._remoteWebNavigation;"
+                readonly="true"/>
 
       <field name="_remoteWebProgress">null</field>
 
       <property name="webProgress" readonly="true">
       	<getter>
       	  <![CDATA[
             if (!this._remoteWebProgress) {
               let jsm = "resource://gre/modules/RemoteWebProgress.jsm";
@@ -106,34 +97,42 @@
       <field name="_imageDocument">null</field>
 
       <property name="imageDocument"
                 onget="return this._imageDocument"
                 readonly="true"/>
 
       <constructor>
         <![CDATA[
+          let jsm = "resource://gre/modules/RemoteWebNavigation.jsm";
+          let RemoteWebNavigation = Cu.import(jsm, {}).RemoteWebNavigation;
+          this._remoteWebNavigation = new RemoteWebNavigation(this);
+
           this.messageManager.addMessageListener("DOMTitleChanged", this);
           this.messageManager.addMessageListener("ImageDocumentLoaded", this);
           this.messageManager.loadFrameScript("chrome://global/content/browser-child.js", true);
 
           if (this.hasAttribute("selectpopup")) {
             this.messageManager.addMessageListener("Forms:ShowDropDown", this);
             this.messageManager.addMessageListener("Forms:HideDropDown", this);
             this.messageManager.loadFrameScript("chrome://global/content/select-child.js", true);
           }
 
-          let jsm = "resource://gre/modules/RemoteController.jsm";
+          jsm = "resource://gre/modules/RemoteController.jsm";
           let RemoteController = Components.utils.import(jsm, {}).RemoteController;
           this._controller = new RemoteController(this);
           this.controllers.appendController(this._controller);
 
           jsm = "resource://gre/modules/RemoteAddonsParent.jsm";
           let RemoteAddonsParent = Components.utils.import(jsm, {}).RemoteAddonsParent;
           RemoteAddonsParent.init();
+
+          if (!this.hasAttribute("disableglobalhistory")) {
+            this.messageManager.sendAsyncMessage("History:UseGlobalHistory", {enabled:true});
+          }
         ]]>
       </constructor>
 
       <method name="receiveMessage">
         <parameter name="aMessage"/>
         <body><![CDATA[
           let data = aMessage.data;
           switch (aMessage.name) {
--- a/toolkit/devtools/apps/app-actor-front.js
+++ b/toolkit/devtools/apps/app-actor-front.js
@@ -248,8 +248,29 @@ function getTargetForApp(client, webapps
         deferred.reject(error);
       });
     }
   });
   return deferred.promise;
 }
 exports.getTargetForApp = getTargetForApp;
 
+function reloadApp(client, webappsActor, manifestURL) {
+  let deferred = promise.defer();
+  getTargetForApp(client,
+                  webappsActor,
+                  manifestURL).
+    then((target) => {
+      // Request the ContentAppActor to reload the app
+      let request = {
+        to: target.form.actor,
+        type: "reload",
+        manifestURL: manifestURL
+      };
+      client.request(request, (res) => {
+        deferred.resolve();
+      });
+    }, () => {
+     deferred.reject("Not running");
+    });
+  return deferred.promise;
+}
+exports.reloadApp = reloadApp;
--- a/toolkit/devtools/server/actors/webapps.js
+++ b/toolkit/devtools/server/actors/webapps.js
@@ -413,22 +413,51 @@ WebappsActor.prototype = {
           let installDir = DOMApplicationRegistry._getAppDir(id);
           let manFile = installDir.clone();
           manFile.append("manifest.webapp");
           zipReader.extract("manifest.webapp", manFile);
           zipReader.close();
           zipFile.moveTo(installDir, "application.zip");
 
           let origin = "app://" + id;
+          let manifestURL = origin + "/manifest.webapp";
+
+          // Refresh application.zip content (e.g. reinstall app), as done here:
+          // http://hg.mozilla.org/mozilla-central/annotate/aaefec5d34f8/dom/apps/src/Webapps.jsm#l1125
+          // Do it in parent process for the simulator
+          let jar = installDir.clone();
+          jar.append("application.zip");
+          Services.obs.notifyObservers(jar, "flush-cache-entry", null);
+
+          // And then in app content process
+          // This function will be evaluated in the scope of the content process
+          // frame script. That will flush the jar cache for this app and allow
+          // loading fresh updated resources if we reload its document.
+          let FlushFrameScript = function (path) {
+            let jar = Components.classes["@mozilla.org/file/local;1"]
+                                .createInstance(Components.interfaces.nsILocalFile);
+            jar.initWithPath(path);
+            let obs = Components.classes["@mozilla.org/observer-service;1"]
+                                .getService(Components.interfaces.nsIObserverService);
+            obs.notifyObservers(jar, "flush-cache-entry", null);
+          };
+          for each (let frame in self._appFrames()) {
+            if (frame.getAttribute("mozapp") == manifestURL) {
+              let mm = frame.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
+              mm.loadFrameScript("data:," +
+                encodeURIComponent("(" + FlushFrameScript.toString() + ")" +
+                                   "('" + jar.path + "')"), false);
+            }
+          }
 
           // Create a fake app object with the minimum set of properties we need.
           let app = {
             origin: origin,
             installOrigin: origin,
-            manifestURL: origin + "/manifest.webapp",
+            manifestURL: manifestURL,
             appStatus: appType,
             receipts: aReceipts,
           }
 
           self._registerApp(deferred, app, id, aDir);
         } catch(e) {
           // If anything goes wrong, just send it back.
           self._sendError(deferred, e.toString(), aId);
@@ -734,16 +763,20 @@ WebappsActor.prototype = {
     }
 
     reg.close(app);
 
     return {};
   },
 
   _appFrames: function () {
+    // For now, we only support app frames on b2g
+    if (Services.appinfo.ID != "{3c2e2abc-06d4-11e1-ac3b-374f68613e61}") {
+      return;
+    }
     // Register the system app
     let chromeWindow = Services.wm.getMostRecentWindow('navigator:browser');
     let systemAppFrame = chromeWindow.shell.contentBrowser;
     yield systemAppFrame;
 
     // Register apps hosted in the system app. i.e. the homescreen, all regular
     // apps and the keyboard.
     // Bookmark apps and other system app internal frames like captive portal
--- a/toolkit/modules/RemoteWebNavigation.jsm
+++ b/toolkit/modules/RemoteWebNavigation.jsm
@@ -6,19 +6,27 @@
 this.EXPORTED_SYMBOLS = ["RemoteWebNavigation"];
 
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+function makeURI(url)
+{
+  return Cc["@mozilla.org/network/io-service;1"].
+         getService(Ci.nsIIOService).
+         newURI(url, null, null);
+}
+
 function RemoteWebNavigation(browser)
 {
   this._browser = browser;
+  this._browser.messageManager.addMessageListener("WebNavigation:setHistory", this);
 }
 
 RemoteWebNavigation.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebNavigation, Ci.nsISupports]),
 
   LOAD_FLAGS_MASK: 65535,
   LOAD_FLAGS_NONE: 0,
   LOAD_FLAGS_IS_REFRESH: 16,
@@ -37,39 +45,67 @@ RemoteWebNavigation.prototype = {
   LOAD_FLAGS_FORCE_ALLOW_COOKIES: 131072,
 
   STOP_NETWORK: 1,
   STOP_CONTENT: 2,
   STOP_ALL: 3,
 
   canGoBack: false,
   canGoForward: false,
-  goBack: function() { this._sendMessage("WebNavigation:GoBack", {}); },
-  goForward: function() { this._sendMessage("WebNavigation:GoForward", {}); },
-  gotoIndex: function(aIndex) { this._sendMessage("WebNavigation:GotoIndex", {index: aIndex}); },
+  goBack: function() {
+    this._sendMessage("WebNavigation:GoBack", {});
+  },
+  goForward: function() {
+    this._sendMessage("WebNavigation:GoForward", {});
+  },
+  gotoIndex: function(aIndex) {
+    this._sendMessage("WebNavigation:GotoIndex", {index: aIndex});
+  },
   loadURI: function(aURI, aLoadFlags, aReferrer, aPostData, aHeaders) {
     this._browser._contentTitle = "";
     this._sendMessage("WebNavigation:LoadURI", {uri: aURI, flags: aLoadFlags});
   },
-  reload: function(aReloadFlags) { this._sendMessage("WebNavigation:Reload", {flags: aReloadFlags}); },
-  stop: function(aStopFlags) { this._sendMessage("WebNavigation:Stop", {flags: aStopFlags}); },
-  get document() { return this._browser.contentDocument; },
+  reload: function(aReloadFlags) {
+    this._sendMessage("WebNavigation:Reload", {flags: aReloadFlags});
+  },
+  stop: function(aStopFlags) {
+    this._sendMessage("WebNavigation:Stop", {flags: aStopFlags});
+  },
+
+  get document() {
+    return this._browser.contentDocument;
+  },
+
+  _currentURI: null,
   get currentURI() {
-    if (!this._currentURI)
-       this._currentURI = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService).newURI("about:blank", null, null);
+    if (!this._currentURI) {
+      this._currentURI = makeURI("about:blank");
+    }
 
     return this._currentURI;
   },
-  set currentURI(aURI) { this.loadURI(aURI.spec, null, null, null); },
+  set currentURI(aURI) {
+    this.loadURI(aURI.spec, null, null, null);
+  },
+
   referringURI: null,
-  get sessionHistory() { return null; },
+
+  _sessionHistory: null,
+  get sessionHistory() { return this._sessionHistory; },
   set sessionHistory(aValue) { },
 
-  _currentURI: null,
   _sendMessage: function(aMessage, aData) {
     try {
       this._browser.messageManager.sendAsyncMessage(aMessage, aData);
     }
     catch (e) {
       Cu.reportError(e);
     }
+  },
+
+  receiveMessage: function(aMessage) {
+    switch (aMessage.name) {
+      case "WebNavigation:setHistory":
+        this._sessionHistory = aMessage.objects.history;
+        break;
+    }
   }
 };
rename from toolkit/mozapps/update/tests/unit_aus_update/downloadMar.js
rename to toolkit/mozapps/update/tests/unit_aus_update/downloadAndHashCheckMar.js
--- a/toolkit/mozapps/update/tests/unit_aus_update/downloadMar.js
+++ b/toolkit/mozapps/update/tests/unit_aus_update/downloadAndHashCheckMar.js
@@ -1,31 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-/* General MAR File Download Tests */
-
-const INC_CONTRACT_ID = "@mozilla.org/network/incremental-download;1";
-
 var gNextRunFunc;
-var gStatusResult;
 var gExpectedStatusResult;
-var gIncrementalDownloadClassID, gIncOldFactory;
-
-// gIncrementalDownloadErrorType is used to loop through each of the connection
-// error types in the Mock incremental downloader.
-var gIncrementalDownloadErrorType = 0;
 
 function run_test() {
   setupTestCommon(true);
 
-  logTestInfo("testing mar downloads, mar hash verification, and " +
-              "mar download interrupted recovery");
+  logTestInfo("testing mar download and mar hash verification");
 
   Services.prefs.setBoolPref(PREF_APP_UPDATE_STAGING_ENABLED, false);
   // The HTTP server is only used for the mar file downloads since it is slow
   start_httpserver();
   setUpdateURLOverride(gURLData + "update.xml");
   // The mock XMLHttpRequest is MUCH faster
   overrideXHR(callHandleEvent);
   standardInit();
@@ -33,17 +22,16 @@ function run_test() {
 }
 
 // The HttpServer must be stopped before calling do_test_finished
 function finish_test() {
   stop_httpserver(do_test_finished);
 }
 
 function end_test() {
-  cleanupMockIncrementalDownload();
   cleanupTestCommon();
 }
 
 // Callback function used by the custom XMLHttpRequest implementation to
 // call the nsIDOMEventListener's handleEvent method for onload.
 function callHandleEvent() {
   gXHR.status = 400;
   gXHR.responseText = gResponseBody;
@@ -186,17 +174,17 @@ function run_test_pt8() {
 
 // mar download with a valid SHA512 hash
 function run_test_pt9() {
   setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR);
   run_test_helper_pt1("mar download with a valid SHA512 hash",
                       AUS_Cr.NS_OK, run_test_pt10);
 }
 
-// mar download with an invalid SHA384 hash
+// mar download with an invalid SHA512 hash
 function run_test_pt10() {
   setResponseBody("SHA512", SHA512_HASH_SIMPLE_MAR + "0");
   run_test_helper_pt1("mar download with an invalid SHA512 hash",
                       AUS_Cr.NS_ERROR_CORRUPTED_CONTENT, run_test_pt11);
 }
 
 // mar download with the mar not found
 function run_test_pt11() {
@@ -214,229 +202,14 @@ function run_test_pt12() {
   if (IS_TOOLKIT_GONK) {
     // There seems to be a race on the web server side when the patchFile is
     // stored on the SDCard. Sometimes, the webserver will serve up an error
     // 416 and the contents of the file, and sometimes it will serve up an error
     // 200 and no contents. This can cause either NS_ERROR_UNEXPECTED or
     // NS_ERROR_CONTENT_CORRUPTED.
     // Bug 828858 was filed to follow up on this issue.
     run_test_helper_bug828858_pt1("mar download with a valid MD5 hash but invalid file size",
-                                  AUS_Cr.NS_ERROR_UNEXPECTED, run_test_pt13);
+                                  AUS_Cr.NS_ERROR_UNEXPECTED, finish_test);
   } else {
     run_test_helper_pt1("mar download with a valid MD5 hash but invalid file size",
-                        AUS_Cr.NS_ERROR_UNEXPECTED, run_test_pt13);
+                        AUS_Cr.NS_ERROR_UNEXPECTED, finish_test);
   }
 }
-
-var newFactory = {
-  createInstance: function(aOuter, aIID) {
-    if (aOuter)
-      throw Components.results.NS_ERROR_NO_AGGREGATION;
-    return new IncrementalDownload().QueryInterface(aIID);
-  },
-  lockFactory: function(aLock) {
-    throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-  },
-  QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIFactory])
-};
-
-function initMockIncrementalDownload() {
-  var registrar = AUS_Cm.QueryInterface(AUS_Ci.nsIComponentRegistrar);
-  gIncrementalDownloadClassID = registrar.contractIDToCID(INC_CONTRACT_ID);
-  gIncOldFactory = AUS_Cm.getClassObject(AUS_Cc[INC_CONTRACT_ID],
-                                         AUS_Ci.nsIFactory);
-  registrar.unregisterFactory(gIncrementalDownloadClassID, gIncOldFactory);
-  var components = [IncrementalDownload];
-  registrar.registerFactory(gIncrementalDownloadClassID, "",
-                            INC_CONTRACT_ID, newFactory);
-}
-
-function cleanupMockIncrementalDownload() {
-  if (gIncOldFactory) {
-    var registrar = AUS_Cm.QueryInterface(AUS_Ci.nsIComponentRegistrar);
-    registrar.unregisterFactory(gIncrementalDownloadClassID, newFactory);
-    registrar.registerFactory(gIncrementalDownloadClassID, "",
-                              INC_CONTRACT_ID, gIncOldFactory);
-  }
-  gIncOldFactory = null;
-}
-
-/* This Mock incremental downloader is used to verify that connection
- * interrupts work correctly in updater code.  The implementation of
- * the mock incremental downloader is very simple, it simply copies
- * the file to the destination location.
-*/
-
-function IncrementalDownload() {
-  this.wrappedJSObject = this;
-}
-
-IncrementalDownload.prototype = {
-  QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIIncrementalDownload]),
-
-  /* nsIIncrementalDownload */
-  init: function(uri, file, chunkSize, intervalInSeconds) {
-    this._destination = file;
-    this._URI = uri;
-    this._finalURI = uri;
-  },
-
-  start: function(observer, ctxt) {
-    var tm = Components.classes["@mozilla.org/thread-manager;1"].
-                        getService(AUS_Ci.nsIThreadManager);
-    // Do the actual operation async to give a chance for observers
-    // to add themselves.
-    tm.mainThread.dispatch(function() {
-        this._observer = observer.QueryInterface(AUS_Ci.nsIRequestObserver);
-        this._ctxt = ctxt;
-        this._observer.onStartRequest(this, this.ctxt);
-        let mar = getTestDirFile(FILE_SIMPLE_MAR);
-        mar.copyTo(this._destination.parent, this._destination.leafName);
-        var status = AUS_Cr.NS_OK
-        switch (gIncrementalDownloadErrorType++) {
-          case 0:
-            status = AUS_Cr.NS_ERROR_NET_RESET;
-          break;
-          case 1:
-            status = AUS_Cr.NS_ERROR_CONNECTION_REFUSED;
-          break;
-          case 2:
-            status = AUS_Cr.NS_ERROR_NET_RESET;
-          break;
-          case 3:
-            status = AUS_Cr.NS_OK;
-            break;
-          case 4:
-            status = AUS_Cr.NS_ERROR_OFFLINE;
-            // After we report offline, we want to eventually show offline
-            // status being changed to online.
-            var tm = Components.classes["@mozilla.org/thread-manager;1"].
-                                getService(AUS_Ci.nsIThreadManager);
-            tm.mainThread.dispatch(function() {
-              Services.obs.notifyObservers(gAUS,
-                                           "network:offline-status-changed",
-                                           "online");
-            }, AUS_Ci.nsIThread.DISPATCH_NORMAL);
-          break;
-        }
-        this._observer.onStopRequest(this, this._ctxt, status);
-      }.bind(this), AUS_Ci.nsIThread.DISPATCH_NORMAL);
-  },
-
-  get URI() {
-    return this._URI;
-  },
-
-  get currentSize() {
-    throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-
-  get destination() {
-    return this._destination;
-  },
-
-  get finalURI() {
-    return this._finalURI;
-  },
-
-  get totalSize() {
-    throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-
-  /* nsIRequest */
-  cancel: function(aStatus) {
-    throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-  suspend: function() {
-    throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-  isPending: function() {
-    throw AUS_Cr.NS_ERROR_NOT_IMPLEMENTED;
-  },
-  _loadFlags: 0,
-  get loadFlags() {
-    return this._loadFlags;
-  },
-  set loadFlags(val) {
-    this._loadFlags = val;
-  },
-
-  _loadGroup: null,
-  get loadGroup() {
-    return this._loadGroup;
-  },
-  set loadGroup(val) {
-    this._loadGroup = val;
-  },
-
-  _name: "",
-  get name() {
-    return this._name;
-  },
-
-  _status: 0,
-  get status() {
-    return this._status;