Merge mc -> pine draft
authorGregor Wagner <anygregor@gmail.com>
Mon, 28 Apr 2014 11:14:47 -0700
changeset 388086 ec705a757f2260a404d4039654fd40d0679bed04
parent 388085 3a360d5eacc8ffa84f87018532f6e3a04f230f31 (current diff)
parent 180520 cfde3603b0206e119abea76fdd6e134b634348f1 (diff)
child 388087 726e2384c5384fbb28655434e9ae1d6ae92cdb79
push id23132
push userbmo:lissyx+mozillians@lissyx.dyndns.org
push dateFri, 15 Jul 2016 10:07:12 +0000
milestone31.0a1
Merge mc -> pine
addon-sdk/source/lib/sdk/tabs/tabs.js
browser/components/customizableui/test/browser_947914_button_addons.js
browser/components/customizableui/test/browser_947914_button_copy.js
browser/components/customizableui/test/browser_947914_button_cut.js
browser/components/customizableui/test/browser_947914_button_find.js
browser/components/customizableui/test/browser_947914_button_history.js
browser/components/customizableui/test/browser_947914_button_newPrivateWindow.js
browser/components/customizableui/test/browser_947914_button_newWindow.js
browser/components/customizableui/test/browser_947914_button_paste.js
browser/components/customizableui/test/browser_947914_button_print.js
browser/components/customizableui/test/browser_947914_button_savePage.js
browser/components/customizableui/test/browser_947914_button_zoomIn.js
browser/components/customizableui/test/browser_947914_button_zoomOut.js
browser/components/customizableui/test/browser_947914_button_zoomReset.js
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/browser-element/nsIAsyncScrollEventDetail.idl
dom/ipc/PreallocatedProcessManager.cpp
js/src/jsgc.cpp
uriloader/exthandler/ExternalHelperAppParent.cpp
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -36,17 +36,17 @@ AccEvent::AccEvent(uint32_t aEventType, 
     mIsFromUserInput = EventStateManager::IsHandlingUserInput();
   else
     mIsFromUserInput = aIsFromUserInput == eFromUserInput ? true : false;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent cycle collection
 
-NS_IMPL_CYCLE_COLLECTION_1(AccEvent, mAccessible)
+NS_IMPL_CYCLE_COLLECTION(AccEvent, mAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AccEvent, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AccEvent, Release)
 
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 // AccTextChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/base/DocManager.cpp
+++ b/accessible/src/base/DocManager.cpp
@@ -113,20 +113,20 @@ DocManager::Shutdown()
     progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
 
   ClearDocCache();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS3(DocManager,
-                   nsIWebProgressListener,
-                   nsIDOMEventListener,
-                   nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS(DocManager,
+                  nsIWebProgressListener,
+                  nsIDOMEventListener,
+                  nsISupportsWeakReference)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIWebProgressListener
 
 NS_IMETHODIMP
 DocManager::OnStateChange(nsIWebProgress* aWebProgress,
                           nsIRequest* aRequest, uint32_t aStateFlags,
                           nsresult aStatus)
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -403,18 +403,18 @@ NotificationController::ContentInsertion
     }
 
     node = node->GetNextSibling();
   }
 
   return haveToUpdate;
 }
 
-NS_IMPL_CYCLE_COLLECTION_1(NotificationController::ContentInsertion,
-                           mContainer)
+NS_IMPL_CYCLE_COLLECTION(NotificationController::ContentInsertion,
+                         mContainer)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NotificationController::ContentInsertion,
                                      AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NotificationController::ContentInsertion,
                                        Release)
 
 void
 NotificationController::ContentInsertion::Process()
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -147,22 +147,22 @@ nsAccessibilityService::~nsAccessibility
 {
   NS_ASSERTION(gIsShutdown, "Accessibility wasn't shutdown!");
   gAccessibilityService = nullptr;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED4(nsAccessibilityService,
-                             DocManager,
-                             nsIAccessibilityService,
-                             nsIAccessibleRetrieval,
-                             nsIObserver,
-                             nsISelectionListener) // from SelectionManager
+NS_IMPL_ISUPPORTS_INHERITED(nsAccessibilityService,
+                            DocManager,
+                            nsIAccessibilityService,
+                            nsIAccessibleRetrieval,
+                            nsIObserver,
+                            nsISelectionListener) // from SelectionManager
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIObserver
 
 NS_IMETHODIMP
 nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
                          const char16_t *aData)
 {
@@ -251,17 +251,17 @@ public:
     sPluginTimers->RemoveElement(aTimer);
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIContent> mContent;
 };
 
-NS_IMPL_ISUPPORTS1(PluginTimerCallBack, nsITimerCallback)
+NS_IMPL_ISUPPORTS(PluginTimerCallBack, nsITimerCallback)
 #endif
 
 already_AddRefed<Accessible>
 nsAccessibilityService::CreatePluginAccessible(nsObjectFrame* aFrame,
                                                nsIContent* aContent,
                                                Accessible* aContext)
 {
   // nsObjectFrame means a plugin, so we need to use the accessibility support
--- a/accessible/src/base/nsAccessiblePivot.cpp
+++ b/accessible/src/base/nsAccessiblePivot.cpp
@@ -43,17 +43,17 @@ nsAccessiblePivot::nsAccessiblePivot(Acc
   mStartOffset(-1), mEndOffset(-1)
 {
   NS_ASSERTION(aRoot, "A root accessible is required");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_3(nsAccessiblePivot, mRoot, mPosition, mObservers)
+NS_IMPL_CYCLE_COLLECTION(nsAccessiblePivot, mRoot, mPosition, mObservers)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsAccessiblePivot)
   NS_INTERFACE_MAP_ENTRY(nsIAccessiblePivot)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessiblePivot)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAccessiblePivot)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAccessiblePivot)
--- a/accessible/src/generic/ARIAGridAccessible.cpp
+++ b/accessible/src/generic/ARIAGridAccessible.cpp
@@ -30,19 +30,19 @@ ARIAGridAccessible::
   ARIAGridAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   AccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED1(ARIAGridAccessible,
-                             Accessible,
-                             nsIAccessibleTable)
+NS_IMPL_ISUPPORTS_INHERITED(ARIAGridAccessible,
+                            Accessible,
+                            nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible
 
 void
 ARIAGridAccessible::Shutdown()
 {
   mTable = nullptr;
@@ -535,19 +535,19 @@ ARIAGridCellAccessible::
   HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
 {
   mGenericTypes |= eTableCell;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED1(ARIAGridCellAccessible,
-                             HyperTextAccessible,
-                             nsIAccessibleTableCell)
+NS_IMPL_ISUPPORTS_INHERITED(ARIAGridCellAccessible,
+                            HyperTextAccessible,
+                            nsIAccessibleTableCell)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleTableCell
 
 TableAccessible*
 ARIAGridCellAccessible::Table() const
 {
   Accessible* table = TableFor(Row());
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -86,18 +86,18 @@
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible: nsISupports and cycle collection
 
-NS_IMPL_CYCLE_COLLECTION_3(Accessible,
-                           mContent, mParent, mChildren)
+NS_IMPL_CYCLE_COLLECTION(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())
--- a/accessible/src/generic/ApplicationAccessible.cpp
+++ b/accessible/src/generic/ApplicationAccessible.cpp
@@ -28,18 +28,18 @@ ApplicationAccessible::ApplicationAccess
 {
   mType = eApplicationType;
   mAppInfo = do_GetService("@mozilla.org/xre/app-info;1");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED1(ApplicationAccessible, Accessible,
-                             nsIAccessibleApplication)
+NS_IMPL_ISUPPORTS_INHERITED(ApplicationAccessible, Accessible,
+                            nsIAccessibleApplication)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
 
 NS_IMETHODIMP
 ApplicationAccessible::GetParent(nsIAccessible** aAccessible)
 {
   NS_ENSURE_ARG_POINTER(aAccessible);
--- a/accessible/src/generic/FormControlAccessible.cpp
+++ b/accessible/src/generic/FormControlAccessible.cpp
@@ -27,19 +27,19 @@ template class mozilla::a11y::ProgressMe
 
 template<int Max>
 NS_IMPL_ADDREF_INHERITED(ProgressMeterAccessible<Max>, LeafAccessible)
 
 template<int Max>
 NS_IMPL_RELEASE_INHERITED(ProgressMeterAccessible<Max>, LeafAccessible)
 
 template<int Max>
-NS_IMPL_QUERY_INTERFACE_INHERITED1(ProgressMeterAccessible<Max>,
-                                   LeafAccessible,
-                                   nsIAccessibleValue)
+NS_IMPL_QUERY_INTERFACE_INHERITED(ProgressMeterAccessible<Max>,
+                                  LeafAccessible,
+                                  nsIAccessibleValue)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible
 
 template<int Max>
 role
 ProgressMeterAccessible<Max>::NativeRole()
 {
--- a/accessible/src/generic/ImageAccessible.cpp
+++ b/accessible/src/generic/ImageAccessible.cpp
@@ -30,18 +30,18 @@ using namespace mozilla::a11y;
 
 ImageAccessible::
   ImageAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   LinkableAccessible(aContent, aDoc)
 {
   mType = eImageType;
 }
 
-NS_IMPL_ISUPPORTS_INHERITED1(ImageAccessible, Accessible,
-                             nsIAccessibleImage)
+NS_IMPL_ISUPPORTS_INHERITED(ImageAccessible, Accessible,
+                            nsIAccessibleImage)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible public
 
 uint64_t
 ImageAccessible::NativeState()
 {
   // The state is a bitfield, get our inherited state, then logically OR it with
--- a/accessible/src/generic/RootAccessible.cpp
+++ b/accessible/src/generic/RootAccessible.cpp
@@ -48,17 +48,17 @@
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 using namespace mozilla::dom;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED1(RootAccessible, DocAccessible, nsIAccessibleDocument)
+NS_IMPL_ISUPPORTS_INHERITED(RootAccessible, DocAccessible, nsIAccessibleDocument)
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/destructor
 
 RootAccessible::
   RootAccessible(nsIDocument* aDocument, nsIContent* aRootContent,
                  nsIPresShell* aPresShell) :
   DocAccessibleWrap(aDocument, aRootContent, aPresShell)
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -287,20 +287,20 @@ HTMLButtonAccessible::IsWidget() const
 
 HTMLTextFieldAccessible::
   HTMLTextFieldAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc)
 {
   mType = eHTMLTextFieldType;
 }
 
-NS_IMPL_ISUPPORTS_INHERITED2(HTMLTextFieldAccessible,
-                             Accessible,                             
-                             nsIAccessibleText,
-                             nsIAccessibleEditableText)
+NS_IMPL_ISUPPORTS_INHERITED(HTMLTextFieldAccessible,
+                            Accessible,                            
+                            nsIAccessibleText,
+                            nsIAccessibleEditableText)
 
 role
 HTMLTextFieldAccessible::NativeRole()
 {
   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
                             nsGkAtoms::password, eIgnoreCase)) {
     return roles::PASSWORD_TEXT;
   }
--- a/accessible/src/html/HTMLLinkAccessible.cpp
+++ b/accessible/src/html/HTMLLinkAccessible.cpp
@@ -23,18 +23,18 @@ using namespace mozilla::a11y;
 
 HTMLLinkAccessible::
   HTMLLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   HyperTextAccessibleWrap(aContent, aDoc)
 {
 }
 
 // Expose nsIAccessibleHyperLink unconditionally
-NS_IMPL_ISUPPORTS_INHERITED1(HTMLLinkAccessible, HyperTextAccessibleWrap,
-                             nsIAccessibleHyperLink)
+NS_IMPL_ISUPPORTS_INHERITED(HTMLLinkAccessible, HyperTextAccessibleWrap,
+                            nsIAccessibleHyperLink)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
 
 role
 HTMLLinkAccessible::NativeRole()
 {
   return roles::LINK;
--- a/accessible/src/html/HTMLTableAccessible.cpp
+++ b/accessible/src/html/HTMLTableAccessible.cpp
@@ -49,19 +49,19 @@ HTMLTableCellAccessible::
   HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
 {
   mGenericTypes |= eTableCell;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableCellAccessible: nsISupports implementation
 
-NS_IMPL_ISUPPORTS_INHERITED1(HTMLTableCellAccessible,
-                             HyperTextAccessible,
-                             nsIAccessibleTableCell)
+NS_IMPL_ISUPPORTS_INHERITED(HTMLTableCellAccessible,
+                            HyperTextAccessible,
+                            nsIAccessibleTableCell)
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableCellAccessible: Accessible implementation
 
 void
 HTMLTableCellAccessible::Shutdown()
 {
   mTableCell = nullptr;
@@ -355,18 +355,18 @@ HTMLTableRowAccessible::NativeRole()
 {
   return roles::ROW;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
-NS_IMPL_ISUPPORTS_INHERITED1(HTMLTableAccessible, Accessible,
-                             nsIAccessibleTable)
+NS_IMPL_ISUPPORTS_INHERITED(HTMLTableAccessible, Accessible,
+                            nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
 // HTMLTableAccessible: Accessible
 
 void
 HTMLTableAccessible::Shutdown()
 {
   mTable = nullptr;
--- a/accessible/src/xpcom/AccEventGen.py
+++ b/accessible/src/xpcom/AccEventGen.py
@@ -171,17 +171,17 @@ def allAttributes(iface):
         attributes.extend(attrs)
 
     return attributes
 
 def write_cpp(eventname, iface, fd):
     classname = "xpcAcc%s" % eventname
     attributes = allAttributes(iface)
     ccattributes = filter(lambda m: m.realtype.nativeType('in').endswith('*'), attributes)
-    fd.write("NS_IMPL_CYCLE_COLLECTION_%u(%s" % (len(ccattributes), classname))
+    fd.write("NS_IMPL_CYCLE_COLLECTION(%s" % classname)
     for c in ccattributes:
         fd.write(", m%s" % firstCap(c.name))
     fd.write(")\n\n");
 
     fd.write("NS_IMPL_CYCLE_COLLECTING_ADDREF(%s)\n" % classname)
     fd.write("NS_IMPL_CYCLE_COLLECTING_RELEASE(%s)\n\n" % classname)
 
     fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(%s)\n" % classname)
--- a/accessible/src/xpcom/nsAccessibleRelation.cpp
+++ b/accessible/src/xpcom/nsAccessibleRelation.cpp
@@ -19,17 +19,17 @@ nsAccessibleRelation::nsAccessibleRelati
 {
   mTargets = do_CreateInstance(NS_ARRAY_CONTRACTID);
   nsIAccessible* targetAcc = nullptr;
   while ((targetAcc = aRel->Next()))
     mTargets->AppendElement(targetAcc, false);
 }
 
 // nsISupports
-NS_IMPL_ISUPPORTS1(nsAccessibleRelation, nsIAccessibleRelation)
+NS_IMPL_ISUPPORTS(nsAccessibleRelation, nsIAccessibleRelation)
 
 // nsIAccessibleRelation
 NS_IMETHODIMP
 nsAccessibleRelation::GetRelationType(uint32_t *aType)
 {
   NS_ENSURE_ARG_POINTER(aType);
   *aType = mType;
   return NS_OK;
--- a/accessible/src/xpcom/xpcAccessibleTextRange.cpp
+++ b/accessible/src/xpcom/xpcAccessibleTextRange.cpp
@@ -9,20 +9,20 @@
 #include "HyperTextAccessible.h"
 #include "TextRange.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 // nsISupports and cycle collection
 
-NS_IMPL_CYCLE_COLLECTION_3(xpcAccessibleTextRange,
-                           mRange.mRoot,
-                           mRange.mStartContainer,
-                           mRange.mEndContainer)
+NS_IMPL_CYCLE_COLLECTION(xpcAccessibleTextRange,
+                         mRange.mRoot,
+                         mRange.mStartContainer,
+                         mRange.mEndContainer)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(xpcAccessibleTextRange)
   NS_INTERFACE_MAP_ENTRY(nsIAccessibleTextRange)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleTextRange)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(xpcAccessibleTextRange)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(xpcAccessibleTextRange)
--- a/accessible/src/xul/XULElementAccessibles.cpp
+++ b/accessible/src/xul/XULElementAccessibles.cpp
@@ -180,18 +180,18 @@ XULTooltipAccessible::NativeRole()
 
 XULLinkAccessible::
   XULLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) :
   XULLabelAccessible(aContent, aDoc)
 {
 }
 
 // Expose nsIAccessibleHyperLink unconditionally
-NS_IMPL_ISUPPORTS_INHERITED1(XULLinkAccessible, XULLabelAccessible,
-                             nsIAccessibleHyperLink)
+NS_IMPL_ISUPPORTS_INHERITED(XULLinkAccessible, XULLabelAccessible,
+                            nsIAccessibleHyperLink)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULLinkAccessible. nsIAccessible
 
 void
 XULLinkAccessible::Value(nsString& aValue)
 {
   aValue.Truncate();
--- a/accessible/src/xul/XULListboxAccessible.cpp
+++ b/accessible/src/xul/XULListboxAccessible.cpp
@@ -734,19 +734,19 @@ XULListCellAccessible::
   HyperTextAccessibleWrap(aContent, aDoc), xpcAccessibleTableCell(this)
 {
   mGenericTypes |= eTableCell;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED1(XULListCellAccessible,
-                             HyperTextAccessible,
-                             nsIAccessibleTableCell)
+NS_IMPL_ISUPPORTS_INHERITED(XULListCellAccessible,
+                            HyperTextAccessible,
+                            nsIAccessibleTableCell)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULListCellAccessible: nsIAccessibleTableCell implementation
 
 TableAccessible*
 XULListCellAccessible::Table() const
 {
   Accessible* thisRow = Parent();
--- a/accessible/src/xul/XULTreeAccessible.cpp
+++ b/accessible/src/xul/XULTreeAccessible.cpp
@@ -60,18 +60,18 @@ XULTreeAccessible::
     if (autoCompletePopupElm)
       mGenericTypes |= eAutoCompletePopup;
   }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeAccessible: nsISupports and cycle collection implementation
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_2(XULTreeAccessible, Accessible,
-                                     mTree, mAccessibleCache)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeAccessible, Accessible,
+                                   mTree, mAccessibleCache)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeAccessible)
 NS_INTERFACE_MAP_END_INHERITING(Accessible)
 
 NS_IMPL_ADDREF_INHERITED(XULTreeAccessible, Accessible)
 NS_IMPL_RELEASE_INHERITED(XULTreeAccessible, Accessible)
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -701,22 +701,22 @@ XULTreeItemAccessibleBase::
 {
   mParent = aParent;
   mStateFlags |= eSharedNode;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessibleBase: nsISupports implementation
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(XULTreeItemAccessibleBase, Accessible,
-                                     mTree)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase, Accessible,
+                                   mTree)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase)
-  NS_INTERFACE_TABLE_INHERITED1(XULTreeItemAccessibleBase,
-                                XULTreeItemAccessibleBase)
+  NS_INTERFACE_TABLE_INHERITED(XULTreeItemAccessibleBase,
+                               XULTreeItemAccessibleBase)
 NS_INTERFACE_TABLE_TAIL_INHERITING(Accessible)
 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessibleBase, Accessible)
 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessibleBase, Accessible)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessibleBase: nsIAccessible implementation
 
 Accessible*
@@ -1101,19 +1101,19 @@ XULTreeItemAccessible::
 {
   mColumn = nsCoreUtils::GetFirstSensibleColumn(mTree);
   GetCellName(mColumn, mCachedName);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessible: nsISupports implementation
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(XULTreeItemAccessible,
-                                     XULTreeItemAccessibleBase,
-                                     mColumn)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible,
+                                   XULTreeItemAccessibleBase,
+                                   mColumn)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible)
 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase)
 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessible: nsIAccessible implementation
--- a/accessible/src/xul/XULTreeGridAccessible.cpp
+++ b/accessible/src/xul/XULTreeGridAccessible.cpp
@@ -20,19 +20,19 @@
 #include "nsITreeSelection.h"
 #include "nsComponentManagerUtils.h"
 
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridAccessible: nsISupports implementation
 
-NS_IMPL_ISUPPORTS_INHERITED1(XULTreeGridAccessible,
-                             XULTreeAccessible,
-                             nsIAccessibleTable)
+NS_IMPL_ISUPPORTS_INHERITED(XULTreeGridAccessible,
+                            XULTreeAccessible,
+                            nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridAccessible: nsIAccessibleTable implementation
 
 uint32_t
 XULTreeGridAccessible::ColCount()
 {
   return nsCoreUtils::GetSensibleColumnCount(mTree);
@@ -260,19 +260,19 @@ XULTreeGridRowAccessible::
   mAccessibleCache(kDefaultTreeCacheSize)
 {
   mGenericTypes |= eTableRow;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridRowAccessible: nsISupports and cycle collection implementation
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(XULTreeGridRowAccessible,
-                                     XULTreeItemAccessibleBase,
-                                     mAccessibleCache)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible,
+                                   XULTreeItemAccessibleBase,
+                                   mAccessibleCache)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible)
 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
 
 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible,
                          XULTreeItemAccessibleBase)
 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
                           XULTreeItemAccessibleBase)
@@ -448,23 +448,23 @@ XULTreeGridCellAccessible::
     mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   else
     mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridCellAccessible: nsISupports implementation
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_2(XULTreeGridCellAccessible, LeafAccessible,
-                                     mTree, mColumn)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible, LeafAccessible,
+                                   mTree, mColumn)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible)
-  NS_INTERFACE_TABLE_INHERITED2(XULTreeGridCellAccessible,
-                                nsIAccessibleTableCell,
-                                XULTreeGridCellAccessible)
+  NS_INTERFACE_TABLE_INHERITED(XULTreeGridCellAccessible,
+                               nsIAccessibleTableCell,
+                               XULTreeGridCellAccessible)
 NS_INTERFACE_TABLE_TAIL_INHERITING(LeafAccessible)
 NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
 NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridCellAccessible: nsIAccessible implementation
 
 void
--- a/addon-sdk/source/lib/sdk/clipboard.js
+++ b/addon-sdk/source/lib/sdk/clipboard.js
@@ -76,18 +76,21 @@ exports.set = function(aData, aDataType)
   // data URL to detect a better datatype
   if (aData && (!aDataType || aDataType === "image")) {
     try {
       let dataURL = new DataURL(aData);
 
       options.datatype = dataURL.mimeType;
       options.data = dataURL.data;
     }
-    catch (e if e.name === "URIError") {
-      // Not a valid Data URL
+    catch (e) {
+      // Ignore invalid URIs
+      if (e.name !== "URIError") {
+        throw e;
+      }
     }
   }
 
   options = apiUtils.validateOptions(options, {
     data: {
       is: ["string"]
     },
     datatype: {
--- a/addon-sdk/source/lib/sdk/console/plain-text.js
+++ b/addon-sdk/source/lib/sdk/console/plain-text.js
@@ -7,17 +7,17 @@
 module.metadata = {
   "stability": "unstable"
 };
 
 const { Cc, Ci, Cu, Cr } = require("chrome");
 const self = require("../self");
 const prefs = require("../preferences/service");
 const { merge } = require("../util/object");
-const { ConsoleAPI } = Cu.import("resource://gre/modules/devtools/Console.jsm");
+const { ConsoleAPI } = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
 
 const DEFAULT_LOG_LEVEL = "error";
 const ADDON_LOG_LEVEL_PREF = "extensions." + self.id + ".sdk.console.logLevel";
 const SDK_LOG_LEVEL_PREF = "extensions.sdk.console.logLevel";
 
 let logLevel = DEFAULT_LOG_LEVEL;
 function setLogLevel() {
   logLevel = prefs.get(ADDON_LOG_LEVEL_PREF,
@@ -39,22 +39,23 @@ let logLevelObserver = {
   }
 };
 let branch = Cc["@mozilla.org/preferences-service;1"].
              getService(Ci.nsIPrefService).
              getBranch(null);
 branch.addObserver(ADDON_LOG_LEVEL_PREF, logLevelObserver, true);
 branch.addObserver(SDK_LOG_LEVEL_PREF, logLevelObserver, true);
 
-function PlainTextConsole(print) {
+function PlainTextConsole(print, innerID) {
 
   let consoleOptions = {
     prefix: self.name + ": ",
     maxLogLevel: logLevel,
-    dump: print
+    dump: print,
+    innerID: innerID
   };
   let console = new ConsoleAPI(consoleOptions);
 
   // As we freeze the console object, we can't modify this property afterward
   Object.defineProperty(console, "maxLogLevel", {
     get: function() {
       return logLevel;
     }
--- a/addon-sdk/source/lib/sdk/content/sandbox.js
+++ b/addon-sdk/source/lib/sdk/content/sandbox.js
@@ -14,16 +14,17 @@ const { requiresAddonGlobal } = require(
 const { delay: async } = require('../lang/functional');
 const { Ci, Cu, Cc } = require('chrome');
 const timer = require('../timers');
 const { URL } = require('../url');
 const { sandbox, evaluate, load } = require('../loader/sandbox');
 const { merge } = require('../util/object');
 const { getTabForContentWindow } = require('../tabs/utils');
 const { getInnerId } = require('../window/utils');
+const { PlainTextConsole } = require('../console/plain-text');
 
 // WeakMap of sandboxes so we can access private values
 const sandboxes = new WeakMap();
 
 /* Trick the linker in order to ensure shipping these files in the XPI.
   require('./content-worker.js');
   Then, retrieve URL of these files in the XPI:
 */
@@ -192,18 +193,20 @@ const WorkerSandbox = Class({
     let chromeAPI = createChromeAPI();
     let result = apiSandbox.ContentWorker.inject(content, chromeAPI, onEvent, options);
 
     // Merge `emitToContent` and `hasListenerFor` into our private
     // model of the WorkerSandbox so we can communicate with content
     // script
     merge(model, result);
 
+    let console = new PlainTextConsole(null, getInnerId(window));
+
     // Handle messages send by this script:
-    setListeners(this);
+    setListeners(this, console);
 
     // Inject `addon` global into target document if document is trusted,
     // `addon` in document is equivalent to `self` in content script.
     if (requiresAddonGlobal(worker)) {
       Object.defineProperty(getUnsafeWindow(window), 'addon', {
           value: content.self
         }
       );
@@ -299,17 +302,17 @@ function importScripts (workerSandbox, .
         throw Error('Unsupported `contentScriptFile` url: ' + String(uri));
     }
     catch(e) {
       emit(worker, 'error', e);
     }
   }
 }
 
-function setListeners (workerSandbox) {
+function setListeners (workerSandbox, console) {
   let { worker } = modelFor(workerSandbox);
   // console.xxx calls
   workerSandbox.on('console', function consoleListener (kind, ...args) {
     console[kind].apply(console, args);
   });
 
   // self.postMessage calls
   workerSandbox.on('message', function postMessage(data) {
--- a/addon-sdk/source/lib/sdk/core/promise.js
+++ b/addon-sdk/source/lib/sdk/core/promise.js
@@ -1,266 +1,51 @@
-;(function(id, factory) { // Module boilerplate :(
-  if (typeof(define) === 'function') { // RequireJS
-    define(factory);
-  } else if (typeof(require) === 'function') { // CommonJS
-    factory.call(this, require, exports, module);
-  } else if (String(this).indexOf('BackstagePass') >= 0) { // JSM
-    this[factory.name] = {};
-    try {
-      this.console = this['Components'].utils
-          .import('resource://gre/modules/devtools/Console.jsm', {}).console;
-    }
-    catch (ex) {
-      // Avoid failures on different toolkit configurations.
-    }
-    factory(function require(uri) {
-      var imports = {};
-      this['Components'].utils.import(uri, imports);
-      return imports;
-    }, this[factory.name], { uri: __URI__, id: id });
-    this.EXPORTED_SYMBOLS = [factory.name];
-  } else if (~String(this).indexOf('Sandbox')) { // Sandbox
-    factory(function require(uri) {}, this, { id: id });
-  } else {  // Browser or alike
-    var globals = this;
-    factory(function require(id) {
-      return globals[id];
-    }, (globals[id] = {}), { uri: document.location.href + '#' + id, id: id });
-  }
-}).call(this, 'promise/core', function Promise(require, exports, module) {
+/* 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';
 
+/*
+ * Uses `Promise.jsm` as a core implementation, with additional sugar
+ * from previous implementation, with inspiration from `Q` and `when`
+ *
+ * https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm
+ * https://github.com/cujojs/when
+ * https://github.com/kriskowal/q
+ */
+const PROMISE_URI = 'resource://gre/modules/Promise.jsm';
+
+getEnvironment.call(this, function ({ require, exports, module, Cu }) {
+
+const { defer, resolve, all, reject, race } = Cu.import(PROMISE_URI, {}).Promise;
+
 module.metadata = {
-  "stability": "unstable"
+  'stability': 'unstable'
 };
 
-/**
- * Internal utility: Wraps given `value` into simplified promise, successfully
- * fulfilled to a given `value`. Note the result is not a complete promise
- * implementation, as its method `then` does not returns anything.
- */
-function fulfilled(value) {
-  return { then: function then(fulfill) { fulfill(value); } };
-}
-
-/**
- * Internal utility: Wraps given input into simplified promise, pre-rejected
- * with a given `reason`. Note the result is not a complete promise
- * implementation, as its method `then` does not returns anything.
- */
-function rejected(reason) {
-  return { then: function then(fulfill, reject) { reject(reason); } };
-}
-
-/**
- * Internal utility: Returns `true` if given `value` is a promise. Value is
- * assumed to be a promise if it implements method `then`.
- */
-function isPromise(value) {
-  return value && typeof(value.then) === 'function';
-}
-
-/**
- * Creates deferred object containing fresh promise & methods to either resolve
- * or reject it. The result is an object with the following properties:
- * - `promise` Eventual value representation implementing CommonJS [Promises/A]
- *   (http://wiki.commonjs.org/wiki/Promises/A) API.
- * - `resolve` Single shot function that resolves enclosed `promise` with a
- *   given `value`.
- * - `reject` Single shot function that rejects enclosed `promise` with a given
- *   `reason`.
- *
- * An optional `prototype` argument is used as a prototype of the returned
- * `promise` allowing one to implement additional API. If prototype is not
- * passed then it falls back to `Object.prototype`.
- *
- *  ## Example
- *
- *  function fetchURI(uri, type) {
- *    var deferred = defer();
- *    var request = new XMLHttpRequest();
- *    request.open("GET", uri, true);
- *    request.responseType = type;
- *    request.onload = function onload() {
- *      deferred.resolve(request.response);
- *    }
- *    request.onerror = function(event) {
- *     deferred.reject(event);
- *    }
- *    request.send();
- *
- *    return deferred.promise;
- *  }
- */
-function defer(prototype) {
-  // Define FIFO queue of observer pairs. Once promise is resolved & all queued
-  // observers are forwarded to `result` and variable is set to `null`.
-  var observers = [];
-
-  // Promise `result`, which will be assigned a resolution value once promise
-  // is resolved. Note that result will always be assigned promise (or alike)
-  // object to take care of propagation through promise chains. If result is
-  // `null` promise is not resolved yet.
-  var result = null;
-
-  prototype = (prototype || prototype === null) ? prototype : Object.prototype;
-
-  // Create an object implementing promise API.
-  var promise = Object.create(prototype, {
-    then: { value: function then(onFulfill, onError) {
-      var deferred = defer(prototype);
-
-      function resolve(value) {
-        // If `onFulfill` handler is provided resolve `deferred.promise` with
-        // result of invoking it with a resolution value. If handler is not
-        // provided propagate value through.
-        try {
-          deferred.resolve(onFulfill ? onFulfill(value) : value);
-        }
-        // `onFulfill` may throw exception in which case resulting promise
-        // is rejected with thrown exception.
-        catch(error) {
-          if (exports._reportErrors && typeof(console) === 'object')
-            console.error(error);
-          // Note: Following is equivalent of `deferred.reject(error)`,
-          // we use this shortcut to reduce a stack.
-          deferred.resolve(rejected(error));
-        }
-      }
-
-      function reject(reason) {
-        try {
-          if (onError) deferred.resolve(onError(reason));
-          else deferred.resolve(rejected(reason));
-        }
-        catch(error) {
-          if (exports._reportErrors && typeof(console) === 'object')
-            console.error(error);
-          deferred.resolve(rejected(error));
-        }
-      }
-
-      // If enclosed promise (`this.promise`) observers queue is still alive
-      // enqueue a new observer pair into it. Note that this does not
-      // necessary means that promise is pending, it may already be resolved,
-      // but we still have to queue observers to guarantee an order of
-      // propagation.
-      if (observers) {
-        observers.push({ resolve: resolve, reject: reject });
-      }
-      // Otherwise just forward observer pair right to a `result` promise.
-      else {
-        result.then(resolve, reject);
-      }
-
-      return deferred.promise;
-    }}
-  })
-
-  var deferred = {
-    promise: promise,
-    /**
-     * Resolves associated `promise` to a given `value`, unless it's already
-     * resolved or rejected. Note that resolved promise is not necessary a
-     * successfully fulfilled. Promise may be resolved with a promise `value`
-     * in which case `value` promise's fulfillment / rejection will propagate
-     * up to a promise resolved with `value`.
-     */
-    resolve: function resolve(value) {
-      if (!result) {
-        // Store resolution `value` in a `result` as a promise, so that all
-        // the subsequent handlers can be simply forwarded to it. Since
-        // `result` will be a promise all the value / error propagation will
-        // be uniformly taken care of.
-        result = isPromise(value) ? value : fulfilled(value);
-
-        // Forward already registered observers to a `result` promise in the
-        // order they were registered. Note that we intentionally dequeue
-        // observer at a time until queue is exhausted. This makes sure that
-        // handlers registered as side effect of observer forwarding are
-        // queued instead of being invoked immediately, guaranteeing FIFO
-        // order.
-        while (observers.length) {
-          var observer = observers.shift();
-          result.then(observer.resolve, observer.reject);
-        }
-
-        // Once `observers` queue is exhausted we `null`-ify it, so that
-        // new handlers are forwarded straight to the `result`.
-        observers = null;
-      }
-    },
-    /**
-     * Rejects associated `promise` with a given `reason`, unless it's already
-     * resolved / rejected. This is just a (better performing) convenience
-     * shortcut for `deferred.resolve(reject(reason))`.
-     */
-    reject: function reject(reason) {
-      // Note that if promise is resolved that does not necessary means that it
-      // is successfully fulfilled. Resolution value may be a promise in which
-      // case its result propagates. In other words if promise `a` is resolved
-      // with promise `b`, `a` is either fulfilled or rejected depending
-      // on weather `b` is fulfilled or rejected. Here `deferred.promise` is
-      // resolved with a promise pre-rejected with a given `reason`, there for
-      // `deferred.promise` is rejected with a given `reason`. This may feel
-      // little awkward first, but doing it this way greatly simplifies
-      // propagation through promise chains.
-      deferred.resolve(rejected(reason));
-    }
-  };
-
-  return deferred;
-}
-exports.defer = defer;
-
-/**
- * Returns a promise resolved to a given `value`. Optionally a second
- * `prototype` argument may be provided to be used as a prototype for the
- * returned promise.
- */
-function resolve(value, prototype) {
-  var deferred = defer(prototype);
-  deferred.resolve(value);
-  return deferred.promise;
-}
-exports.resolve = resolve;
-
-/**
- * Returns a promise rejected with a given `reason`. Optionally a second
- * `prototype` argument may be provided to be used as a prototype for the
- * returned promise.
- */
-function reject(reason, prototype) {
-  var deferred = defer(prototype);
-  deferred.reject(reason);
-  return deferred.promise;
-}
-exports.reject = reject;
-
-var promised = (function() {
+let promised = (function() {
   // Note: Define shortcuts and utility functions here in order to avoid
   // slower property accesses and unnecessary closure creations on each
   // call of this popular function.
 
   var call = Function.call;
   var concat = Array.prototype.concat;
 
   // Utility function that does following:
   // execute([ f, self, args...]) => f.apply(self, args)
-  function execute(args) { return call.apply(call, args) }
+  function execute (args) call.apply(call, args)
 
   // Utility function that takes promise of `a` array and maybe promise `b`
   // as arguments and returns promise for `a.concat(b)`.
   function promisedConcat(promises, unknown) {
-    return promises.then(function(values) {
-      return resolve(unknown).then(function(value) {
-        return values.concat([ value ]);
-      });
+    return promises.then(function (values) {
+      return resolve(unknown)
+        .then(function (value) values.concat([value]));
     });
   }
 
   return function promised(f, prototype) {
     /**
     Returns a wrapped `f`, which when called returns a promise that resolves to
     `f(...)` passing all the given arguments to it, which by the way may be
     promises. Optionally second `prototype` argument may be provided to be used
@@ -275,16 +60,58 @@ var promised = (function() {
     return function promised() {
       // create array of [ f, this, args... ]
       return concat.apply([ f, this ], arguments).
         // reduce it via `promisedConcat` to get promised array of fulfillments
         reduce(promisedConcat, resolve([], prototype)).
         // finally map that to promise of `f.apply(this, args...)`
         then(execute);
     };
-  }
+  };
 })();
+
 exports.promised = promised;
-
-var all = promised(Array);
 exports.all = all;
+exports.defer = defer;
+exports.resolve = resolve;
+exports.reject = reject;
+exports.race = race;
+exports.Promise = Promise;
 
 });
+
+function getEnvironment (callback) {
+  let Cu, _exports, _module, _require;
+
+  // CommonJS / SDK
+  if (typeof(require) === 'function') {
+    Cu = require('chrome').Cu;
+    _exports = exports;
+    _module = module;
+    _require = require;
+  }
+  // JSM
+  else if (String(this).indexOf('BackstagePass') >= 0) {
+    Cu = this['Components'].utils;
+    _exports = this.Promise = {};
+    _module = { uri: __URI__, id: 'promise/core' };
+    _require = uri => {
+      let imports = {};
+      Cu.import(uri, imports);
+      return imports;
+    };
+    this.EXPORTED_SYMBOLS = ['Promise'];
+  // mozIJSSubScriptLoader.loadSubscript
+  } else if (~String(this).indexOf('Sandbox')) {
+    Cu = this['Components'].utils;
+    _exports = this;
+    _module = { id: 'promise/core' };
+    _require = uri => {};
+  }
+
+  callback({
+    Cu: Cu,
+    exports: _exports,
+    module: _module,
+    require: _require
+  });
+}
+
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/model/core.js
@@ -0,0 +1,25 @@
+/* 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";
+
+module.metadata = {
+  "stability": "unstable"
+};
+
+const { dispatcher } = require("../util/dispatcher");
+
+
+// Define `modelFor` accessor function that can be implemented
+// for different types of views. Since view's we'll be dealing
+// with types that don't really play well with `instanceof`
+// operator we're gonig to use `dispatcher` that is slight
+// extension over polymorphic dispatch provided by method.
+// This allows models to extend implementations of this by
+// providing predicates:
+//
+// modelFor.when($ => $ && $.nodeName === "tab", findTabById($.id))
+const modelFor = dispatcher("modelFor");
+exports.modelFor = modelFor;
--- a/addon-sdk/source/lib/sdk/net/url.js
+++ b/addon-sdk/source/lib/sdk/net/url.js
@@ -10,37 +10,34 @@ module.metadata = {
 
 const { Cu, components } = require("chrome");
 const { defer } = require("../core/promise");
 const { merge } = require("../util/object");
 
 const { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 
 /**
- * Open a channel synchronously for the URI given, with an optional charset, and
- * returns a resolved promise if succeed; rejected promise otherwise.
+ * Reads a URI and returns a promise.
+ *
+ * @param uri {string} The URI to read
+ * @param [options] {object} This parameter can have any or all of the following
+ * fields: `charset`. By default the `charset` is set to 'UTF-8'.
+ *
+ * @returns {promise}  The promise that will be resolved with the content of the
+ *          URL given.
+ *
+ * @example
+ *  let promise = readURI('resource://gre/modules/NetUtil.jsm', {
+ *    charset: 'US-ASCII'
+ *  });
  */
-function readSync(uri, charset) {
-  let { promise, resolve, reject } = defer();
+function readURI(uri, options) {
+  options = options || {};
+  let charset = options.charset || 'UTF-8';
 
-  try {
-    resolve(readURISync(uri, charset));
-  }
-  catch (e) {
-    reject("Failed to read: '" + uri + "' (Error Code: " + e.result + ")");
-  }
-
-  return promise;
-}
-
-/**
- * Open a channel synchronously for the URI given, with an optional charset, and
- * returns a promise.
- */
-function readAsync(uri, charset) {
   let channel = NetUtil.newChannel(uri, charset, null);
 
   let { promise, resolve, reject } = defer();
 
   try {
     NetUtil.asyncFetch(channel, function (stream, result) {
       if (components.isSuccessCode(result)) {
         let count = stream.available();
@@ -54,44 +51,16 @@ function readAsync(uri, charset) {
   }
   catch (e) {
     reject("Failed to read: '" + uri + "' (Error: " + e.message + ")");
   }
 
   return promise;
 }
 
-/**
- * Reads a URI and returns a promise. If the `sync` option is set to `true`, the
- * promise will be resolved synchronously.
- *
- * @param uri {string} The URI to read
- * @param [options] {object} This parameter can have any or all of the following
- * fields: `sync`, `charset`. By default the `charset` is set to 'UTF-8'.
- *
- * @returns {promise}  The promise that will be resolved with the content of the
- *          URL given.
-  *
- * @example
- *  let promise = readURI('resource://gre/modules/NetUtil.jsm', {
- *    sync: true,
- *    charset: 'US-ASCII'
- });
- */
-function readURI(uri, options) {
-  options = merge({
-    charset: "UTF-8",
-    sync: false
-  }, options);
-
-  return options.sync
-    ? readSync(uri, options.charset)
-    : readAsync(uri, options.charset);
-}
-
 exports.readURI = readURI;
 
 /**
  * Reads a URI synchronously.
  * This function is intentionally undocumented to favorites the `readURI` usage.
  *
  * @param uri {string} The URI to read
  * @param [charset] {string} The character set to use when read the content of
--- a/addon-sdk/source/lib/sdk/notifications.js
+++ b/addon-sdk/source/lib/sdk/notifications.js
@@ -40,25 +40,26 @@ exports.notify = function notifications_
   };
   function notifyWithOpts(notifyFn) {
     notifyFn(valOpts.iconURL, valOpts.title, valOpts.text, !!clickObserver,
              valOpts.data, clickObserver, valOpts.tag, valOpts.dir, valOpts.lang);
   }
   try {
     notifyWithOpts(notify);
   }
-  catch (err if err instanceof Ci.nsIException &&
-                err.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
-    console.warn("The notification icon named by " + valOpts.iconURL +
-                 " does not exist.  A default icon will be used instead.");
-    delete valOpts.iconURL;
-    notifyWithOpts(notify);
-  }
   catch (err) {
-    notifyWithOpts(notifyUsingConsole);
+    if (err instanceof Ci.nsIException && err.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
+      console.warn("The notification icon named by " + valOpts.iconURL +
+                   " does not exist.  A default icon will be used instead.");
+      delete valOpts.iconURL;
+      notifyWithOpts(notify);
+    }
+    else {
+      notifyWithOpts(notifyUsingConsole);
+    }
   }
 };
 
 function notifyUsingConsole(iconURL, title, text) {
   title = title ? "[" + title + "]" : "";
   text = text || "";
   let str = [title, text].filter(function (s) s).join(" ");
   console.log(str);
--- a/addon-sdk/source/lib/sdk/panel/utils.js
+++ b/addon-sdk/source/lib/sdk/panel/utils.js
@@ -362,21 +362,26 @@ function style(panel) {
     let window = document.defaultView;
     let node = document.getAnonymousElementByAttribute(panel, "class",
                                                        "panel-arrowcontent") ||
                // Before bug 764755, anonymous content was different:
                // TODO: Remove this when targeting FF16+
                 document.getAnonymousElementByAttribute(panel, "class",
                                                         "panel-inner-arrowcontent");
 
-    let color = window.getComputedStyle(node).getPropertyValue("color");
+    let { color, fontFamily, fontSize, fontWeight } = window.getComputedStyle(node);
 
     let style = contentDocument.createElement("style");
     style.id = "sdk-panel-style";
-    style.textContent = "body { color: " + color + "; }";
+    style.textContent = "body { " +
+      "color: " + color + ";" +
+      "font-family: " + fontFamily + ";" +
+      "font-weight: " + fontWeight + ";" +
+      "font-size: " + fontSize + ";" +
+    "}";
 
     let container = contentDocument.head ? contentDocument.head :
                     contentDocument.documentElement;
 
     if (container.firstChild)
       container.insertBefore(style, container.firstChild);
     else
       container.appendChild(style);
--- a/addon-sdk/source/lib/sdk/places/utils.js
+++ b/addon-sdk/source/lib/sdk/places/utils.js
@@ -44,18 +44,19 @@ let TreeNode = Class({
   get: method(get),
   walk: method(walk),
   toString: function () '[object TreeNode]'
 });
 exports.TreeNode = TreeNode;
 
 /*
  * Descends down from `node` applying `fn` to each in order.
- * Can be asynchronous if `fn` returns a promise. `fn` is passed 
- * one argument, the current node, `curr`
+ * `fn` can return values or promises -- if promise returned,
+ * children are not processed until resolved. `fn` is passed 
+ * one argument, the current node, `curr`.
  */
 function walk (curr, fn) {
   return promised(fn)(curr).then(val => {
     return all(curr.children.map(child => walk(child, fn)));
   });
 } 
 
 /*
--- a/addon-sdk/source/lib/sdk/preferences/service.js
+++ b/addon-sdk/source/lib/sdk/preferences/service.js
@@ -132,24 +132,28 @@ exports.keys = keys;
 function isSet(name) {
   return (has(name) && prefSvc.prefHasUserValue(name));
 }
 exports.isSet = isSet;
 
 function reset(name) {
   try {
     prefSvc.clearUserPref(name);
-  } catch (e if e.result == Cr.NS_ERROR_UNEXPECTED) {
+  }
+  catch (e) {
     // The pref service throws NS_ERROR_UNEXPECTED when the caller tries
     // to reset a pref that doesn't exist or is already set to its default
     // value.  This interface fails silently in those cases, so callers
     // can unconditionally reset a pref without having to check if it needs
     // resetting first or trap exceptions after the fact.  It passes through
     // other exceptions, however, so callers know about them, since we don't
     // know what other exceptions might be thrown and what they might mean.
+    if (e.result != Cr.NS_ERROR_UNEXPECTED) {
+      throw e;
+    }
   }
 }
 exports.reset = reset;
 
 function getLocalized(name, defaultValue) {
   let value = null;
   try {
     value = prefSvc.getComplexValue(name, Ci.nsIPrefLocalizedString).data;
--- a/addon-sdk/source/lib/sdk/simple-storage.js
+++ b/addon-sdk/source/lib/sdk/simple-storage.js
@@ -3,23 +3,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 module.metadata = {
   "stability": "stable"
 };
 
-const { Cc, Ci } = require("chrome");
+const { Cc, Ci, Cu } = require("chrome");
 const file = require("./io/file");
 const prefs = require("./preferences/service");
 const jpSelf = require("./self");
 const timer = require("./timers");
 const unload = require("./system/unload");
 const { emit, on, off } = require("./event/core");
+const { defer } = require('./core/promise');
+
+const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
 
 const WRITE_PERIOD_PREF = "extensions.addon-sdk.simple-storage.writePeriod";
 const WRITE_PERIOD_DEFAULT = 300000; // 5 minutes
 
 const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota";
 const QUOTA_DEFAULT = 5242880; // 5 MiB
 
 const JETPACK_DIR_BASENAME = "jetpack";
@@ -30,29 +33,78 @@ Object.defineProperties(exports, {
     get: function() { return manager.root; },
     set: function(value) { manager.root = value; }
   },
   quotaUsage: {
     get: function() { return manager.quotaUsage; }
   }
 });
 
+function getHash(data) {
+  let { promise, resolve } = defer();
+
+  let crypto = Cc["@mozilla.org/security/hash;1"].createInstance(Ci.nsICryptoHash);
+  crypto.init(crypto.MD5);
+
+  let listener = {
+    onStartRequest: function() { },
+
+    onDataAvailable: function(request, context, inputStream, offset, count) {
+      crypto.updateFromStream(inputStream, count);
+    },
+
+    onStopRequest: function(request, context, status) {
+      resolve(crypto.finish(false));
+    }
+  };
+
+  let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
+                  createInstance(Ci.nsIScriptableUnicodeConverter);
+  converter.charset = "UTF-8";
+  let stream = converter.convertToInputStream(data);
+  let pump = Cc["@mozilla.org/network/input-stream-pump;1"].
+             createInstance(Ci.nsIInputStreamPump);
+  pump.init(stream, -1, -1, 0, 0, true);
+  pump.asyncRead(listener, null);
+
+  return promise;
+}
+
+function writeData(filename, data) {
+  let { promise, resolve, reject } = defer();
+
+  let stream = file.open(filename, "w");
+  try {
+    stream.writeAsync(data, err => {
+      if (err)
+        reject(err);
+      else
+        resolve();
+    });
+  }
+  catch (err) {
+    // writeAsync closes the stream after it's done, so only close on error.
+    stream.close();
+    reject(err);
+  }
+
+  return promise;
+}
+
 // A generic JSON store backed by a file on disk.  This should be isolated
 // enough to move to its own module if need be...
 function JsonStore(options) {
   this.filename = options.filename;
   this.quota = options.quota;
   this.writePeriod = options.writePeriod;
   this.onOverQuota = options.onOverQuota;
   this.onWrite = options.onWrite;
-
+  this.hash = null;
   unload.ensure(this);
-
-  this.writeTimer = timer.setInterval(this.write.bind(this),
-                                      this.writePeriod);
+  this.startTimer();
 }
 
 JsonStore.prototype = {
   // The store's root.
   get root() {
     return this.isRootInited ? this._root : {};
   },
 
@@ -76,21 +128,28 @@ JsonStore.prototype = {
   // Percentage of quota used, as a number [0, Inf).  > 1 implies over quota.
   // Undefined if there is no quota.
   get quotaUsage() {
     return this.quota > 0 ?
            JSON.stringify(this.root).length / this.quota :
            undefined;
   },
 
+  startTimer: function JsonStore_startTimer() {
+    timer.setTimeout(() => {
+      this.write().then(this.startTimer.bind(this));
+    }, this.writePeriod);
+  },
+
   // Removes the backing file and all empty subdirectories.
   purge: function JsonStore_purge() {
     try {
       // This'll throw if the file doesn't exist.
       file.remove(this.filename);
+      this.hash = null;
       let parentPath = this.filename;
       do {
         parentPath = file.dirname(parentPath);
         // This'll throw if the dir isn't empty.
         file.rmdir(parentPath);
       } while (file.basename(parentPath) !== JETPACK_DIR_BASENAME);
     }
     catch (err) {}
@@ -100,41 +159,35 @@ JsonStore.prototype = {
   read: function JsonStore_read() {
     try {
       let str = file.read(this.filename);
 
       // Ideally we'd log the parse error with console.error(), but logged
       // errors cause tests to fail.  Supporting "known" errors in the test
       // harness appears to be non-trivial.  Maybe later.
       this.root = JSON.parse(str);
+      let self = this;
+      getHash(str).then(hash => this.hash = hash);
     }
     catch (err) {
       this.root = {};
+      this.hash = null;
     }
   },
 
-  // If the store is under quota, writes the root to the backing file.
-  // Otherwise quota observers are notified and nothing is written.
-  write: function JsonStore_write() {
-    if (this.quotaUsage > 1)
-      this.onOverQuota(this);
-    else
-      this._write();
-  },
-
   // Cleans up on unload.  If unloading because of uninstall, the store is
   // purged; otherwise it's written.
   unload: function JsonStore_unload(reason) {
-    timer.clearInterval(this.writeTimer);
+    timer.clearTimeout(this.writeTimer);
     this.writeTimer = null;
 
     if (reason === "uninstall")
       this.purge();
     else
-      this._write();
+      this.write();
   },
 
   // True if the root is an empty object.
   get _isEmpty() {
     if (this.root && typeof(this.root) === "object") {
       let empty = true;
       for (let key in this.root) {
         empty = false;
@@ -143,42 +196,50 @@ JsonStore.prototype = {
       return empty;
     }
     return false;
   },
 
   // Writes the root to the backing file, notifying write observers when
   // complete.  If the store is over quota or if it's empty and the store has
   // never been written, nothing is written and write observers aren't notified.
-  _write: function JsonStore__write() {
+  write: Task.async(function JsonStore_write() {
     // Don't write if the root is uninitialized or if the store is empty and the
     // backing file doesn't yet exist.
     if (!this.isRootInited || (this._isEmpty && !file.exists(this.filename)))
       return;
 
+    let data = JSON.stringify(this.root);
+
     // If the store is over quota, don't write.  The current under-quota state
     // should persist.
-    if (this.quotaUsage > 1)
+    if ((this.quota > 0) && (data.length > this.quota)) {
+      this.onOverQuota(this);
+      return;
+    }
+
+    // Hash the data to compare it to any previously written data
+    let hash = yield getHash(data);
+
+    if (hash == this.hash)
       return;
 
     // Finally, write.
-    let stream = file.open(this.filename, "w");
     try {
-      stream.writeAsync(JSON.stringify(this.root), function writeAsync(err) {
-        if (err)
-          console.error("Error writing simple storage file: " + this.filename);
-        else if (this.onWrite)
-          this.onWrite(this);
-      }.bind(this));
+      yield writeData(this.filename, data);
+
+      this.hash = hash;
+      if (this.onWrite)
+        this.onWrite(this);
     }
     catch (err) {
-      // writeAsync closes the stream after it's done, so only close on error.
-      stream.close();
+      console.error("Error writing simple storage file: " + this.filename);
+      console.error(err);
     }
-  }
+  })
 };
 
 
 // This manages a JsonStore singleton and tailors its use to simple storage.
 // The root of the JsonStore is lazy-loaded:  The backing file is only read the
 // first time the root's gotten.
 let manager = ({
   jsonStore: null,
--- a/addon-sdk/source/lib/sdk/tabs.js
+++ b/addon-sdk/source/lib/sdk/tabs.js
@@ -1,10 +1,37 @@
 /* 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';
+"use strict";
 
 module.metadata = {
-  'stability': 'stable'
+  "stability": "unstable",
+  "engines": {
+    "Firefox": "*",
+    "Fennec": "*"
+  }
 };
 
-module.exports = require('./tabs/tabs');
+const { modelFor } = require("./model/core");
+const { viewFor } = require("./view/core");
+const { isTab } = require("./tabs/utils");
+
+
+if (require("./system/xul-app").is("Fennec")) {
+  module.exports = require("./windows/tabs-fennec").tabs;
+}
+else {
+  module.exports = require("./tabs/tabs-firefox");
+}
+
+const tabs = module.exports;
+
+// Implement `modelFor` function for the Tab instances.
+// Finds a right model by iterating over all tab models
+// and finding one that wraps given `view`.
+modelFor.when(isTab, view => {
+  for (let model of tabs) {
+    if (viewFor(model) === view)
+      return model;
+  }
+  return null;
+});
deleted file mode 100644
--- a/addon-sdk/source/lib/sdk/tabs/tabs.js
+++ /dev/null
@@ -1,19 +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';
-
-module.metadata = {
-  'stability': 'unstable',
-  'engines': {
-    'Firefox': '*',
-    'Fennec': '*'
-  }
-};
-
-if (require('../system/xul-app').name == 'Fennec') {
-  module.exports = require('../windows/tabs-fennec').tabs;
-}
-else {
-  module.exports = require('./tabs-firefox');
-}
--- a/addon-sdk/source/lib/sdk/tabs/utils.js
+++ b/addon-sdk/source/lib/sdk/tabs/utils.js
@@ -15,16 +15,41 @@ const { Ci } = require('chrome');
 const { defer } = require("../lang/functional");
 const { windows, isBrowser } = require('../window/utils');
 const { isPrivateBrowsingSupported } = require('../self');
 const { isGlobalPBSupported } = require('../private-browsing/utils');
 
 // Bug 834961: ignore private windows when they are not supported
 function getWindows() windows(null, { includePrivate: isPrivateBrowsingSupported || isGlobalPBSupported });
 
+const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+// Define predicate functions that can be used to detech weather
+// we deal with fennec tabs or firefox tabs.
+
+// Predicate to detect whether tab is XUL "Tab" node.
+const isXULTab = tab =>
+  tab instanceof Ci.nsIDOMNode &&
+  tab.nodeName === "tab" &&
+  tab.namespaceURI === XUL_NS;
+exports.isXULTab = isXULTab;
+
+// Predicate to detecet whether given tab is a fettec tab.
+// Unfortunately we have to guess via duck typinng of:
+// http://mxr.mozilla.org/mozilla-central/source/mobile/android/chrome/content/browser.js#2583
+const isFennecTab = tab =>
+  tab &&
+  tab.QueryInterface &&
+  Ci.nsIBrowserTab &&
+  tab.QueryInterface(Ci.nsIBrowserTab) === tab;
+exports.isFennecTab = isFennecTab;
+
+const isTab = x => isXULTab(x) || isFennecTab(x);
+exports.isTab = isTab;
+
 function activateTab(tab, window) {
   let gBrowser = getTabBrowserForTab(tab);
 
   // normal case
   if (gBrowser) {
     gBrowser.selectedTab = tab;
   }
   // fennec ?
--- a/addon-sdk/source/lib/sdk/test/loader.js
+++ b/addon-sdk/source/lib/sdk/test/loader.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { resolveURI, Require,
         unload, override, descriptor } = require('../../toolkit/loader');
 const { ensure } = require('../system/unload');
 const addonWindow = require('../addon/window');
-const { PlainTextConsole } = require("sdk/console/plain-text");
+const { PlainTextConsole } = require('sdk/console/plain-text');
 
 let defaultGlobals = override(require('../system/globals'), {
   console: console
 });
 
 function CustomLoader(module, globals, packaging, overrides={}) {
   let options = packaging || require("@loader/options");
   options = override(options, {
@@ -38,43 +38,53 @@ function CustomLoader(module, globals, p
       unload(loader, reason);
     }
   }));
   ensure(wrapper);
   return wrapper;
 };
 exports.Loader = CustomLoader;
 
+function HookedPlainTextConsole(hook, print, innerID) {
+  this.log = hook.bind(null, "log", innerID);
+  this.info = hook.bind(null, "info", innerID);
+  this.warn = hook.bind(null, "warn", innerID);
+  this.error = hook.bind(null, "error", innerID);
+  this.debug = hook.bind(null, "debug", innerID);
+  this.exception = hook.bind(null, "exception", innerID);
+  this.time = hook.bind(null, "time", innerID);
+  this.timeEnd = hook.bind(null, "timeEnd", innerID);
+
+  this.__exposedProps__ = {
+    log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw",
+    exception: "rw", time: "rw", timeEnd: "rw"
+  };
+}
+
 // Creates a custom loader instance whose console module is hooked in order
 // to avoid printing messages to the console, and instead, expose them in the
 // returned `messages` array attribute
 exports.LoaderWithHookedConsole = function (module, callback) {
   let messages = [];
-  function hook(msg) {
-    messages.push({type: this, msg: msg});
+  function hook(type, innerID, msg) {
+    messages.push({ type: type, msg: msg, innerID: innerID });
     if (callback)
-      callback(this, msg);
+      callback(type, msg, innerID);
   }
+
   return {
     loader: CustomLoader(module, {
-      console: {
-        log: hook.bind("log"),
-        info: hook.bind("info"),
-        warn: hook.bind("warn"),
-        error: hook.bind("error"),
-        debug: hook.bind("debug"),
-        exception: hook.bind("exception"),
-        time: hook.bind("time"),
-        timeEnd: hook.bind("timeEnd"),
-        __exposedProps__: {
-          log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw",
-          exception: "rw", time: "rw", timeEnd: "rw"
+      console: new HookedPlainTextConsole(hook, null, null)
+    }, override(require("@loader/options"), {
+      modules: {
+        'sdk/console/plain-text': {
+          PlainTextConsole: HookedPlainTextConsole.bind(null, hook)
         }
       }
-    }),
+    })),
     messages: messages
   };
 }
 
 // Same than LoaderWithHookedConsole with lower level, instead we get what is
 // actually printed to the command line console
 exports.LoaderWithHookedConsole2 = function (module, callback) {
   let messages = [];
@@ -89,30 +99,24 @@ exports.LoaderWithHookedConsole2 = funct
     messages: messages
   };
 }
 
 // Creates a custom loader with a filtered console. The callback is passed every
 // console message type and message and if it returns false the message will
 // not be logged normally
 exports.LoaderWithFilteredConsole = function (module, callback) {
-  function hook(msg) {
-    if (callback && callback(this, msg) == false)
+  function hook(type, innerID, msg) {
+    if (callback && callback(type, msg, innerID) == false)
       return;
-    console[this](msg);
+    console[type](msg);
   }
+
   return CustomLoader(module, {
-    console: {
-      log: hook.bind("log"),
-      info: hook.bind("info"),
-      warn: hook.bind("warn"),
-      error: hook.bind("error"),
-      debug: hook.bind("debug"),
-      exception: hook.bind("exception"),
-      time: hook.bind("time"),
-      timeEnd: hook.bind("timeEnd"),
-      __exposedProps__: {
-        log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw",
-        exception: "rw", time: "rw", timeEnd: "rw"
+    console: new HookedPlainTextConsole(hook, null, null)
+  }, override(require("@loader/options"), {
+    modules: {
+      'sdk/console/plain-text': {
+        PlainTextConsole: HookedPlainTextConsole.bind(null, hook)
       }
     }
-  });
+  }));
 }
--- a/addon-sdk/source/lib/sdk/url.js
+++ b/addon-sdk/source/lib/sdk/url.js
@@ -23,32 +23,37 @@ var resProt = ios.getProtocolHandler("re
 var URLParser = Cc["@mozilla.org/network/url-parser;1?auth=no"]
                 .getService(Ci.nsIURLParser);
 
 function newURI(uriStr, base) {
   try {
     let baseURI = base ? ios.newURI(base, null, null) : null;
     return ios.newURI(uriStr, null, baseURI);
   }
-  catch (e if e.result == Cr.NS_ERROR_MALFORMED_URI) {
-    throw new Error("malformed URI: " + uriStr);
-  }
-  catch (e if (e.result == Cr.NS_ERROR_FAILURE ||
-               e.result == Cr.NS_ERROR_ILLEGAL_VALUE)) {
-    throw new Error("invalid URI: " + uriStr);
+  catch (e) {
+    if (e.result == Cr.NS_ERROR_MALFORMED_URI) {
+      throw new Error("malformed URI: " + uriStr);
+    }
+    if (e.result == Cr.NS_ERROR_FAILURE ||
+        e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
+      throw new Error("invalid URI: " + uriStr);
+    }
   }
 }
 
 function resolveResourceURI(uri) {
   var resolved;
   try {
     resolved = resProt.resolveURI(uri);
-  } catch (e if e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
-    throw new Error("resource does not exist: " + uri.spec);
-  };
+  }
+  catch (e) {
+    if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
+      throw new Error("resource does not exist: " + uri.spec);
+    }
+  }
   return resolved;
 }
 
 let fromFilename = exports.fromFilename = function fromFilename(path) {
   var file = Cc['@mozilla.org/file/local;1']
              .createInstance(Ci.nsILocalFile);
   file.initWithPath(path);
   return ios.newFileURI(file).spec;
@@ -58,18 +63,21 @@ let toFilename = exports.toFilename = fu
   var uri = newURI(url);
   if (uri.scheme == "resource")
     uri = newURI(resolveResourceURI(uri));
   if (uri.scheme == "chrome") {
     var channel = ios.newChannelFromURI(uri);
     try {
       channel = channel.QueryInterface(Ci.nsIFileChannel);
       return channel.file.path;
-    } catch (e if e.result == Cr.NS_NOINTERFACE) {
-      throw new Error("chrome url isn't on filesystem: " + url);
+    }
+    catch (e) {
+      if (e.result == Cr.NS_NOINTERFACE) {
+        throw new Error("chrome url isn't on filesystem: " + url);
+      }
     }
   }
   if (uri.scheme == "file") {
     var file = uri.QueryInterface(Ci.nsIFileURL).file;
     return file.path;
   }
   throw new Error("cannot map to filename: " + url);
 };
@@ -79,27 +87,42 @@ function URL(url, base) {
      return new URL(url, base);
   }
 
   var uri = newURI(url, base);
 
   var userPass = null;
   try {
     userPass = uri.userPass ? uri.userPass : null;
-  } catch (e if e.result == Cr.NS_ERROR_FAILURE) {}
+  }
+  catch (e) {
+    if (e.result != Cr.NS_ERROR_FAILURE) {
+      throw e;
+    }
+  }
 
   var host = null;
   try {
     host = uri.host;
-  } catch (e if e.result == Cr.NS_ERROR_FAILURE) {}
+  }
+  catch (e) {
+    if (e.result != Cr.NS_ERROR_FAILURE) {
+      throw e;
+    }
+  }
 
   var port = null;
   try {
     port = uri.port == -1 ? null : uri.port;
-  } catch (e if e.result == Cr.NS_ERROR_FAILURE) {}
+  }
+  catch (e) {
+    if (e.result != Cr.NS_ERROR_FAILURE) {
+      throw e;
+    }
+  }
 
   let uriData = [uri.path, uri.path.length, {}, {}, {}, {}, {}, {}];
   URLParser.parsePath.apply(URLParser, uriData);
   let [{ value: filepathPos }, { value: filepathLen },
     { value: queryPos }, { value: queryLen },
     { value: refPos }, { value: refLen }] = uriData.slice(2);
 
   let hash = uri.ref ? "#" + uri.ref : "";
@@ -257,26 +280,31 @@ const DataURL = Class({
 
 exports.DataURL = DataURL;
 
 let getTLD = exports.getTLD = function getTLD (url) {
   let uri = newURI(url.toString());
   let tld = null;
   try {
     tld = tlds.getPublicSuffix(uri);
-  } catch (e if
-      e.result == Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS ||
-      e.result == Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {}
+  }
+  catch (e) {
+    if (e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS &&
+        e.result != Cr.NS_ERROR_HOST_IS_IP_ADDRESS) {
+      throw e;
+    }
+  }
   return tld;
 };
 
 let isValidURI = exports.isValidURI = function (uri) {
   try {
     newURI(uri);
-  } catch(e) {
+  }
+  catch(e) {
     return false;
   }
   return true;
 }
 
 function isLocalURL(url) {
   if (String.indexOf(url, './') === 0)
     return true;
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/util/dispatcher.js
@@ -0,0 +1,55 @@
+/* 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";
+
+module.metadata = {
+  "stability": "experimental"
+};
+
+const method = require("method/core");
+
+// Utility function that is just an enhancement over `method` to
+// allow predicate based dispatch in addition to polymorphic
+// dispatch. Unfortunately polymorphic dispatch does not quite
+// cuts it in the world of XPCOM where no types / classes exist
+// and all the XUL nodes share same type / prototype.
+// Probably this is more generic and belongs some place else, but
+// we can move it later once this will be relevant.
+let dispatcher = hint => {
+  const base = method(hint);
+  // Make a map for storing predicate, implementation mappings.
+  let implementations = new Map();
+
+  // Dispatcher function goes through `predicate, implementation`
+  // pairs to find predicate that matches first argument and
+  // returns application of arguments on the associated
+  // `implementation`. If no matching predicate is found delegates
+  // to a `base` polymorphic function.
+  let dispatch = (value, ...rest) => {
+    for (let [predicate, implementation] of implementations) {
+      if (predicate(value))
+        return implementation(value, ...rest);
+    }
+
+    return base(value, ...rest);
+  };
+
+  // Expose base API.
+  dispatch.define = base.define;
+  dispatch.implement = base.implement;
+  dispatch.toString = base.toString;
+
+  // Add a `when` function to allow extending function via
+  // predicates.
+  dispatch.when = (predicate, implementation) => {
+    if (implementations.has(predicate))
+      throw TypeError("Already implemented for the given predicate");
+    implementations.set(predicate, implementation);
+  };
+
+  return dispatch;
+};
+
+exports.dispatcher = dispatcher;
--- a/addon-sdk/source/lib/sdk/windows.js
+++ b/addon-sdk/source/lib/sdk/windows.js
@@ -6,14 +6,31 @@
 module.metadata = {
   'stability': 'stable',
   'engines': {
     'Firefox': '*',
     'Fennec': '*'
   }
 };
 
+const { isBrowser } = require('./window/utils');
+const { modelFor } = require('./model/core');
+const { viewFor } = require('./view/core');
+
+
 if (require('./system/xul-app').is('Fennec')) {
   module.exports = require('./windows/fennec');
 }
 else {
   module.exports = require('./windows/firefox');
 }
+
+
+const browsers = module.exports.browserWindows;
+
+//
+modelFor.when(isBrowser, view => {
+  for (let model of browsers) {
+    if (viewFor(model) === view)
+      return model;
+  }
+  return null;
+});
--- a/addon-sdk/source/test/addons/places/tests/test-places-favicon.js
+++ b/addon-sdk/source/test/addons/places/tests/test-places-favicon.js
@@ -142,23 +142,23 @@ exports.testTabsGetFaviconPromiseFailure
     onOpen: function (newTab) tab = newTab,
     inBackground: true
   });
 };
 
 exports.testRejects = function (assert, done) {
   getFavicon({})
     .then(invalidResolve(assert), validReject(assert, 'Object'))
-  .then(getFavicon(null))
+  .then(() => getFavicon(null))
     .then(invalidResolve(assert), validReject(assert, 'null'))
-  .then(getFavicon(undefined))
+  .then(() => getFavicon(undefined))
     .then(invalidResolve(assert), validReject(assert, 'undefined'))
-  .then(getFavicon([]))
+  .then(() => getFavicon([]))
     .then(invalidResolve(assert), validReject(assert, 'Array'))
-    .then(done);
+    .catch(assert.fail).then(done);
 };
 
 function invalidResolve (assert) {
   return function () assert.fail('Promise should not be resolved successfully');
 }
 
 function validReject (assert, name) {
   return function () assert.pass(name + ' correctly rejected');
--- a/addon-sdk/source/test/addons/places/tests/test-places-utils.js
+++ b/addon-sdk/source/test/addons/places/tests/test-places-utils.js
@@ -26,36 +26,35 @@ exports['test construct tree'] = functio
   assert.equal(tree.get(4.32).value, 4.32, 'get returns node even if created from nested node');
   assert.equal(tree.get(4).children.length, 3, 'nodes have correct children length');
   assert.equal(tree.get(3).children.length, 0, 'nodes have correct children length');
 
   assert.equal(tree.get(4).get(4.32).value, 4.32, 'node.get descends from itself');
   assert.equal(tree.get(4).get(2), null, 'node.get descends from itself fails if not descendant');
 };
 
-exports['test walk'] = function (assert) {
+exports['test walk'] = function (assert, done) {
   let resultsAll = [];
+  let resultsNode = [];
   let tree = TreeNode(1);
   tree.add([2, 3, 4]);
   tree.get(2).add([2.1, 2.2]);
 
   tree.walk(function (node) {
     resultsAll.push(node.value);
-  });
-
-  [1, 2, 2.1, 2.2, 3, 4].forEach(function (num) {
-    assert.ok(~resultsAll.indexOf(num), 'function applied to each node from root');
-  });
-
-  let resultsNode = [];
-  tree.get(2).walk(function (node) resultsNode.push(node.value));
-
-  [2, 2.1, 2.2].forEach(function (num) {
-    assert.ok(~resultsNode.indexOf(num), 'function applied to each node from node');
-  });
+  }).then(() => {
+    [1, 2, 2.1, 2.2, 3, 4].forEach(num => {
+      assert.ok(~resultsAll.indexOf(num), 'function applied to each node from root');
+    });
+    return tree.get(2).walk(node => resultsNode.push(node.value));
+  }).then(() => {
+    [2, 2.1, 2.2].forEach(function (num) {
+      assert.ok(~resultsNode.indexOf(num), 'function applied to each node from node');
+    });
+  }).catch(assert.fail).then(done);
 };
 
 exports['test async walk'] = function (assert, done) {
   let resultsAll = [];
   let tree = TreeNode(1);
   tree.add([2, 3, 4]);
   tree.get(2).add([2.1, 2.2]);
 
new file mode 100644
--- /dev/null
+++ b/addon-sdk/source/test/test-dispatcher.js
@@ -0,0 +1,77 @@
+/* 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 { dispatcher } = require("sdk/util/dispatcher");
+
+exports["test dispatcher API"] = assert => {
+  const dispatch = dispatcher();
+
+  assert.equal(typeof(dispatch), "function",
+               "dispatch is a function");
+
+  assert.equal(typeof(dispatch.define), "function",
+               "dispatch.define is a function");
+
+  assert.equal(typeof(dispatch.implement), "function",
+               "dispatch.implement is a function");
+
+  assert.equal(typeof(dispatch.when), "function",
+               "dispatch.when is a function");
+};
+
+exports["test dispatcher"] = assert => {
+  const isDuck = dispatcher();
+
+  const quacks = x => x && typeof(x.quack) === "function";
+
+  const Duck = function() {};
+  const Goose = function() {};
+
+  const True = _ => true;
+  const False = _ => false;
+
+
+
+  isDuck.define(Goose, False);
+  isDuck.define(Duck, True);
+  isDuck.when(quacks, True);
+
+  assert.equal(isDuck(new Goose()), false,
+               "Goose ain't duck");
+
+  assert.equal(isDuck(new Duck()), true,
+               "Ducks are ducks");
+
+  assert.equal(isDuck({ quack: () => "Quaaaaaack!" }), true,
+               "It's a duck if it quacks");
+
+
+  assert.throws(() => isDuck({}), /Type does not implements method/, "not implemneted");
+
+  isDuck.define(Object, False);
+
+  assert.equal(isDuck({}), false,
+               "Ain't duck if it does not quacks!");
+};
+
+exports["test redefining fails"] = assert => {
+  const isPM = dispatcher();
+  const isAfternoon = time => time.getHours() > 12;
+
+  isPM.when(isAfternoon, _ => true);
+
+  assert.equal(isPM(new Date(Date.parse("Jan 23, 1985, 13:20:00"))), true,
+               "yeap afternoon");
+  assert.equal(isPM({ getHours: _ => 17 }), true,
+                "seems like afternoon");
+
+  assert.throws(() => isPM.when(isAfternoon, x => x > 12 && x < 24),
+                /Already implemented for the given predicate/,
+               "can't redefine on same predicate");
+
+};
+
+require("sdk/test").run(exports);
--- a/addon-sdk/source/test/test-net-url.js
+++ b/addon-sdk/source/test/test-net-url.js
@@ -24,28 +24,16 @@ exports["test async readURI"] = function
   }, function() {
     assert.fail("should not reject");
     done();
   })
 
   assert.equal(content, "", "The URL content is not load yet");
 }
 
-exports["test sync readURI"] = function(assert) {
-  let content = "";
-
-  readURI(data.url("test-net-url.txt"), { sync: true }).then(function(data) {
-    content = data;
-  }, function() {
-    assert.fail("should not reject");
-  })
-
-  assert.equal(content, utf8text, "The URL content is loaded properly");
-}
-
 exports["test readURISync"] = function(assert) {
   let content = readURISync(data.url("test-net-url.txt"));
 
   assert.equal(content, utf8text, "The URL content is loaded properly");
 }
 
 exports["test async readURI with ISO-8859-1 charset"] = function(assert, done) {
   let content = "";
@@ -57,55 +45,32 @@ exports["test async readURI with ISO-885
   }, function() {
     assert.fail("should not reject");
     done();
   })
 
   assert.equal(content, "", "The URL content is not load yet");
 }
 
-exports["test sync readURI with ISO-8859-1 charset"] = function(assert) {
-  let content = "";
-
-  readURI(data.url("test-net-url.txt"), {
-    sync: true,
-    charset: "ISO-8859-1"
-  }).then(function(data) {
-    content = data;
-  }, function() {
-    assert.fail("should not reject");
-  })
-
-  assert.equal(content, latin1text, "The URL content is loaded properly");
-}
-
 exports["test readURISync with ISO-8859-1 charset"] = function(assert) {
   let content = readURISync(data.url("test-net-url.txt"), "ISO-8859-1");
 
   assert.equal(content, latin1text, "The URL content is loaded properly");
 }
 
 exports["test async readURI with not existing file"] = function(assert, done) {
   readURI(data.url("test-net-url-fake.txt")).then(function(data) {
     assert.fail("should not resolve");
     done();
   }, function(reason) {
     assert.ok(reason.indexOf("Failed to read:") === 0);
     done();
   })
 }
 
-exports["test sync readURI with not existing file"] = function(assert) {
-  readURI(data.url("test-net-url-fake.txt"), { sync: true }).then(function(data) {
-    assert.fail("should not resolve");
-  }, function(reason) {
-    assert.ok(reason.indexOf("Failed to read:") === 0);
-  })
-}
-
 exports["test readURISync with not existing file"] = function(assert) {
   assert.throws(function() {
     readURISync(data.url("test-net-url-fake.txt"));
   }, /NS_ERROR_FILE_NOT_FOUND/);
 }
 
 exports["test async readURI with data URI"] = function(assert, done) {
   let content = "";
@@ -117,28 +82,16 @@ exports["test async readURI with data UR
   }, function() {
     assert.fail("should not reject");
     done();
   })
 
   assert.equal(content, "", "The URL content is not load yet");
 }
 
-exports["test sync readURI with data URI"] = function(assert) {
-  let content = "";
-
-  readURI(dataURIutf8, { sync: true }).then(function(data) {
-    content = data;
-  }, function() {
-    assert.fail("should not reject");
-  })
-
-  assert.equal(content, utf8text, "The URL content is loaded properly");
-}
-
 exports["test readURISync with data URI"] = function(assert) {
   let content = readURISync(dataURIutf8);
 
   assert.equal(content, utf8text, "The URL content is loaded properly");
 }
 
 exports["test async readURI with data URI and ISO-8859-1 charset"] = function(assert, done) {
   let content = "";
@@ -150,31 +103,16 @@ exports["test async readURI with data UR
   }, function() {
     assert.fail("should not reject");
     done();
   })
 
   assert.equal(content, "", "The URL content is not load yet");
 }
 
-exports["test sync readURI with data URI and ISO-8859-1 charset"] = function(assert) {
-  let content = "";
-
-  readURI(dataURIlatin1, {
-    sync: true,
-    charset: "ISO-8859-1"
-  }).then(function(data) {
-    content = unescape(data);
-  }, function() {
-    assert.fail("should not reject");
-  })
-
-  assert.equal(content, latin1text, "The URL content is loaded properly");
-}
-
 exports["test readURISync with data URI and ISO-8859-1 charset"] = function(assert) {
   let content = unescape(readURISync(dataURIlatin1, "ISO-8859-1"));
 
   assert.equal(content, latin1text, "The URL content is loaded properly");
 }
 
 exports["test readURISync with chrome URI"] = function(assert) {
   let content = readURISync(chromeURI);
@@ -192,21 +130,9 @@ exports["test async readURI with chrome 
   }, function() {
     assert.fail("should not reject");
     done();
   })
 
   assert.equal(content, "", "The URL content is not load yet");
 }
 
-exports["test sync readURI with chrome URI"] = function(assert) {
-  let content = "";
-
-  readURI(chromeURI, { sync: true }).then(function(data) {
-    content = data;
-  }, function() {
-    assert.fail("should not reject");
-  })
-
-  assert.equal(content, readURISync(chromeURI), "The URL content is loaded properly");
-}
-
 require("test").run(exports)
--- a/addon-sdk/source/test/test-page-mod.js
+++ b/addon-sdk/source/test/test-page-mod.js
@@ -19,16 +19,17 @@ const { getTabContentWindow, getActiveTa
 const xulApp = require("sdk/system/xul-app");
 const { isPrivateBrowsingSupported } = require('sdk/self');
 const { isPrivate } = require('sdk/private-browsing');
 const { openWebpage } = require('./private-browsing/helper');
 const { isTabPBSupported, isWindowPBSupported, isGlobalPBSupported } = require('sdk/private-browsing/utils');
 const promise = require("sdk/core/promise");
 const { pb } = require('./private-browsing/helper');
 const { URL } = require("sdk/url");
+const { LoaderWithHookedConsole } = require('sdk/test/loader');
 
 const { waitUntil } = require("sdk/test/utils");
 const data = require("./fixtures");
 
 const { gDevToolsExtensions } = Cu.import("resource://gre/modules/devtools/DevToolsExtensions.jsm", {});
 
 const testPageURI = data.url("test.html");
 
@@ -1526,16 +1527,51 @@ exports.testDetachOnUnload = function(as
   });
 
   tabs.open({
     url: TEST_URL,
     onOpen: t => tab = t
   })
 }
 
+exports.testConsole = function(assert, done) {
+  let innerID;
+  const TEST_URL = 'data:text/html;charset=utf-8,console';
+  const { loader } = LoaderWithHookedConsole(module, onMessage);
+  const { PageMod } = loader.require('sdk/page-mod');
+  const system = require("sdk/system/events");
+
+  let seenMessage = false;
+  function onMessage(type, msg, msgID) {
+    seenMessage = true;
+    innerID = msgID;
+  }
+
+  let mod = PageMod({
+    include: TEST_URL,
+    contentScriptWhen: "ready",
+    contentScript: Isolate(function() {
+      console.log("Hello from the page mod");
+      self.port.emit("done");
+    }),
+    onAttach: function(worker) {
+      worker.port.on("done", function() {
+        let window = getTabContentWindow(tab);
+        let id = getInnerId(window);
+        assert.ok(seenMessage, "Should have seen the console message");
+        assert.equal(innerID, id, "Should have seen the right inner ID");
+        closeTab(tab);
+        done();
+      });
+    },
+  });
+
+  let tab = openTab(getMostRecentBrowserWindow(), TEST_URL);
+}
+
 exports.testSyntaxErrorInContentScript = function(assert, done) {
   const url = "data:text/html;charset=utf-8,testSyntaxErrorInContentScript";
   let hitError = null;
   let attached = false;
 
   testPageMod(assert, done, url, [{
       include: url,
       contentScript: 'console.log(23',
--- a/addon-sdk/source/test/test-page-worker.js
+++ b/addon-sdk/source/test/test-page-worker.js
@@ -449,15 +449,20 @@ exports.testMessageQueue = function (ass
     done();
   });
 };
 
 function isDestroyed(page) {
   try {
     page.postMessage("foo");
   }
-  catch (err if err.message == ERR_DESTROYED) {
-    return true;
+  catch (err) {
+    if (err.message == ERR_DESTROYED) {
+      return true;
+    }
+    else {
+      throw err;
+    }
   }
   return false;
 }
 
 require("test").run(exports);
--- a/addon-sdk/source/test/test-panel.js
+++ b/addon-sdk/source/test/test-panel.js
@@ -896,17 +896,17 @@ exports['test passing DOM node as first 
   let widget = Widget({
     id: 'panel-widget',
     label: 'panel widget',
     content: '<i></i>',
   });
 
   let widgetNode = document.getElementById(widgetId);
 
-  all(warned.promise, shown.promise).
+  all([warned.promise, shown.promise]).
     then(loader.unload).
     then(done, assert.fail)
 
   panel.show(widgetNode);
 };
 
 // This test is checking that `onpupshowing` events emitted by panel's children
 // are not considered.
--- a/addon-sdk/source/test/test-plain-text-console.js
+++ b/addon-sdk/source/test/test-plain-text-console.js
@@ -225,16 +225,41 @@ exports.testPlainTextConsoleBoundMethods
   let tbLines = prints[0].split("\n");
   assert.equal(tbLines[0], "console.trace: " + name + ": ");
   assert.ok(tbLines[1].indexOf("_ain-text-console.js 224") === 0);
   prints = [];
 
   restorePrefs();
 };
 
+exports.testConsoleInnerID = function(assert) {
+  let Console = require("sdk/console/plain-text").PlainTextConsole;
+  let { log, info, warn, error, debug, exception, trace } = new Console(function() {}, "test ID");
+
+  let messages = [];
+  function onMessage({ subject }) {
+    let message = subject.wrappedJSObject;
+    messages.push({ msg: message.arguments[0], type: message.level, innerID: message.innerID });
+  }
+
+  const system = require("sdk/system/events");
+  system.on("console-api-log-event", onMessage);
+
+  log("Test log");
+  warn("Test warning");
+  error("Test error");
+
+  assert.equal(messages.length, 3, "Should see 3 log events");
+  assert.deepEqual(messages[0], { msg: "Test log", type: "log", innerID: "test ID" }, "Should see the right event");
+  assert.deepEqual(messages[1], { msg: "Test warning", type: "warn", innerID: "test ID" }, "Should see the right event");
+  assert.deepEqual(messages[2], { msg: "Test error", type: "error", innerID: "test ID" }, "Should see the right event");
+
+  system.off("console-api-log-event", onMessage);
+};
+
 function restorePrefs() {
   if (HAS_ORIGINAL_ADDON_LOG_LEVEL)
     prefs.set(ADDON_LOG_LEVEL_PREF, ORIGINAL_ADDON_LOG_LEVEL);
   else
     prefs.reset(ADDON_LOG_LEVEL_PREF);
 
   if (HAS_ORIGINAL_SDK_LOG_LEVEL)
     prefs.set(SDK_LOG_LEVEL_PREF, ORIGINAL_SDK_LOG_LEVEL);
--- a/addon-sdk/source/test/test-promise.js
+++ b/addon-sdk/source/test/test-promise.js
@@ -1,349 +1,318 @@
 /* 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';
 
-var core = require('sdk/core/promise'),
-    defer = core.defer, resolve = core.resolve, reject = core.reject, all = core.all,
-    promised = core.promised;
-
-var { setTimeout } = require('sdk/timers');
+const { Cc, Cu, Ci } = require('chrome');
+const { setTimeout } = require('sdk/timers');
+const { prefixURI, name } = require('@loader/options');
+const addonPromiseURI = prefixURI + name + '/lib/sdk/core/promise.js';
+const builtPromiseURI = 'resource://gre/modules/commonjs/sdk/core/promise.js';
+let { Promise, defer, resolve, reject, all, promised } = require('sdk/core/promise');
 
 exports['test all observers are notified'] = function(assert, done) {
-  var expected = 'Taram pam param!'
-  var deferred = defer()
-  var pending = 10, i = 0
+  let expected = 'Taram pam param!';
+  let deferred = defer();
+  let pending = 10, i = 0;
 
   function resolved(value) {
-    assert.equal(value, expected, 'value resolved as expected: #' + pending)
-    if (!--pending) done()
+    assert.equal(value, expected, 'value resolved as expected: #' + pending);
+    if (!--pending) done();
   }
 
-  while (i++ < pending) deferred.promise.then(resolved)
+  while (i++ < pending) deferred.promise.then(resolved);
 
-  deferred.resolve(expected)
-}
+  deferred.resolve(expected);
+};
 
 exports['test exceptions dont stop notifications'] = function(assert, done) {
-  var threw = false, boom = Error('Boom!')
-  var deferred = defer()
+  let threw = false, boom = Error('Boom!');
+  let deferred = defer();
 
-  var promise2 = deferred.promise.then(function() {
-    threw = true
-    throw boom
-  })
+  let promise2 = deferred.promise.then(function() {
+    threw = true;
+    throw boom;
+  });
 
   deferred.promise.then(function() {
-    assert.ok(threw, 'observer is called even though previos one threw')
+    assert.ok(threw, 'observer is called even though previos one threw');
     promise2.then(function() {
-      assert.fail('should not resolve')
+      assert.fail('should not resolve');
     }, function(reason) {
-      assert.equal(reason, boom, 'rejects to thrown error')
-      done()
-    })
-  })
+      assert.equal(reason, boom, 'rejects to thrown error');
+      done();
+    });
+  });
 
-  deferred.resolve('go!')
-}
+  deferred.resolve('go!');
+};
 
 exports['test subsequent resolves are ignored'] = function(assert, done) {
-  var deferred = defer()
-  deferred.resolve(1)
-  deferred.resolve(2)
-  deferred.reject(3)
+  let deferred = defer();
+  deferred.resolve(1);
+  deferred.resolve(2);
+  deferred.reject(3);
 
   deferred.promise.then(function(actual) {
-    assert.equal(actual, 1, 'resolves to first value')
+    assert.equal(actual, 1, 'resolves to first value');
   }, function() {
-    assert.fail('must not reject')
-  })
+    assert.fail('must not reject');
+  });
   deferred.promise.then(function(actual) {
-    assert.equal(actual, 1, 'subsequent resolutions are ignored')
-    done()
+    assert.equal(actual, 1, 'subsequent resolutions are ignored');
+    done();
   }, function() {
-    assert.fail('must not reject')
-  })
-}
+    assert.fail('must not reject');
+  });
+};
 
 exports['test subsequent rejections are ignored'] = function(assert, done) {
-  var deferred = defer()
-  deferred.reject(1)
-  deferred.resolve(2)
-  deferred.reject(3)
+  let deferred = defer();
+  deferred.reject(1);
+  deferred.resolve(2);
+  deferred.reject(3);
 
   deferred.promise.then(function(actual) {
-    assert.fail('must not resolve')
+    assert.fail('must not resolve');
   }, function(actual) {
-    assert.equal(actual, 1, 'must reject to first')
-  })
+    assert.equal(actual, 1, 'must reject to first');
+  });
   deferred.promise.then(function(actual) {
-    assert.fail('must not resolve')
+    assert.fail('must not resolve');
   }, function(actual) {
-    assert.equal(actual, 1, 'must reject to first')
-    done()
-  })
-}
+    assert.equal(actual, 1, 'must reject to first');
+    done();
+  });
+};
 
 exports['test error recovery'] = function(assert, done) {
-  var boom = Error('Boom!')
-  var deferred = defer()
+  let boom = Error('Boom!');
+  let deferred = defer();
 
   deferred.promise.then(function() {
-    assert.fail('rejected promise should not resolve')
+    assert.fail('rejected promise should not resolve');
   }, function(reason) {
-    assert.equal(reason, boom, 'rejection reason delivered')
-    return 'recovery'
+    assert.equal(reason, boom, 'rejection reason delivered');
+    return 'recovery';
   }).then(function(value) {
-    assert.equal(value, 'recovery', 'error handled by a handler')
-    done()
-  })
+    assert.equal(value, 'recovery', 'error handled by a handler');
+    done();
+  });
 
-  deferred.reject(boom)
-}
-
+  deferred.reject(boom);
+};
 
 exports['test error recovery with promise'] = function(assert, done) {
-  var deferred = defer()
+  let deferred = defer();
 
   deferred.promise.then(function() {
-    assert.fail('must reject')
+    assert.fail('must reject');
   }, function(actual) {
-    assert.equal(actual, 'reason', 'rejected')
-    var deferred = defer()
-    deferred.resolve('recovery')
-    return deferred.promise
+    assert.equal(actual, 'reason', 'rejected');
+    let deferred = defer();
+    deferred.resolve('recovery');
+    return deferred.promise;
   }).then(function(actual) {
-    assert.equal(actual, 'recovery', 'recorvered via promise')
-    var deferred = defer()
-    deferred.reject('error')
-    return deferred.promise
+    assert.equal(actual, 'recovery', 'recorvered via promise');
+    let deferred = defer();
+    deferred.reject('error');
+    return deferred.promise;
   }).then(null, function(actual) {
-    assert.equal(actual, 'error', 'rejected via promise')
-    var deferred = defer()
-    deferred.reject('end')
-    return deferred.promise
+    assert.equal(actual, 'error', 'rejected via promise');
+    let deferred = defer();
+    deferred.reject('end');
+    return deferred.promise;
   }).then(null, function(actual) {
-    assert.equal(actual, 'end', 'rejeced via promise')
-    done()
-  })
+    assert.equal(actual, 'end', 'rejeced via promise');
+    done();
+  });
 
-  deferred.reject('reason')
-}
+  deferred.reject('reason');
+};
 
 exports['test propagation'] = function(assert, done) {
-  var d1 = defer(), d2 = defer(), d3 = defer()
+  let d1 = defer(), d2 = defer(), d3 = defer();
 
   d1.promise.then(function(actual) {
-    assert.equal(actual, 'expected', 'resolves to expected value')
-    done()
-  })
+    assert.equal(actual, 'expected', 'resolves to expected value');
+    done();
+  });
 
-  d1.resolve(d2.promise)
-  d2.resolve(d3.promise)
-  d3.resolve('expected')
-}
+  d1.resolve(d2.promise);
+  d2.resolve(d3.promise);
+  d3.resolve('expected');
+};
 
 exports['test chaining'] = function(assert, done) {
-  var boom = Error('boom'), brax = Error('braxXXx')
-  var deferred = defer()
+  let boom = Error('boom'), brax = Error('braxXXx');
+  let deferred = defer();
 
   deferred.promise.then().then().then(function(actual) {
-    assert.equal(actual, 2, 'value propagates unchanged')
-    return actual + 2
+    assert.equal(actual, 2, 'value propagates unchanged');
+    return actual + 2;
   }).then(null, function(reason) {
-    assert.fail('should not reject')
+    assert.fail('should not reject');
   }).then(function(actual) {
-    assert.equal(actual, 4, 'value propagates through if not handled')
-    throw boom
+    assert.equal(actual, 4, 'value propagates through if not handled');
+    throw boom;
   }).then(function(actual) {
-    assert.fail('exception must reject promise')
+    assert.fail('exception must reject promise');
   }).then().then(null, function(actual) {
-    assert.equal(actual, boom, 'reason propagates unchanged')
-    throw brax
+    assert.equal(actual, boom, 'reason propagates unchanged');
+    throw brax;
   }).then().then(null, function(actual) {
-    assert.equal(actual, brax, 'reason changed becase of exception')
-    return 'recovery'
+    assert.equal(actual, brax, 'reason changed becase of exception');
+    return 'recovery';
   }).then(function(actual) {
-    assert.equal(actual, 'recovery', 'recovered from error')
-    done()
-  })
+    assert.equal(actual, 'recovery', 'recovered from error');
+    done();
+  });
 
-  deferred.resolve(2)
-}
-
+  deferred.resolve(2);
+};
 
 exports['test reject'] = function(assert, done) {
-  var expected = Error('boom')
+  let expected = Error('boom');
 
   reject(expected).then(function() {
-    assert.fail('should reject')
+    assert.fail('should reject');
   }, function(actual) {
-    assert.equal(actual, expected, 'rejected with expected reason')
-  }).then(function() {
-    done()
-  })
-}
+    assert.equal(actual, expected, 'rejected with expected reason');
+  }).then(done, assert.fail);
+};
 
 exports['test resolve to rejected'] = function(assert, done) {
-  var expected = Error('boom')
-  var deferred = defer()
+  let expected = Error('boom');
+  let deferred = defer();
 
   deferred.promise.then(function() {
-    assert.fail('should reject')
+    assert.fail('should reject');
   }, function(actual) {
-    assert.equal(actual, expected, 'rejected with expected failure')
-  }).then(function() {
-    done()
-  })
+    assert.equal(actual, expected, 'rejected with expected failure');
+  }).then(done, assert.fail);
 
-  deferred.resolve(reject(expected))
-}
+  deferred.resolve(reject(expected));
+};
 
 exports['test resolve'] = function(assert, done) {
-  var expected = 'value'
+  let expected = 'value';
   resolve(expected).then(function(actual) {
-    assert.equal(actual, expected, 'resolved as expected')
-  }).then(function() {
-    done()
-  })
-}
-
-exports['test resolve with prototype'] = function(assert, done) {
-  var seventy = resolve(70, {
-    subtract: function subtract(y) {
-      return this.then(function(x) { return x - y })
-    }
-  })
-
-  seventy.subtract(17).then(function(actual) {
-    assert.equal(actual, 70 - 17, 'resolves to expected')
-    done()
-  })
-}
+    assert.equal(actual, expected, 'resolved as expected');
+  }).catch(assert.fail).then(done);
+};
 
 exports['test promised with normal args'] = function(assert, done) {
-  var sum = promised(function(x, y) { return x + y })
+  let sum = promised((x, y) => x + y );
 
   sum(7, 8).then(function(actual) {
-    assert.equal(actual, 7 + 8, 'resolves as expected')
-    done()
-  })
-}
+    assert.equal(actual, 7 + 8, 'resolves as expected');
+  }).catch(assert.fail).then(done);
+};
 
 exports['test promised with promise args'] = function(assert, done) {
-  var sum = promised(function(x, y) { return x + y })
-  var deferred = defer()
+  let sum = promised((x, y) => x + y );
+  let deferred = defer();
 
   sum(11, deferred.promise).then(function(actual) {
-    assert.equal(actual, 11 + 24, 'resolved as expected')
-    done()
-  })
-
-  deferred.resolve(24)
-}
-
-exports['test promised with prototype'] = function(assert, done) {
-  var deferred = defer()
-  var numeric = {}
-  numeric.subtract = promised(function(y) { return this - y }, numeric)
+    assert.equal(actual, 11 + 24, 'resolved as expected');
+  }).catch(assert.fail).then(done);
 
-  var sum = promised(function(x, y) { return x + y }, numeric)
-
-  sum(7, 70).
-    subtract(14).
-    subtract(deferred.promise).
-    subtract(5).
-    then(function(actual) {
-      assert.equal(actual, 7 + 70 - 14 - 23 - 5, 'resolved as expected')
-      done()
-    })
-
-  deferred.resolve(23)
-}
+  deferred.resolve(24);
+};
 
 exports['test promised error handleing'] = function(assert, done) {
-  var expected = Error('boom')
-  var f = promised(function() {
-    throw expected
-  })
+  let expected = Error('boom');
+  let f = promised(function() {
+    throw expected;
+  });
 
   f().then(function() {
-    assert.fail('should reject')
+    assert.fail('should reject');
   }, function(actual) {
-    assert.equal(actual, expected, 'rejected as expected')
-    done()
-  })
-}
+    assert.equal(actual, expected, 'rejected as expected');
+  }).catch(assert.fail).then(done);
+};
 
 exports['test errors in promise resolution handlers are propagated'] = function(assert, done) {
   var expected = Error('Boom');
   var { promise, resolve } = defer();
 
   promise.then(function() {
     throw expected;
   }).then(function() {
     return undefined;
   }).then(null, function(actual) {
     assert.equal(actual, expected, 'rejected as expected');
   }).then(done, assert.fail);
 
   resolve({});
-}
+};
 
 exports['test return promise form promised'] = function(assert, done) {
-  var f = promised(function() {
-    return resolve(17)
-  })
+  let f = promised(function() {
+    return resolve(17);
+  });
 
   f().then(function(actual) {
-    assert.equal(actual, 17, 'resolves to a promise resolution')
-    done()
-  })
-}
+    assert.equal(actual, 17, 'resolves to a promise resolution');
+  }).catch(assert.fail).then(done);
+};
 
 exports['test promised returning failure'] = function(assert, done) {
-  var expected = Error('boom')
-  var f = promised(function() {
-    return reject(expected)
-  })
+  let expected = Error('boom');
+  let f = promised(function() {
+    return reject(expected);
+  });
 
   f().then(function() {
-    assert.fail('must reject')
+    assert.fail('must reject');
   }, function(actual) {
-    assert.equal(actual, expected, 'rejects with expected reason')
-    done()
-  })
-}
+    assert.equal(actual, expected, 'rejects with expected reason');
+  }).catch(assert.fail).then(done);
+};
 
-exports['test promised are greedy'] = function(assert, done) {
-  var runs = 0
-  var f = promised(function() { ++runs })
-  var promise = f()
-  assert.equal(runs, 1, 'promised runs task right away')
-  done()
-}
+/*
+ * Changed for compliance in Bug 881047, promises are now always async
+ */
+exports['test promises are always async'] = function (assert, done) {
+  let runs = 0;
+  resolve(1)
+    .then(val => ++runs)
+    .catch(assert.fail).then(done);
+  assert.equal(runs, 0, 'resolutions are called in following tick');
+};
+
+/*
+ * Changed for compliance in Bug 881047, promised's are now non greedy
+ */
+exports['test promised are not greedy'] = function(assert, done) {
+  let runs = 0;
+  promised(() => ++runs)()
+    .catch(assert.fail).then(done);
+  assert.equal(runs, 0, 'promised does not run task right away');
+};
 
 exports['test arrays should not flatten'] = function(assert, done) {
-  var a = defer()
-  var b = defer()
+  let a = defer();
+  let b = defer();
 
-  var combine = promised(function(str, arr) {
-    assert.equal(str, 'Hello', 'Array was not flattened')
-    assert.deepEqual(arr, [ 'my', 'friend' ])
-  })
+  let combine = promised(function(str, arr) {
+    assert.equal(str, 'Hello', 'Array was not flattened');
+    assert.deepEqual(arr, [ 'my', 'friend' ]);
+  });
 
-  combine(a.promise, b.promise).then(done)
+  combine(a.promise, b.promise).catch(assert.fail).then(done);
 
 
-  a.resolve('Hello')
-  b.resolve([ 'my', 'friend' ])
-}
+  a.resolve('Hello');
+  b.resolve([ 'my', 'friend' ]);
+};
 
 exports['test `all` for all promises'] = function (assert, done) {
   all([
     resolve(5), resolve(7), resolve(10)
   ]).then(function (val) {
     assert.equal(
       val[0] === 5 &&
       val[1] === 7 &&
@@ -361,17 +330,17 @@ exports['test `all` aborts upon first re
   ]).then(function (val) {
     assert.fail('Successful resolve function should not be called');
   }, function (reason) {
     assert.equal(reason, 'error', 'should reject the `all` promise');
     done();
   });
 
   function delayedResolve () {
-    var deferred = defer();
+    let deferred = defer();
     setTimeout(deferred.resolve, 50);
     return deferred.promise;
   }
 };
 
 exports['test `all` with array containing non-promise'] = function (assert, done) {
   all([
     resolve(5), resolve(10), 925
@@ -399,9 +368,83 @@ exports['test `all` with multiple reject
   ]).then(function (value) {
     assert.fail('should not be successful');
   }, function (reason) {
     assert.equal(reason, 'error1', 'should reject on first promise reject');
     done();
   });
 };
 
-require("test").run(exports)
+exports['test Promise constructor resolve'] = function (assert, done) {
+  var isAsync = true;
+  new Promise(function (resolve, reject) {
+    resolve(5);
+  }).then(x => {
+    isAsync = false;
+    assert.equal(x, 5, 'Promise constructor resolves correctly');
+  }).catch(assert.fail).then(done);
+  assert.ok(isAsync, 'Promise constructor runs async');
+};
+
+exports['test Promise constructor reject'] = function (assert, done) {
+  new Promise(function (resolve, reject) {
+    reject(new Error('deferred4life'));
+  }).then(assert.fail, (err) => {
+    assert.equal(err.message, 'deferred4life', 'Promise constructor rejects correctly');
+  }).catch(assert.fail).then(done);
+};
+
+exports['test JSM Load and API'] = function (assert, done) {
+  // Use addon URL when loading from cfx/local:
+  // resource://90111c90-c31e-4dc7-ac35-b65947434435-at-jetpack/addon-sdk/lib/sdk/core/promise.js
+  // Use built URL when testing on try, etc.
+  // resource://gre/modules/commonjs/sdk/core/promise.js
+  try {
+    var { Promise } = Cu.import(addonPromiseURI, {});
+  } catch (e) {
+    var { Promise } = Cu.import(builtPromiseURI, {});
+  }
+  testEnvironment(Promise, assert, done, 'JSM');
+};
+
+exports['test mozIJSSubScriptLoader exporting'] = function (assert, done) {
+  let { Services } = Cu.import('resource://gre/modules/Services.jsm', {});
+  let systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
+  let Promise = new Cu.Sandbox(systemPrincipal);
+  let loader = Cc['@mozilla.org/moz/jssubscript-loader;1']
+                 .getService(Ci.mozIJSSubScriptLoader);
+
+  // Use addon URL when loading from cfx/local:
+  // resource://90111c90-c31e-4dc7-ac35-b65947434435-at-jetpack/addon-sdk/lib/sdk/core/promise.js
+  // Use built URL when testing on try, etc.
+  // resource://gre/modules/commonjs/sdk/core/promise.js
+  try {
+    loader.loadSubScript(addonPromiseURI, Promise);
+  } catch (e) {
+    loader.loadSubScript(builtPromiseURI, Promise);
+  }
+
+  testEnvironment(Promise, assert, done, 'mozIJSSubScript');
+};
+
+function testEnvironment ({all, resolve, defer, reject, promised}, assert, done, type) {
+  all([resolve(5), resolve(10), 925]).then(val => {
+    assert.equal(val[0], 5, 'promise#all works ' + type);
+    assert.equal(val[1], 10, 'promise#all works ' + type);
+    assert.equal(val[2], 925, 'promise#all works ' + type);
+    return resolve(1000);
+  }).then(value => {
+    assert.equal(value, 1000, 'promise#resolve works ' + type);
+    return reject('testing reject');
+  }).then(null, reason => {
+    assert.equal(reason, 'testing reject', 'promise#reject works ' + type);
+    let deferred = defer();
+    setTimeout(() => deferred.resolve('\\m/'), 10);
+    return deferred.promise;
+  }).then(value => {
+    assert.equal(value, '\\m/', 'promise#defer works ' + type);
+    return promised(x => x * x)(5);
+  }).then(value => {
+    assert.equal(value, 25, 'promise#promised works ' + type);
+  }).then(done, assert.fail);
+}
+
+require("sdk/test").run(exports);
--- a/addon-sdk/source/test/test-simple-storage.js
+++ b/addon-sdk/source/test/test-simple-storage.js
@@ -1,49 +1,52 @@
 /* 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/. */
 
 const file = require("sdk/io/file");
 const prefs = require("sdk/preferences/service");
 
 const QUOTA_PREF = "extensions.addon-sdk.simple-storage.quota";
+const WRITE_PERIOD_PREF = "extensions.addon-sdk.simple-storage.writePeriod";
 
 let {Cc,Ci} = require("chrome");
 
 const { Loader } = require("sdk/test/loader");
 const { id } = require("sdk/self");
 
 let storeFile = Cc["@mozilla.org/file/directory_service;1"].
                 getService(Ci.nsIProperties).
                 get("ProfD", Ci.nsIFile);
 storeFile.append("jetpack");
 storeFile.append(id);
 storeFile.append("simple-storage");
+file.mkpath(storeFile.path);
 storeFile.append("store.json");
 let storeFilename = storeFile.path;
 
 function manager(loader) loader.sandbox("sdk/simple-storage").manager;
 
 exports.testSetGet = function (assert, done) {
   // Load the module once, set a value.
   let loader = Loader(module);
   let ss = loader.require("sdk/simple-storage");
   manager(loader).jsonStore.onWrite = function (storage) {
     assert.ok(file.exists(storeFilename), "Store file should exist");
 
     // Load the module again and make sure the value stuck.
     loader = Loader(module);
     ss = loader.require("sdk/simple-storage");
+    assert.equal(ss.storage.foo, val, "Value should persist");
     manager(loader).jsonStore.onWrite = function (storage) {
-      file.remove(storeFilename);
-      done();
+      assert.fail("Nothing should be written since `storage` was not changed.");
     };
-    assert.equal(ss.storage.foo, val, "Value should persist");
     loader.unload();
+    file.remove(storeFilename);
+    done();
   };
   let val = "foo";
   ss.storage.foo = val;
   assert.equal(ss.storage.foo, val, "Value read should be value set");
   loader.unload();
 };
 
 exports.testSetGetRootArray = function (assert, done) {
@@ -99,28 +102,46 @@ exports.testSetGetRootUndefined = functi
 
 exports.testEmpty = function (assert) {
   let loader = Loader(module);
   let ss = loader.require("sdk/simple-storage");
   loader.unload();
   assert.ok(!file.exists(storeFilename), "Store file should not exist");
 };
 
+exports.testStorageDataRecovery = function(assert) {
+  const data = { 
+    a: true,
+    b: [3, 13],
+    c: "guilty!",
+    d: { e: 1, f: 2 }
+  };
+  let stream = file.open(storeFilename, "w");
+  stream.write(JSON.stringify(data));
+  stream.close();
+  let loader = Loader(module);
+  let ss = loader.require("sdk/simple-storage");
+  assert.deepEqual(ss.storage, data, "Recovered data should be the same as written");
+  file.remove(storeFilename);
+  loader.unload();
+}
+
 exports.testMalformed = function (assert) {
   let stream = file.open(storeFilename, "w");
   stream.write("i'm not json");
   stream.close();
   let loader = Loader(module);
   let ss = loader.require("sdk/simple-storage");
   let empty = true;
   for (let key in ss.storage) {
     empty = false;
     break;
   }
   assert.ok(empty, "Malformed storage should cause root to be empty");
+  file.remove(storeFilename);
   loader.unload();
 };
 
 // Go over quota and handle it by listener.
 exports.testQuotaExceededHandle = function (assert, done) {
   prefs.set(QUOTA_PREF, 18);
 
   let loader = Loader(module);
@@ -136,20 +157,21 @@ exports.testQuotaExceededHandle = functi
       let numProps = 0;
       for (let prop in ss.storage)
         numProps++;
       assert.ok(numProps, 2,
                   "Store should contain 2 values: " + ss.storage.toSource());
       assert.equal(ss.storage.x, 4, "x value should be correct");
       assert.equal(ss.storage.y, 5, "y value should be correct");
       manager(loader).jsonStore.onWrite = function (storage) {
-        prefs.reset(QUOTA_PREF);
-        done();
+        assert.fail("Nothing should be written since `storage` was not changed.");
       };
       loader.unload();
+      prefs.reset(QUOTA_PREF);
+      done();
     };
     loader.unload();
   });
   // This will be JSON.stringify()ed to: {"a":1,"b":2,"c":3} (19 bytes)
   ss.storage = { a: 1, b: 2, c: 3 };
   manager(loader).jsonStore.write();
 };
 
@@ -173,16 +195,19 @@ exports.testQuotaExceededNoHandle = func
       };
       loader.unload();
 
       loader = Loader(module);
       ss = loader.require("sdk/simple-storage");
       assert.equal(ss.storage, val,
                        "Over-quota value should not have been written, " +
                        "old value should have persisted: " + ss.storage);
+      manager(loader).jsonStore.onWrite = function (storage) {
+        assert.fail("Nothing should be written since `storage` was not changed.");
+      };
       loader.unload();
       prefs.reset(QUOTA_PREF);
       done();
     });
     manager(loader).jsonStore.write();
   };
 
   let val = "foo";
@@ -227,16 +252,194 @@ exports.testUninstall = function (assert
     loader.unload("uninstall");
     assert.ok(!file.exists(storeFilename), "Store file should be removed");
     done();
   };
   ss.storage.foo = "foo";
   loader.unload();
 };
 
+exports.testChangeInnerArray = function(assert, done) {
+  prefs.set(WRITE_PERIOD_PREF, 10);
+
+  let expected = {
+    x: [5, 7],
+    y: [7, 28],
+    z: [6, 2]
+  };
+
+  // Load the module, set a value.
+  let loader = Loader(module);
+  let ss = loader.require("sdk/simple-storage");
+  manager(loader).jsonStore.onWrite = function (storage) {
+    assert.ok(file.exists(storeFilename), "Store file should exist");
+
+    // Load the module again and check the result
+    loader = Loader(module);
+    ss = loader.require("sdk/simple-storage");
+    assert.equal(JSON.stringify(ss.storage),
+                     JSON.stringify(expected), "Should see the expected object");
+
+    // Add a property
+    ss.storage.x.push(["bar"]);
+    expected.x.push(["bar"]);
+    manager(loader).jsonStore.onWrite = function (storage) {
+      assert.equal(JSON.stringify(ss.storage),
+                       JSON.stringify(expected), "Should see the expected object");
+
+      // Modify a property
+      ss.storage.y[0] = 42;
+      expected.y[0] = 42;
+      manager(loader).jsonStore.onWrite = function (storage) {
+        assert.equal(JSON.stringify(ss.storage),
+                         JSON.stringify(expected), "Should see the expected object");
+
+        // Delete a property
+        delete ss.storage.z[1];
+        delete expected.z[1];
+        manager(loader).jsonStore.onWrite = function (storage) {
+          assert.equal(JSON.stringify(ss.storage),
+                           JSON.stringify(expected), "Should see the expected object");
+
+          // Modify the new inner-object
+          ss.storage.x[2][0] = "baz";
+          expected.x[2][0] = "baz";
+          manager(loader).jsonStore.onWrite = function (storage) {
+            assert.equal(JSON.stringify(ss.storage),
+                             JSON.stringify(expected), "Should see the expected object");
+
+            manager(loader).jsonStore.onWrite = function (storage) {
+              assert.fail("Nothing should be written since `storage` was not changed.");
+            };
+            loader.unload();
+
+            // Load the module again and check the result
+            loader = Loader(module);
+            ss = loader.require("sdk/simple-storage");
+            assert.equal(JSON.stringify(ss.storage),
+                             JSON.stringify(expected), "Should see the expected object");
+            loader.unload();
+            file.remove(storeFilename);
+            prefs.reset(WRITE_PERIOD_PREF);
+            done();
+          };
+        };
+      };
+    };
+  };
+
+  ss.storage = {
+    x: [5, 7],
+    y: [7, 28],
+    z: [6, 2]
+  };
+  assert.equal(JSON.stringify(ss.storage),
+                   JSON.stringify(expected), "Should see the expected object");
+
+  loader.unload();
+};
+
+exports.testChangeInnerObject = function(assert, done) {
+  prefs.set(WRITE_PERIOD_PREF, 10);
+
+  let expected = {
+    x: {
+      a: 5,
+      b: 7
+    },
+    y: {
+      c: 7,
+      d: 28
+    },
+    z: {
+      e: 6,
+      f: 2
+    }
+  };
+
+  // Load the module, set a value.
+  let loader = Loader(module);
+  let ss = loader.require("sdk/simple-storage");
+  manager(loader).jsonStore.onWrite = function (storage) {
+    assert.ok(file.exists(storeFilename), "Store file should exist");
+
+    // Load the module again and check the result
+    loader = Loader(module);
+    ss = loader.require("sdk/simple-storage");
+    assert.equal(JSON.stringify(ss.storage),
+                     JSON.stringify(expected), "Should see the expected object");
+
+    // Add a property
+    ss.storage.x.g = {foo: "bar"};
+    expected.x.g = {foo: "bar"};
+    manager(loader).jsonStore.onWrite = function (storage) {
+      assert.equal(JSON.stringify(ss.storage),
+                       JSON.stringify(expected), "Should see the expected object");
+
+      // Modify a property
+      ss.storage.y.c = 42;
+      expected.y.c = 42;
+      manager(loader).jsonStore.onWrite = function (storage) {
+        assert.equal(JSON.stringify(ss.storage),
+                         JSON.stringify(expected), "Should see the expected object");
+
+        // Delete a property
+        delete ss.storage.z.f;
+        delete expected.z.f;
+        manager(loader).jsonStore.onWrite = function (storage) {
+          assert.equal(JSON.stringify(ss.storage),
+                           JSON.stringify(expected), "Should see the expected object");
+
+          // Modify the new inner-object
+          ss.storage.x.g.foo = "baz";
+          expected.x.g.foo = "baz";
+          manager(loader).jsonStore.onWrite = function (storage) {
+            assert.equal(JSON.stringify(ss.storage),
+                             JSON.stringify(expected), "Should see the expected object");
+
+            manager(loader).jsonStore.onWrite = function (storage) {
+              assert.fail("Nothing should be written since `storage` was not changed.");
+            };
+            loader.unload();
+
+            // Load the module again and check the result
+            loader = Loader(module);
+            ss = loader.require("sdk/simple-storage");
+            assert.equal(JSON.stringify(ss.storage),
+                             JSON.stringify(expected), "Should see the expected object");
+            loader.unload();
+            file.remove(storeFilename);
+            prefs.reset(WRITE_PERIOD_PREF);
+            done();
+          };
+        };
+      };
+    };
+  };
+
+  ss.storage = {
+    x: {
+      a: 5,
+      b: 7
+    },
+    y: {
+      c: 7,
+      d: 28
+    },
+    z: {
+      e: 6,
+      f: 2
+    }
+  };
+  assert.equal(JSON.stringify(ss.storage),
+                   JSON.stringify(expected), "Should see the expected object");
+
+  loader.unload();
+};
+
 exports.testSetNoSetRead = function (assert, done) {
   // Load the module, set a value.
   let loader = Loader(module);
   let ss = loader.require("sdk/simple-storage");
   manager(loader).jsonStore.onWrite = function (storage) {
     assert.ok(file.exists(storeFilename), "Store file should exist");
 
     // Load the module again but don't access ss.storage.
@@ -245,22 +448,23 @@ exports.testSetNoSetRead = function (ass
     manager(loader).jsonStore.onWrite = function (storage) {
       assert.fail("Nothing should be written since `storage` was not accessed.");
     };
     loader.unload();
 
     // Load the module a third time and make sure the value stuck.
     loader = Loader(module);
     ss = loader.require("sdk/simple-storage");
+    assert.equal(ss.storage.foo, val, "Value should persist");
     manager(loader).jsonStore.onWrite = function (storage) {
-      file.remove(storeFilename);
-      done();
+      assert.fail("Nothing should be written since `storage` was not changed.");
     };
-    assert.equal(ss.storage.foo, val, "Value should persist");
     loader.unload();
+    file.remove(storeFilename);
+    done();
   };
   let val = "foo";
   ss.storage.foo = val;
   assert.equal(ss.storage.foo, val, "Value read should be value set");
   loader.unload();
 };
 
 
@@ -271,22 +475,23 @@ function setGetRoot(assert, done, val, c
   let loader = Loader(module);
   let ss = loader.require("sdk/simple-storage");
   manager(loader).jsonStore.onWrite = function () {
     assert.ok(file.exists(storeFilename), "Store file should exist");
 
     // Load the module again and make sure the value stuck.
     loader = Loader(module);
     ss = loader.require("sdk/simple-storage");
-    manager(loader).jsonStore.onWrite = function () {
-      file.remove(storeFilename);
-      done();
+    assert.ok(compare(ss.storage, val), "Value should persist");
+    manager(loader).jsonStore.onWrite = function (storage) {
+      assert.fail("Nothing should be written since `storage` was not changed.");
     };
-    assert.ok(compare(ss.storage, val), "Value should persist");
     loader.unload();
+    file.remove(storeFilename);
+    done();
   };
   ss.storage = val;
   assert.ok(compare(ss.storage, val), "Value read should be value set");
   loader.unload();
 }
 
 function setGetRootError(assert, done, val, msg) {
   let pred = new RegExp("storage must be one of the following types: " +
--- a/addon-sdk/source/test/test-tab.js
+++ b/addon-sdk/source/test/test-tab.js
@@ -1,19 +1,21 @@
 /* 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 tabs = require("sdk/tabs"); // From addon-kit
 const windowUtils = require("sdk/deprecated/window-utils");
 const { getTabForWindow } = require('sdk/tabs/helpers');
 const app = require("sdk/system/xul-app");
 const { viewFor } = require("sdk/view/core");
-const { getTabId } = require("sdk/tabs/utils");
+const { modelFor } = require("sdk/model/core");
+const { getTabId, isTab } = require("sdk/tabs/utils");
 const { defer } = require("sdk/lang/functional");
 
 // The primary test tab
 var primaryTab;
 
 // We have an auxiliary tab to test background tabs.
 var auxTab;
 
@@ -147,11 +149,27 @@ exports["test viewFor(tab)"] = (assert, 
     const view = viewFor(tab);
     assert.ok(view, "view is returned");
     assert.equal(getTabId(view), tab.id, "tab has a same id");
 
     tab.close(defer(done));
   }));
 
   tabs.open({ url: "about:mozilla" });
-}
+};
+
+
+exports["test modelFor(xulTab)"] = (assert, done) => {
+  tabs.open({
+    url: "about:mozilla",
+    onReady: tab => {
+      const view = viewFor(tab);
+      assert.ok(view, "view is returned");
+      assert.ok(isTab(view), "view is underlaying tab");
+      assert.equal(getTabId(view), tab.id, "tab has a same id");
+      assert.equal(modelFor(view), tab, "modelFor(view) is SDK tab");
+
+      tab.close(defer(done));
+    }
+  });
+};
 
 require("test").run(exports);
--- a/addon-sdk/source/test/test-test-loader.js
+++ b/addon-sdk/source/test/test-test-loader.js
@@ -43,18 +43,18 @@ exports["test LoaderWithHookedConsole"] 
   let console = loader.globals.console;
   console.log("1st");
   console.error("2nd");
   console.warn("3rd");
   console.info("4th");
   console.debug("5th");
   console.exception("6th");
   assert.equal(messages.length, 6, "Got all console messages");
-  assert.deepEqual(messages[0], {type: "log", msg: "1st"}, "Got log");
-  assert.deepEqual(messages[1], {type: "error", msg: "2nd"}, "Got error");
-  assert.deepEqual(messages[2], {type: "warn", msg: "3rd"}, "Got warn");
-  assert.deepEqual(messages[3], {type: "info", msg: "4th"}, "Got info");
-  assert.deepEqual(messages[4], {type: "debug", msg: "5th"}, "Got debug");
-  assert.deepEqual(messages[5], {type: "exception", msg: "6th"}, "Got exception");
+  assert.deepEqual(messages[0], {type: "log", msg: "1st", innerID: null}, "Got log");
+  assert.deepEqual(messages[1], {type: "error", msg: "2nd", innerID: null}, "Got error");
+  assert.deepEqual(messages[2], {type: "warn", msg: "3rd", innerID: null}, "Got warn");
+  assert.deepEqual(messages[3], {type: "info", msg: "4th", innerID: null}, "Got info");
+  assert.deepEqual(messages[4], {type: "debug", msg: "5th", innerID: null}, "Got debug");
+  assert.deepEqual(messages[5], {type: "exception", msg: "6th", innerID: null}, "Got exception");
   assert.equal(count, 6, "Called for all messages");
 };
 
 require("sdk/test").run(exports);
--- a/addon-sdk/source/test/test-traceback.js
+++ b/addon-sdk/source/test/test-traceback.js
@@ -43,48 +43,63 @@ exports.testFormatDoesNotFetchRemoteFile
                        scheme + " request");
     });
 };
 
 exports.testFromExceptionWithString = function(assert) {
   try {
     throw "foob";
     assert.fail("an exception should've been thrown");
-  } catch (e if e == "foob") {
-    var tb = traceback.fromException(e);
-    assert.equal(tb.length, 0);
+  } catch (e) {
+    if (e == "foob") {
+      var tb = traceback.fromException(e);
+      assert.equal(tb.length, 0);
+    }
+    else {
+      throw e;
+    }
   }
 };
 
 exports.testFormatWithString = function(assert) {
   // This can happen if e.g. a thrown exception was
   // a string instead of an Error instance.
   assert.equal(traceback.format("blah"),
 		   "Traceback (most recent call last):");
 };
 
 exports.testFromExceptionWithError = function(assert) {
   try {
     throwError();
     assert.fail("an exception should've been thrown");
-  } catch (e if e instanceof Error) {
-    var tb = traceback.fromException(e);
+  } catch (e) {
+    if (e instanceof Error) {
+      var tb = traceback.fromException(e);
 
-    var xulApp = require("sdk/system/xul-app");
-    assert.equal(tb.slice(-1)[0].name, "throwError");
+      var xulApp = require("sdk/system/xul-app");
+      assert.equal(tb.slice(-1)[0].name, "throwError");
+    }
+    else {
+      throw e;
+    }
   }
 };
 
 exports.testFromExceptionWithNsIException = function(assert) {
   try {
     throwNsIException();
     assert.fail("an exception should've been thrown");
-  } catch (e if e.result == Cr.NS_ERROR_MALFORMED_URI) {
-    var tb = traceback.fromException(e);
-    assert.equal(tb[tb.length - 1].name, "throwNsIException");
+  } catch (e) {
+    if (e.result == Cr.NS_ERROR_MALFORMED_URI) {
+      var tb = traceback.fromException(e);
+      assert.equal(tb[tb.length - 1].name, "throwNsIException");
+    }
+    else {
+      throw e;
+    }
   }
 };
 
 exports.testFormat = function(assert) {
   function getTraceback() {
     return traceback.format();
   }
 
--- a/addon-sdk/source/test/test-ui-frame.js
+++ b/addon-sdk/source/test/test-ui-frame.js
@@ -4,44 +4,61 @@
 "use strict";
 
 module.metadata = {
   "engines": {
     "Firefox": "*"
   }
 };
 
+const { Cu } = require("chrome");
 const { Frame } = require("sdk/ui/frame");
 const { Toolbar } = require("sdk/ui/toolbar");
 const { Loader } = require("sdk/test/loader");
 const { identify } = require("sdk/ui/id");
 const { setTimeout } = require("sdk/timers");
 const { getMostRecentBrowserWindow, open } = require("sdk/window/utils");
 const { ready, loaded, close } = require("sdk/window/helpers");
-const { defer } = require("sdk/core/promise");
+const { defer, all } = require("sdk/core/promise");
 const { send } = require("sdk/event/utils");
 const { object } = require("sdk/util/sequence");
 const { OutputPort } = require("sdk/output/system");
+const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
 const output = new OutputPort({ id: "toolbar-change" });
 
-const wait = (toolbar, event) => {
+const wait = (toolbar, event, times) => {
   let { promise, resolve } = defer();
-  toolbar.once(event, resolve);
+  if (times) {
+    let resolveArray = [];
+    let counter = 0;
+    toolbar.on(event, function onEvent (e) {
+      resolveArray.push(e);
+      if (++counter === times) {
+        toolbar.off(event, onEvent);
+        resolve(resolveArray);
+      }
+    });
+  }
+  else {
+    toolbar.once(event, resolve);
+  }
   return promise;
 };
 
 const stateEventsFor = frame =>
   [wait(frame, "attach"), wait(frame, "ready"),
    wait(frame, "load"), wait(frame, "detach")];
 
 
 const isAttached = ({id}, window=getMostRecentBrowserWindow()) =>
   !!window.document.getElementById(id);
 
-exports["test frame API"] = function*(assert) {
+// Use `Task.spawn` instead of `Task.async` because the returned function does not contain
+// a length for the test harness to determine whether the test should be executed
+exports["test frame API"] = function* (assert) {
   const url = "data:text/html,frame-api";
   assert.throws(() => new Frame(),
                 /The `options.url`/,
                 "must provide url");
 
   assert.throws(() => new Frame({ url: "http://mozilla.org/" }),
                 /The `options.url`/,
                 "options.url must be local url");
@@ -81,18 +98,17 @@ exports["test frame API"] = function*(as
   assert.pass("frame identical to destroyed one can be created");
 
   yield wait(f3, "register");
   assert.equal(f3.url, url, "url is set");
   f2.destroy();
   f3.destroy();
 };
 
-
-exports["test frame in toolbar"] = function*(assert) {
+exports["test frame in toolbar"] = function* (assert) {
   const assertEvent = (event, type) => {
     assert.ok(event, "`" + type + "` event was dispatched");
     assert.equal(event.type, type, "event.type is: " + type);
     assert.equal(typeof(event.source), "object",
                  "event.source is an object");
     assert.equal(typeof(event.source.postMessage), "function",
                  "messages can be posted to event.source");
   };
@@ -111,39 +127,37 @@ exports["test frame in toolbar"] = funct
   assertEvent((yield a1), "attach");
   assert.ok(isAttached(f1, w1), "frame is in the window#1");
   assertEvent((yield r1), "ready");
   assertEvent((yield l1), "load");
 
   const [a2, r2, l2] = stateEventsFor(f1);
   const w2 = open();
 
-
   assertEvent((yield a2), "attach");
   assert.ok(isAttached(f1, w2), "frame is in the window#2");
   assertEvent((yield r2), "ready");
   assertEvent((yield l2), "load");
   assert.pass("frame attached to window#2");
 
 
   const d1 = wait(f1, "detach");
   yield close(w2);
-
   assertEvent((yield d1), "detach");
   assert.pass("frame detached when window is closed");
 
   t1.destroy();
 
   assertEvent((yield wait(f1, "detach")), "detach");
   assert.ok(!isAttached(f1, w1), "frame was removed from window#1");
   assert.pass("toolbar destroy detaches frame");
 };
 
 
-exports["test host to content messaging"] = function*(assert) {
+exports["test host to content messaging"] = function* (assert) {
   const url = "data:text/html,<script>new " + function() {
     window.addEventListener("message", (event) => {
       if (event.data === "ping!")
         event.source.postMessage("pong!", event.origin);
     });
   } + "</script>";
   const f1 = new Frame({ name: "mailbox", url: url });
   const t1 = new Toolbar({ title: "mailbox", items: [f1] });
@@ -154,17 +168,17 @@ exports["test host to content messaging"
   const pong = yield wait(f1, "message");
   assert.equal(pong.data, "pong!", "received ping back");
   t1.destroy();
 
   yield wait(t1, "detach");
 };
 
 
-exports["test content to host messaging"] = function*(assert) {
+exports["test content to host messaging"] = function* (assert) {
   const url = "data:text/html,<script>new " + function() {
     window.addEventListener("message", (event) => {
       if (event.data === "pong!")
         event.source.postMessage("end", event.origin);
     });
 
     window.parent.postMessage("ping!", "*");
   } + "</script>";
@@ -177,20 +191,21 @@ exports["test content to host messaging"
 
   e1.source.postMessage("pong!", e1.origin);
 
   const e2 = yield wait(f1, "message");
   assert.equal(e2.data, "end", "received end message");
 
   t1.destroy();
   yield wait(t1, "detach");
+
 };
 
 
-exports["test direct messaging"] = function*(assert) {
+exports["test direct messaging"] = function* (assert) {
   const url = "data:text/html,<script>new " + function() {
     var n = 0;
     window.addEventListener("message", (event) => {
       if (event.data === "inc")
         n = n + 1;
       if (event.data === "print")
         event.source.postMessage({ n: n }, event.origin);
     });
@@ -203,36 +218,35 @@ exports["test direct messaging"] = funct
   yield wait(f1, "ready");
   assert.pass("document loaded in window#1");
 
   const w2 = open();
 
   yield wait(f1, "ready");
   assert.pass("document loaded in window#2");
 
+  let messages = wait(f1, "message", 2);
   f1.postMessage("inc", f1.origin);
   f1.postMessage("print", f1.origin);
 
-  const e1 = yield wait(f1, "message");
+  const [e1, e2] = yield messages;
   assert.deepEqual(e1.data, {n: 1}, "received message from window#1");
-
-  const e2 = yield wait(f1, "message");
   assert.deepEqual(e2.data, {n: 1}, "received message from window#2");
 
+  let message = wait(f1, "message");
   e1.source.postMessage("inc", e1.origin);
-
   e1.source.postMessage("print", e1.origin);
-
-  const e3 = yield wait(f1, "message");
+  const e3 = yield message;
   assert.deepEqual(e3.data, {n: 2}, "state changed in window#1");
 
+  let message = wait(f1, "message");
   e2.source.postMessage("print", e2.origin);
-  const e4 = yield wait(f1, "message");
-
+  yield message;
   assert.deepEqual(e2.data, {n:1}, "window#2 didn't received inc message");
 
   yield close(w2);
   t1.destroy();
 
   yield wait(t1, "detach");
+
 };
 
 require("sdk/test").run(exports);
--- a/addon-sdk/source/test/test-ui-sidebar.js
+++ b/addon-sdk/source/test/test-ui-sidebar.js
@@ -824,17 +824,17 @@ exports.testShowingInOneWindowDoesNotAff
       sidebar1.url += '1';
       assert.pass('set sidebar1.url');
     });
 
     sidebar1.show();
   }, assert.fail);
 }
 
-exports.testHidingAHiddenSidebarRejects = function(assert) {
+exports.testHidingAHiddenSidebarRejects = function(assert, done) {
   const { Sidebar } = require('sdk/ui/sidebar');
   let testName = 'testHidingAHiddenSidebarRejects';
   let url = 'data:text/html;charset=utf-8,'+testName;
   let sidebar = Sidebar({
     id: testName,
     title: testName,
     url: url
   });
@@ -1380,28 +1380,28 @@ exports.testEventListeners = function(as
     onReady.resolve();
   });
   sidebar.on('hide', function() {
     assert.equal(this, sidebar, '`this` is correct in on hide');
     eventListenerOrder.push('on hide');
     onHide.resolve();
   });
 
-  all(constructorOnShow.promise,
+  all([constructorOnShow.promise,
       constructorOnAttach.promise,
       constructorOnReady.promise,
       constructorOnHide.promise,
       onceShow.promise,
       onceAttach.promise,
       onceReady.promise,
       onceHide.promise,
       onShow.promise,
       onAttach.promise,
       onReady.promise,
-      onHide.promise).then(function() {
+      onHide.promise]).then(function() {
         assert.equal(eventListenerOrder.join(), [
             'onAttach',
             'once attach',
             'on attach',
             'onReady',
             'once ready',
             'on ready',
             'onShow',
@@ -1431,41 +1431,32 @@ exports.testAttachDoesNotEmitWhenShown =
       if (count > 2) {
         assert.fail('sidebar was attached again..');
       }
       else {
         assert.pass('sidebar was attached ' + count + ' time(s)');
       }
 
       if (++count == 1) {
-        setTimeout(function() {
-          let shown = false;
-          let endShownTest = false;
-          sidebar.once('show', function() {
-            assert.pass('shown was emitted');
-            shown = !endShownTest && true;
-          });
+        setImmediate(function() {
+          let shownFired = 0;
+          let onShow = () => shownFired++;
+          sidebar.on('show', onShow);
 
-          sidebar.show().then(function() {
-            assert.pass('calling hide');
-            sidebar.hide();
-          }).then(function() {
-            endShownTest = true;
-
-            setTimeout(function() {
-              sidebar.show().then(function() {
-                assert.ok(!shown, 'show did not emit');
-
-                sidebar.hide().then(function() {
-                  sidebar.destroy();
-                  done();
-                }).then(null, assert.fail);
-              })
-            })
-          }).then(null, assert.fail);
+          sidebar.show()
+          .then(() => assert.equal(shownFired, 0, 'shown should not be fired again when already showing from after attach'))
+          .then(sidebar.hide.bind(sidebar))
+          .then(sidebar.show.bind(sidebar))
+          .then(() => assert.equal(shownFired, 1, 'shown was emitted when `show` called after being hidden'))
+          .then(sidebar.show.bind(sidebar))
+          .then(() => {
+            assert.equal(shownFired, 1, 'shown was not emitted again if already being shown');
+            sidebar.off('show', onShow);
+            sidebar.destroy();
+          }).catch(assert.fail).then(done);
         });
       }
     }
   });
 
   sidebar.show();
 }
 
--- a/addon-sdk/source/test/test-windows-common.js
+++ b/addon-sdk/source/test/test-windows-common.js
@@ -1,16 +1,19 @@
 /* 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 { Loader } = require('sdk/test/loader');
 const { browserWindows } = require('sdk/windows');
+const { viewFor } = require('sdk/view/core');
+const { modelFor } = require('sdk/model/core');
 const { Ci } = require("chrome");
+const { isBrowser, getWindowTitle } = require("sdk/window/utils");
 
 // TEST: browserWindows Iterator
 exports.testBrowserWindowsIterator = function(assert) {
   let activeWindowCount = 0;
   let windows = [];
   let i = 0;
   for each (let window in browserWindows) {
     if (window === browserWindows.activeWindow)
@@ -52,9 +55,42 @@ exports.testWindowActivateMethod_simple 
   window.activate();
 
   assert.equal(browserWindows.activeWindow, window,
                'Active window is active after window.activate() call');
   assert.equal(window.tabs.activeTab, tab,
                'Active tab is active after window.activate() call');
 };
 
+
+exports["test getView(window)"] = function(assert, done) {
+  browserWindows.once("open", window => {
+    const view = viewFor(window);
+
+    assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
+    assert.ok(isBrowser(view), "view is a browser window");
+    assert.equal(getWindowTitle(view), window.title,
+                 "window has a right title");
+
+    window.close(done);
+  });
+
+
+  browserWindows.open({ url: "data:text/html;charset=utf-8,<title>yo</title>" });
+};
+
+
+exports["test modelFor(window)"] = function(assert, done) {
+  browserWindows.once("open", window => {
+    const view = viewFor(window);
+
+    assert.ok(view instanceof Ci.nsIDOMWindow, "view is a window");
+    assert.ok(isBrowser(view), "view is a browser window");
+    assert.ok(modelFor(view) === window, "modelFor(browserWindow) is SDK window");
+
+    window.close(done);
+  });
+
+
+  browserWindows.open({ url: "data:text/html;charset=utf-8,<title>yo</title>" });
+};
+
 require('sdk/test').run(exports);
--- a/b2g/app/ua-update.json.in
+++ b/b2g/app/ua-update.json.in
@@ -1,17 +1,15 @@
 // Comments must be on their own lines and must start with "//"
 
 // Send these sites a custom user-agent. Bugs to remove each override after
 // evangelism are included.
 {
   // bug 826335, globo.com
   "globo.com": "\\(Mobile#(Android; Mobile",
-  // bug 826344, abril.com.br
-  "abril.com.br": "\\(Mobile#(Android; Mobile",
   // bug 826347, msn.com
   "msn.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
   // bug 826348, linkedin.com
   "linkedin.com": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
   // bug 826353, itau.com.br
   "itau.com.br": "\\(Mobile#(Android; Mobile",
   // bug 826504, orkut.com.br
   "orkut.com.br": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
@@ -38,30 +36,20 @@
   // bug 827573, webmotors.com.br
   "webmotors.com.br": "\\(Mobile#(Android; Mobile",
   // bug 827670, elpais.com.co
   "elpais.com.co": "Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19",
   // bug 827674, avianca.com
   "avianca.com": "\\(Mobile#(Android; Mobile",
   // bug 827678, marca.com
   "marca.com": "\\(Mobile#(Android; Mobile",
-  // bug 828354, gazeta.pl
-  "gazeta.pl": "\\(Mobile#(Android; Mobile",
-  // bug 828360, sport.pl
-  "sport.pl": "\\(Mobile#(Android; Mobile",
   // bug 828371, ingbank.pl
   "ingbank.pl": "\\(Mobile#(Android; Mobile",
-  // bug 828378, wyborcza.pl
-  "wyborcza.pl": "\\(Mobile#(Android; Mobile",
-  // bug 828380, deser.pl
-  "deser.pl": "\\(Mobile#(Android; Mobile",
   // bug 828386, ebay.es
   "ebay.es": "\\(Mobile#(Android; Mobile",
-  // bug 828392, infojobs.net
-  "infojobs.net": "\\(Mobile#(Android; Mobile",
   // bug 828399, antena3.com
   "antena3.com": "\\(Mobile#(Android; Mobile",
   // bug 828416, loteriasyapuestas.es
   "loteriasyapuestas.es": "\\(Mobile#(Android; Mobile",
   // bug 828418, bbva.es
   "bbva.es": "\\(Mobile#(Android; Mobile",
   // bug 828422, publico.es
   "publico.es": "\\(Mobile#(Android; Mobile",
@@ -74,50 +62,44 @@
   // bug 843132, comunio.es
   "comunio.es": "\\(Mobile#(Android; Mobile",
   // bug 843151, citibank.com
   "citibank.com": "\\(Mobile#(Android; Mobile",
   // bug 843153, games.com
   "games.com": "\\(Mobile#(Android; Mobile",
   // bug 843160, ehow.com
   "ehow.com": "\\(Mobile#(Android; Mobile",
-  // bug 866577, 3g.qq.com
-  "3g.qq.com": "\\(Mobile#(Android; Mobile",
   // bug 878228, blikk.hu
   "blikk.hu": "\\(Mobile#(Android; Mobile",
   // bug 878232, hazipatika.com
   "hazipatika.com": "\\(Mobile#(Android; Mobile",
   // bug 878238, koponyeg.hu
   "koponyeg.hu": "\\(Mobile#(Android; Mobile",
   // bug 878240, kuruc.info
   "kuruc.info": "\\(Mobile#(Android; Mobile",
   // bug 878242, nemzetisport.hu
   "nemzetisport.hu": "\\(Mobile#(Android; Mobile",
   // bug 878246, port.hu
   "port.hu": "\\(Mobile#(Android; Mobile",
   // bug 878249, portfolio.hu
   "portfolio.hu": "\\(Mobile#(Android; Mobile",
   // bug 878253, vatera.hu
   "vatera.hu": "\\(Mobile#(Android; Mobile",
-  // bug 878255, 24sata.hr
-  "24sata.hr": "\\(Mobile#(Android; Mobile",
   // bug 878260, cdm.me
   "cdm.me": "\\(Mobile#(Android; Mobile",
   // bug 878262, download.com
   "download.com": "\\(Mobile#(Android; Mobile",
   // bug 878264, haber.ba
   "haber.ba": "\\(Mobile#(Android; Mobile",
   // bug 878271, kurir-info.rs
   "kurir-info.rs": "\\(Mobile#(Android; Mobile",
   // bug 878273, livescore.com
   "livescore.com": "\\(Mobile#(Android; Mobile",
   // bug 878277, naslovi.net
   "naslovi.net": "\\(Mobile#(Android; Mobile",
-  // bug 878630, ask.com
-  "ask.com": "\\(Mobile#(Android; Mobile",
   // bug 878632, banorte.com
   "banorte.com": "\\(Mobile#(Android; Mobile",
   // bug 878649, univision.com
   "univision.com": "\\(Mobile#(Android; Mobile",
   // bug 878653, redstarbelgrade.info
   "redstarbelgrade.info": "\\(Mobile#(Android; Mobile",
   // bug 878655, vesti-online.com
   "vesti-online.com": "\\(Mobile#(Android; Mobile"
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="0292e64ef8451df104dcf9ac3b2c6749b81684dd"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="85f9690323b235f4dcf2901ea2240d3c60fc22a0"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,19 +10,19 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="65fba428f8d76336b33ddd9e15900357953600ba">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="0292e64ef8451df104dcf9ac3b2c6749b81684dd"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="85f9690323b235f4dcf2901ea2240d3c60fc22a0"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -13,18 +13,18 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "a0017eff21d39da46b6e8cf993f8fecf9ccb2af2", 
+    "revision": "dd1090309fea415972091d81b2c5fe5420759eeb", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,18 +10,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -14,18 +14,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,18 +12,18 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="56f79456db5dc3ca010a56d09e1e8cc15a2408db"/>
-  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="266bca6e60dad43e395f38b66edabe8bdc882334"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="cadddcac2b8ce162a5e27e6dc105557b00a94478"/>
+  <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2f28398184d20480254ca275a441a1c79a1a9d8c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d6c36d74ba9aefbc8c3618fc93dd4907a0dbf5e"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1396993434000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1398202482000">
   <emItems>
       <emItem  blockID="i454" id="sqlmoz@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                                 <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
@@ -177,17 +177,17 @@
               </prefs>
     </emItem>
       <emItem  blockID="i40" id="{28387537-e3f9-4ed7-860c-11e69af4a8a0}">
                         <versionRange  minVersion="0.1" maxVersion="4.3.1.00" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
-      <emItem  blockID="i566" id="{77BEC163-D389-42c1-91A4-C758846296A5}">
+      <emItem  blockID="i491" id="{515b2424-5911-40bd-8a2c-bdb20286d8f5}">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i498" id="hoverst@facebook.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
@@ -1098,16 +1098,22 @@
                               <versionRange  minVersion="3.0a1" maxVersion="*" />
                           </targetApplication>
                     </versionRange>
                                 <versionRange  minVersion="1.5.7.5" maxVersion="1.5.7.5" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
+      <emItem  blockID="i566" id="{77BEC163-D389-42c1-91A4-C758846296A5}">
+                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+                    </versionRange>
+                    <prefs>
+              </prefs>
+    </emItem>
       <emItem  blockID="i533" id="extension@Fast_Free_Converter.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i362" id="addon@defaulttab.com">
                         <versionRange  minVersion="0" maxVersion="1.4.4" severity="1">
@@ -1116,18 +1122,18 @@
               </prefs>
     </emItem>
       <emItem  blockID="i12" id="masterfiler@gmail.com">
                         <versionRange  severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
-      <emItem  blockID="i491" id="{515b2424-5911-40bd-8a2c-bdb20286d8f5}">
-                        <versionRange  minVersion="0" maxVersion="*" severity="1">
+      <emItem  blockID="i576" id="newmoz@facebook.com">
+                        <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i444" id="fplayer@adobe.flash">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1473,18 +1473,16 @@ pref("social.sidebar.unload_timeout_ms",
 pref("dom.identity.enabled", false);
 
 // Turn on the CSP 1.0 parser for Content Security Policy headers
 pref("security.csp.speccompliant", true);
 
 // Block insecure active content on https pages
 pref("security.mixed_content.block_active_content", true);
 
-pref("security.use_mozillapkix_verification", true);
-
 // Override the Gecko-default value of false for Firefox.
 pref("plain_text.wrap_long_lines", true);
 
 // If this turns true, Moz*Gesture events are not called stopPropagation()
 // before content.
 pref("dom.debug.propagate_gesture_events_through_content", false);
 
 // The request URL of the GeoLocation backend.
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -285,16 +285,21 @@ toolbarpaletteitem > #personal-bookmarks
 }
 
 toolbarpaletteitem > #personal-bookmarks > #bookmarks-toolbar-placeholder,
 #personal-bookmarks[cui-areatype="menu-panel"] > #bookmarks-toolbar-placeholder,
 #personal-bookmarks[cui-areatype="toolbar"][overflowedItem=true] > #bookmarks-toolbar-placeholder {
   display: -moz-box;
 }
 
+toolbar:not(#TabsToolbar) > #wrapper-personal-bookmarks,
+toolbar:not(#TabsToolbar) > #personal-bookmarks {
+  -moz-box-flex: 1;
+}
+
 #zoom-controls[cui-areatype="toolbar"]:not([overflowedItem=true]) > #zoom-reset-button > .toolbarbutton-text {
   display: -moz-box;
 }
 
 #urlbar-reload-button:not([displaystop]) + #urlbar-stop-button,
 #urlbar-reload-button[displaystop] {
   visibility: collapse;
 }
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -939,17 +939,16 @@
              mode="icons" iconsize="small"
              class="chromeclass-directories"
              context="toolbar-context-menu"
              defaultset="personal-bookmarks"
              toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"
              collapsed="true"
              customizable="true">
       <toolbaritem id="personal-bookmarks"
-                   flex="1"
                    title="&bookmarksToolbarItem.label;"
                    cui-areatype="toolbar"
                    removable="true">
         <toolbarbutton id="bookmarks-toolbar-placeholder"
                        class="toolbarbutton-1"
                        mousethrough="never"
                        label="&bookmarksToolbarItem.label;"
                        oncommand="PlacesToolbarHelper.onPlaceholderCommand();"/>
--- a/browser/base/content/newtab/grid.js
+++ b/browser/base/content/newtab/grid.js
@@ -193,17 +193,17 @@ let gGrid = {
       let refCell = document.querySelector(".newtab-cell");
       this._cellMargin = parseFloat(getComputedStyle(refCell).marginTop) * 2;
       this._cellHeight = refCell.offsetHeight + this._cellMargin;
       this._cellWidth = refCell.offsetWidth + this._cellMargin;
     }
 
     let availSpace = document.documentElement.clientHeight - this._cellMargin -
                      document.querySelector("#newtab-margin-undo-container").offsetHeight -
-                     document.querySelector("#newtab-search-form").offsetHeight;
+                     document.querySelector("#newtab-search-container").offsetHeight;
     let visibleRows = Math.floor(availSpace / this._cellHeight);
     this._node.style.height = this._computeHeight() + "px";
     this._node.style.maxHeight = this._computeHeight(visibleRows) + "px";
     this._node.style.maxWidth = gGridPrefs.gridColumns * this._cellWidth +
                                 GRID_WIDTH_EXTRA + "px";
 
     // Resize the search bar.
     let width = parseFloat(window.getComputedStyle(this._node).width);
--- a/browser/base/content/newtab/newTab.css
+++ b/browser/base/content/newtab/newTab.css
@@ -23,16 +23,17 @@ input[type=button] {
 #newtab-scrollbox:not([page-disabled]) {
   overflow: auto;
 }
 
 /* UNDO */
 #newtab-undo-container {
   transition: opacity 100ms ease-out;
   display: -moz-box;
+  margin-bottom: 26px; /* 32 - 6 search form top "padding" */
   -moz-box-align: center;
   -moz-box-pack: center;
 }
 
 #newtab-undo-container[undo-disabled] {
   opacity: 0;
   pointer-events: none;
 }
@@ -55,17 +56,16 @@ input[type=button] {
   position: relative;
   -moz-box-flex: 1;
   -moz-box-orient: vertical;
 }
 
 #newtab-margin-undo-container {
   display: -moz-box;
   -moz-box-pack: center;
-  margin-bottom: 26px; /* 32 - 6 search form top "padding" */
 }
 
 #newtab-horizontal-margin {
   display: -moz-box;
   -moz-box-flex: 1;
 }
 
 #newtab-margin-top,
--- a/browser/base/content/newtab/newTab.js
+++ b/browser/base/content/newtab/newTab.js
@@ -14,16 +14,18 @@ Cu.import("resource://gre/modules/Backgr
 Cu.import("resource://gre/modules/DirectoryLinksProvider.jsm");
 Cu.import("resource://gre/modules/NewTabUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Rect",
   "resource://gre/modules/Geometry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
+  "resource://gre/modules/UpdateChannel.jsm");
 
 let {
   links: gLinks,
   allPages: gAllPages,
   linkChecker: gLinkChecker,
   pinnedLinks: gPinnedLinks,
   blockedLinks: gBlockedLinks,
   gridPrefs: gGridPrefs
--- a/browser/base/content/newtab/newTab.xul
+++ b/browser/base/content/newtab/newTab.xul
@@ -15,17 +15,18 @@
   %searchBarDTD;
 ]>
 
 <xul:window id="newtab-window" xmlns="http://www.w3.org/1999/xhtml"
             xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
             title="&newtab.pageTitle;">
 
   <xul:panel id="sponsored-panel" orient="vertical" type="arrow">
-    <xul:description>&newtab.panel.message;</xul:description>
+    <xul:description id="sponsored-panel-release-descr">&newtab.sponsored.release.message;</xul:description>
+    <xul:description id="sponsored-panel-trial-descr">&newtab.sponsored.trial.message;</xul:description>
     <xul:label class="text-link"
                href="https://support.mozilla.org/kb/how-do-sponsored-tiles-work"
                value="&newtab.panel.link.text;" />
   </xul:panel>
 
   <xul:panel id="newtab-search-panel" orient="vertical" type="arrow"
              noautohide="true">
     <xul:hbox id="newtab-search-manage" class="newtab-search-panel-engine">
--- a/browser/base/content/newtab/page.js
+++ b/browser/base/content/newtab/page.js
@@ -23,16 +23,22 @@ let gPage = {
     // listening from xhtml nodes -- in particular middle clicks on sites, so
     // listen from the xul window and filter then delegate
     addEventListener("click", this, false);
 
     // Initialize sponsored panel
     this._sponsoredPanel = document.getElementById("sponsored-panel");
     let link = this._sponsoredPanel.querySelector(".text-link");
     link.addEventListener("click", () => this._sponsoredPanel.hidePopup());
+    if (UpdateChannel.get().startsWith("release")) {
+      document.getElementById("sponsored-panel-trial-descr").style.display = "none";
+    }
+    else {
+      document.getElementById("sponsored-panel-release-descr").style.display = "none";
+    }
 
     // Check if the new tab feature is enabled.
     let enabled = gAllPages.enabled;
     if (enabled)
       this._init();
 
     this._updateAttributes(enabled);
   },
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -8,17 +8,17 @@
 #include "AboutRedirector.h"
 #include "nsNetUtil.h"
 #include "nsIScriptSecurityManager.h"
 #include "mozilla/ArrayUtils.h"
 
 namespace mozilla {
 namespace browser {
 
-NS_IMPL_ISUPPORTS1(AboutRedirector, nsIAboutModule)
+NS_IMPL_ISUPPORTS(AboutRedirector, nsIAboutModule)
 
 struct RedirEntry {
   const char* id;
   const char* url;
   uint32_t flags;
 };
 
 /*
--- a/browser/components/customizableui/src/CustomizableUI.jsm
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -160,16 +160,25 @@ let CustomizableUIInternal = {
       "add-ons-button",
       "developer-button",
     ];
 
     if (gPalette.has("switch-to-metro-button")) {
       panelPlacements.push("switch-to-metro-button");
     }
 
+#ifdef NIGHTLY_BUILD
+    if (gPalette.has("e10s-button")) {
+      let newWindowIndex = panelPlacements.indexOf("new-window-button");
+      if (newWindowIndex > -1) {
+        panelPlacements.splice(newWindowIndex + 1, 0, "e10s-button");
+      }
+    }
+#endif
+
     let showCharacterEncoding = Services.prefs.getComplexValue(
       "browser.menu.showCharacterEncoding",
       Ci.nsIPrefLocalizedString
     ).data;
     if (showCharacterEncoding == "true") {
       panelPlacements.push("characterencoding-button");
     }
 
--- a/browser/components/customizableui/src/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/src/CustomizableWidgets.jsm
@@ -907,8 +907,41 @@ if (Services.metro && Services.metro.sup
       if (win && typeof win.SwitchToMetro == "function") {
         win.SwitchToMetro();
       }
     }
   });
 }
 #endif
 #endif
+
+#ifdef NIGHTLY_BUILD
+/**
+ * The e10s button's purpose is to lower the barrier of entry
+ * for our Nightly testers to use e10s windows. We'll be removing it
+ * once remote tabs are enabled. This button should never ever make it
+ * to production. If it does, that'd be bad, and we should all feel bad.
+ */
+if (Services.prefs.getBoolPref("browser.tabs.remote")) {
+  let getCommandFunction = function(aOpenRemote) {
+    return function(aEvent) {
+      let win = aEvent.view;
+      if (win && typeof win.OpenBrowserWindow == "function") {
+        win.OpenBrowserWindow({remote: aOpenRemote});
+      }
+    };
+  }
+
+  let openRemote = !Services.prefs.getBoolPref("browser.tabs.remote.autostart");
+  // Like the XUL menuitem counterparts, we hard-code these strings in because
+  // this button should never roll into production.
+  let buttonLabel = openRemote ? "New e10s Window"
+                               : "New Non-e10s Window";
+
+  CustomizableWidgets.push({
+    id: "e10s-button",
+    label: buttonLabel,
+    tooltiptext: buttonLabel,
+    defaultArea: CustomizableUI.AREA_PANEL,
+    onCommand: getCommandFunction(openRemote),
+  });
+}
+#endif
\ No newline at end of file
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -60,29 +60,16 @@ skip-if = e10s # Bug ?????? - test uses 
 [browser_940107_home_button_in_bookmarks_toolbar.js]
 [browser_940307_panel_click_closure_handling.js]
 [browser_940946_removable_from_navbar_customizemode.js]
 [browser_941083_invalidate_wrapper_cache_createWidget.js]
 [browser_942581_unregisterArea_keeps_placements.js]
 [browser_943683_migration_test.js]
 [browser_944887_destroyWidget_should_destroy_in_palette.js]
 [browser_945739_showInPrivateBrowsing_customize_mode.js]
-[browser_947914_button_addons.js]
-[browser_947914_button_copy.js]
-[browser_947914_button_cut.js]
-[browser_947914_button_find.js]
-[browser_947914_button_history.js]
-[browser_947914_button_newPrivateWindow.js]
-[browser_947914_button_newWindow.js]
-[browser_947914_button_paste.js]
-[browser_947914_button_print.js]
-[browser_947914_button_savePage.js]
-[browser_947914_button_zoomIn.js]
-[browser_947914_button_zoomOut.js]
-[browser_947914_button_zoomReset.js]
 [browser_947987_removable_default.js]
 [browser_948985_non_removable_defaultArea.js]
 [browser_952963_areaType_getter_no_area.js]
 [browser_956602_remove_special_widget.js]
 [browser_962884_opt_in_disable_hyphens.js]
 [browser_963639_customizing_attribute_non_customizable_toolbar.js]
 [browser_967000_button_charEncoding.js]
 skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s friendly.
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_addons.js
+++ /dev/null
@@ -1,34 +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";
-
-add_task(function() {
-  info("Check addons button existence and functionality");
-
-  let initialLocation = gBrowser.currentURI.spec;
-
-  yield PanelUI.show();
-
-  let addonsButton = document.getElementById("add-ons-button");
-  ok(addonsButton, "Add-ons button exists in Panel Menu");
-  addonsButton.click();
-
-  yield waitForCondition(function() gBrowser.currentURI &&
-                                    gBrowser.currentURI.spec == "about:addons");
-
-  let addonsPage = gBrowser.selectedBrowser.contentWindow.document.
-                            getElementById("addons-page");
-  ok(addonsPage, "Add-ons page was opened");
-
-  // close the add-ons tab
-  if(gBrowser.tabs.length > 1) {
-    gBrowser.removeTab(gBrowser.selectedTab);
-  }
-  else {
-    var tabToRemove = gBrowser.selectedTab;
-    gBrowser.addTab(initialLocation);
-    gBrowser.removeTab(tabToRemove);
-  }
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_copy.js
+++ /dev/null
@@ -1,51 +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";
-
-add_task(function() {
-  info("Check copy button existence and functionality");
-
-  var testText = "copy text test";
-  let initialLocation = gBrowser.currentURI.spec;
-
-  yield PanelUI.show();
-
-  let copyButton = document.getElementById("copy-button");
-  ok(copyButton, "Copy button exists in Panel Menu");
-  is(copyButton.getAttribute("disabled"), "true", "Copy button is initially disabled");
-
-  // copy text from URL bar
-  gURLBar.value = testText;
-  gURLBar.focus();
-  gURLBar.select();
-  yield PanelUI.show();
-
-  ok(!copyButton.hasAttribute("disabled"), "Copy button gets enabled");
-
-  copyButton.click();
-  is(gURLBar.value, testText, "Selected text is unaltered when clicking copy");
-
-  // check that the text was added to the clipboard
-  let clipboard = Services.clipboard;
-  let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
-  const globalClipboard = clipboard.kGlobalClipboard;
-
-  transferable.init(null);
-  transferable.addDataFlavor("text/unicode");
-  clipboard.getData(transferable, globalClipboard);
-  let str = {}, strLength = {};
-  transferable.getTransferData("text/unicode", str, strLength);
-  let clipboardValue = "";
-
-  if (str.value) {
-    str.value.QueryInterface(Ci.nsISupportsString);
-    clipboardValue = str.value.data;
-  }
-  is(clipboardValue, testText, "Data was copied to the clipboard.");
-
-  // restore the tab location and clear the clipboard
-  Services.clipboard.emptyClipboard(globalClipboard);
-  gURLBar.value = initialLocation;
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_cut.js
+++ /dev/null
@@ -1,50 +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";
-
-add_task(function() {
-  info("Check cut button existence and functionality");
-
-  var testText = "cut text test";
-  let initialLocation = gBrowser.currentURI.spec;
-
-  yield PanelUI.show();
-
-  let cutButton = document.getElementById("cut-button");
-  ok(cutButton, "Cut button exists in Panel Menu");
-  ok(cutButton.getAttribute("disabled"), "Cut button is disabled");
-
-  // cut text from URL bar
-  gURLBar.value = testText;
-  gURLBar.focus();
-  gURLBar.select();
-  yield PanelUI.show();
-
-  ok(!cutButton.hasAttribute("disabled"), "Cut button gets enabled");
-  cutButton.click();
-  is(gURLBar.value, "", "Selected text is removed from source when clicking on cut");
-
-  // check that the text was added to the clipboard
-  let clipboard = Services.clipboard;
-  let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
-  const globalClipboard = clipboard.kGlobalClipboard;
-
-  transferable.init(null);
-  transferable.addDataFlavor("text/unicode");
-  clipboard.getData(transferable, globalClipboard);
-  let str = {}, strLength = {};
-  transferable.getTransferData("text/unicode", str, strLength);
-  let clipboardValue = "";
-
-  if (str.value) {
-    str.value.QueryInterface(Ci.nsISupportsString);
-    clipboardValue = str.value.data;
-  }
-  is(clipboardValue, testText, "Data was copied to the clipboard.");
-
-  // restore the tab location and clear the clipboard
-  gBrowser.value = initialLocation;
-  Services.clipboard.emptyClipboard(globalClipboard);
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_find.js
+++ /dev/null
@@ -1,20 +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";
-
-add_task(function() {
-  info("Check find button existence and functionality");
-
-  yield PanelUI.show();
-
-  let findButton = document.getElementById("find-button");
-  ok(findButton, "Find button exists in Panel Menu");
-
-  findButton.click();
-  ok(!gFindBar.hasAttribute("hidden"), "Findbar opened successfully");
-
-  // close find bar
-  gFindBar.close();
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_history.js
+++ /dev/null
@@ -1,22 +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";
-
-add_task(function() {
-  info("Check history button existence and functionality");
-
-  yield PanelUI.show();
-
-  let historyButton = document.getElementById("history-panelmenu");
-  ok(historyButton, "History button appears in Panel Menu");
-
-  historyButton.click();
-  let historyPanel = document.getElementById("PanelUI-history");
-  ok(historyPanel.getAttribute("current"), "History Panel is in view");
-
-  let panelHiddenPromise = promisePanelHidden(window);
-  PanelUI.hide();
-  yield panelHiddenPromise
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_newPrivateWindow.js
+++ /dev/null
@@ -1,45 +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";
-
-add_task(function() {
-  info("Check private browsing button existence and functionality");
-  yield PanelUI.show();
-
-  var windowWasHandled = false;
-  let privateWindow = null;
-
-  let observerWindowOpened = {
-    observe: function(aSubject, aTopic, aData) {
-      if (aTopic == "domwindowopened") {
-        privateWindow = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
-        privateWindow.addEventListener("load", function newWindowHandler() {
-          privateWindow.removeEventListener("load", newWindowHandler, false);
-          is(privateWindow.location.href, "chrome://browser/content/browser.xul",
-             "A new browser window was opened");
-          ok(PrivateBrowsingUtils.isWindowPrivate(privateWindow), "Window is private");
-          windowWasHandled = true;
-        }, false);
-      }
-    }
-  }
-
-  Services.ww.registerNotification(observerWindowOpened);
-
-  let privateBrowsingButton = document.getElementById("privatebrowsing-button");
-  ok(privateBrowsingButton, "Private browsing button exists in Panel Menu");
-  privateBrowsingButton.click();
-
-  try{
-    yield waitForCondition(() => windowWasHandled);
-    yield promiseWindowClosed(privateWindow);
-  }
-  catch(e) {
-    ok(false, "The new private browser window was not properly handled");
-  }
-  finally {
-    Services.ww.unregisterNotification(observerWindowOpened);
-  }
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_newWindow.js
+++ /dev/null
@@ -1,45 +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";
-
-add_task(function() {
-  info("Check new window button existence and functionality");
-  yield PanelUI.show();
-
-  var windowWasHandled = false;
-  var newWindow = null;
-
-  let observerWindowOpened = {
-    observe: function(aSubject, aTopic, aData) {
-      if (aTopic == "domwindowopened") {
-        newWindow = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
-        newWindow.addEventListener("load", function newWindowHandler() {
-          newWindow.removeEventListener("load", newWindowHandler, false);
-          is(newWindow.location.href, "chrome://browser/content/browser.xul",
-             "A new browser window was opened");
-          ok(!PrivateBrowsingUtils.isWindowPrivate(newWindow), "Window is not private");
-          windowWasHandled = true;
-        }, false);
-      }
-    }
-  }
-
-  Services.ww.registerNotification(observerWindowOpened);
-
-  let newWindowButton = document.getElementById("new-window-button");
-  ok(newWindowButton, "New Window button exists in Panel Menu");
-  newWindowButton.click();
-
-  try{
-    yield waitForCondition(() => windowWasHandled);
-    yield promiseWindowClosed(newWindow);
-  }
-  catch(e) {
-    ok(false, "The new browser window was not properly handled");
-  }
-  finally {
-    Services.ww.unregisterNotification(observerWindowOpened);
-  }
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_paste.js
+++ /dev/null
@@ -1,35 +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";
-
-add_task(function() {
-  info("Check paste button existence and functionality");
-
-  let initialLocation = gBrowser.currentURI.spec;
-  let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
-  const globalClipboard = Services.clipboard.kGlobalClipboard;
-
-  yield PanelUI.show();
-
-  let pasteButton = document.getElementById("paste-button");
-  ok(pasteButton, "Paste button exists in Panel Menu");
-
-  // add text to clipboard
-  var text = "Sample text for testing";
-  clipboard.copyString(text);
-
-  // test paste button by pasting text to URL bar
-  gURLBar.focus();
-  yield PanelUI.show();
-
-  ok(!pasteButton.hasAttribute("disabled"), "Paste button is enabled");
-  pasteButton.click();
-
-  is(gURLBar.value, text, "Text pasted successfully");
-
-  // clear the clipboard and restore the tab location as it was at the begining of the test
-  Services.clipboard.emptyClipboard(globalClipboard);
-  gURLBar.value = initialLocation;
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_print.js
+++ /dev/null
@@ -1,32 +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 isOSX = (Services.appinfo.OS === "Darwin");
-
-add_task(function() {
-  info("Check print button existence and functionality");
-
-  yield PanelUI.show();
-
-  let printButton = document.getElementById("print-button");
-  ok(printButton, "Print button exists in Panel Menu");
-
-  if(isOSX) {
-    let panelHiddenPromise = promisePanelHidden(window);
-    PanelUI.hide();
-    yield panelHiddenPromise;
-  }
-  else {
-    printButton.click();
-    yield waitForCondition(() => window.gInPrintPreviewMode);
-
-    ok(window.gInPrintPreviewMode, "Entered print preview mode");
-
-    // close print preview
-    PrintUtils.exitPrintPreview();
-    yield waitForCondition(() => !window.gInPrintPreviewMode);
-  }
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_savePage.js
+++ /dev/null
@@ -1,18 +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";
-
-add_task(function() {
-  info("Check save page button existence");
-
-  yield PanelUI.show();
-
-  let savePageButton = document.getElementById("save-page-button");
-  ok(savePageButton, "Save Page button exists in Panel Menu");
-
-  let panelHiddenPromise = promisePanelHidden(window);
-  PanelUI.hide();
-  yield panelHiddenPromise;
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_zoomIn.js
+++ /dev/null
@@ -1,31 +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";
-
-add_task(function() {
-  info("Check zoom in button existence and functionality");
-
-  let initialPageZoom = ZoomManager.zoom;
-  is(initialPageZoom, 1, "Initial zoom factor should be 1");
-
-  yield PanelUI.show();
-
-  let zoomInButton = document.getElementById("zoom-in-button");
-  ok(zoomInButton, "Zoom in button exists in Panel Menu");
-
-  zoomInButton.click();
-  let pageZoomLevel = parseInt(ZoomManager.zoom * 100);
-  let zoomResetButton = document.getElementById("zoom-reset-button");
-  let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
-  ok(pageZoomLevel > 100 && pageZoomLevel == expectedZoomLevel, "Page zoomed in correctly");
-
-  // close the Panel
-  let panelHiddenPromise = promisePanelHidden(window);
-  PanelUI.hide();
-  yield panelHiddenPromise;
-
-  // reset zoom level
-  ZoomManager.zoom = initialPageZoom;
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_zoomOut.js
+++ /dev/null
@@ -1,32 +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";
-
-add_task(function() {
-  info("Check zoom out button existence and functionality");
-
-  let initialPageZoom = ZoomManager.zoom;
-  is(initialPageZoom, 1, "Initial zoom factor should be 1");
-
-  yield PanelUI.show();
-
-  let zoomOutButton = document.getElementById("zoom-out-button");
-  ok(zoomOutButton, "Zoom out button exists in Panel Menu");
-
-  zoomOutButton.click();
-  let pageZoomLevel = Math.round(ZoomManager.zoom*100);
-
-  let zoomResetButton = document.getElementById("zoom-reset-button");
-  let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
-  ok(pageZoomLevel < 100 && pageZoomLevel == expectedZoomLevel, "Page zoomed out correctly");
-
-  // close the panel
-  let panelHiddenPromise = promisePanelHidden(window);
-  PanelUI.hide();
-  yield panelHiddenPromise;
-
-  // reset zoom level
-  ZoomManager.zoom = initialPageZoom;
-});
deleted file mode 100644
--- a/browser/components/customizableui/test/browser_947914_button_zoomReset.js
+++ /dev/null
@@ -1,30 +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";
-
-add_task(function() {
-  info("Check zoom reset button existence and functionality");
-
-  let initialPageZoom = ZoomManager.zoom;
-  is(initialPageZoom, 1, "Initial zoom factor should be 1");
-  ZoomManager.zoom = 0.5;
-  yield PanelUI.show();
-
-  let zoomResetButton = document.getElementById("zoom-reset-button");
-  ok(zoomResetButton, "Zoom reset button exists in Panel Menu");
-
-  zoomResetButton.click();
-  let pageZoomLevel = parseInt(ZoomManager.zoom * 100);
-  let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
-  ok(pageZoomLevel == expectedZoomLevel && pageZoomLevel == 100, "Page zoom reset correctly");
-
-  // close the panel
-  let panelHiddenPromise = promisePanelHidden(window);
-  PanelUI.hide();
-  yield panelHiddenPromise;
-
-  //reset the zoom level
-  ZoomManager.zoom = initialPageZoom;
-});
--- a/browser/components/dirprovider/DirectoryProvider.cpp
+++ b/browser/components/dirprovider/DirectoryProvider.cpp
@@ -22,19 +22,19 @@
 #include "nsServiceManagerUtils.h"
 #include "nsStringAPI.h"
 #include "nsXULAppAPI.h"
 #include "nsIPrefLocalizedString.h"
 
 namespace mozilla {
 namespace browser {
 
-NS_IMPL_ISUPPORTS2(DirectoryProvider,
-                   nsIDirectoryServiceProvider,
-                   nsIDirectoryServiceProvider2)
+NS_IMPL_ISUPPORTS(DirectoryProvider,
+                  nsIDirectoryServiceProvider,
+                  nsIDirectoryServiceProvider2)
 
 NS_IMETHODIMP
 DirectoryProvider::GetFile(const char *aKey, bool *aPersist, nsIFile* *aResult)
 {
   nsresult rv;
 
   *aResult = nullptr;
 
@@ -249,17 +249,17 @@ DirectoryProvider::GetFiles(const char *
       return NS_ERROR_OUT_OF_MEMORY;
 
     return NS_NewUnionEnumerator(aResult, extEnum, baseEnum);
   }
 
   return NS_ERROR_FAILURE;
 }
 
-NS_IMPL_ISUPPORTS1(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator)
+NS_IMPL_ISUPPORTS(DirectoryProvider::AppendingEnumerator, nsISimpleEnumerator)
 
 NS_IMETHODIMP
 DirectoryProvider::AppendingEnumerator::HasMoreElements(bool *aResult)
 {
   *aResult = mNext ? true : false;
   return NS_OK;
 }
 
--- a/browser/components/feeds/src/nsFeedSniffer.cpp
+++ b/browser/components/feeds/src/nsFeedSniffer.cpp
@@ -34,20 +34,20 @@
 #define TYPE_RSS "application/rss+xml"
 #define TYPE_MAYBE_FEED "application/vnd.mozilla.maybe.feed"
 
 #define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 #define NS_RSS "http://purl.org/rss/1.0/"
 
 #define MAX_BYTES 512u
 
-NS_IMPL_ISUPPORTS3(nsFeedSniffer,
-                   nsIContentSniffer,
-                   nsIStreamListener,
-                   nsIRequestObserver)
+NS_IMPL_ISUPPORTS(nsFeedSniffer,
+                  nsIContentSniffer,
+                  nsIStreamListener,
+                  nsIRequestObserver)
 
 nsresult
 nsFeedSniffer::ConvertEncodedData(nsIRequest* request,
                                   const uint8_t* data,
                                   uint32_t length)
 {
   nsresult rv = NS_OK;
 
--- a/browser/components/migration/src/nsIEHistoryEnumerator.cpp
+++ b/browser/components/migration/src/nsIEHistoryEnumerator.cpp
@@ -36,17 +36,17 @@ namespace {
     return PR_ImplodeTime(&prt);
   }
 
 } // Anonymous namespace.
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsIEHistoryEnumerator
 
-NS_IMPL_ISUPPORTS1(nsIEHistoryEnumerator, nsISimpleEnumerator)
+NS_IMPL_ISUPPORTS(nsIEHistoryEnumerator, nsISimpleEnumerator)
 
 nsIEHistoryEnumerator::nsIEHistoryEnumerator()
 {
   ::CoInitialize(nullptr);  
 }
 
 nsIEHistoryEnumerator::~nsIEHistoryEnumerator()
 {
--- a/browser/components/preferences/in-content/applications.js
+++ b/browser/components/preferences/in-content/applications.js
@@ -1682,18 +1682,20 @@ var gApplicationsPane = {
   manageApp: function(aEvent) {
     // Don't let the normal "on select action" handler get this event,
     // as we handle it specially ourselves.
     aEvent.stopPropagation();
 
     var typeItem = this._list.selectedItem;
     var handlerInfo = this._handledTypes[typeItem.type];
 
-    document.documentElement.openSubDialog("chrome://browser/content/preferences/applicationManager.xul",
-                                           "", handlerInfo);
+    openDialog("chrome://browser/content/preferences/applicationManager.xul",
+               "",
+               "modal,centerscreen,resizable=no",
+               handlerInfo);
 
     // Rebuild the actions menu so that we revert to the previous selection,
     // or "Always ask" if the previous default application has been removed
     this.rebuildActionsMenu();
 
     // update the richlistitem too. Will be visible when selecting another row
     typeItem.setAttribute("actionDescription",
                           this._describePreferredAction(handlerInfo));
--- a/browser/components/shell/src/nsGNOMEShellService.cpp
+++ b/browser/components/shell/src/nsGNOMEShellService.cpp
@@ -111,17 +111,17 @@ nsGNOMEShellService::Init()
   nsCOMPtr<nsIFile> appPath;
   rv = dirSvc->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
                    getter_AddRefs(appPath));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return appPath->GetNativePath(mAppPath);
 }
 
-NS_IMPL_ISUPPORTS1(nsGNOMEShellService, nsIShellService)
+NS_IMPL_ISUPPORTS(nsGNOMEShellService, nsIShellService)
 
 bool
 nsGNOMEShellService::GetAppPathFromLauncher()
 {
   gchar *tmp;
 
   const char *launcher = PR_GetEnv("MOZ_APP_LAUNCHER");
   if (!launcher)
--- a/browser/components/shell/src/nsMacShellService.cpp
+++ b/browser/components/shell/src/nsMacShellService.cpp
@@ -26,17 +26,17 @@
 #include <CoreFoundation/CoreFoundation.h>
 #include <ApplicationServices/ApplicationServices.h>
 
 #define NETWORK_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/Network.prefPane")
 #define DESKTOP_PREFPANE NS_LITERAL_CSTRING("/System/Library/PreferencePanes/DesktopScreenEffectsPref.prefPane")
 
 #define SAFARI_BUNDLE_IDENTIFIER "com.apple.Safari"
 
-NS_IMPL_ISUPPORTS3(nsMacShellService, nsIMacShellService, nsIShellService, nsIWebProgressListener)
+NS_IMPL_ISUPPORTS(nsMacShellService, nsIMacShellService, nsIShellService, nsIWebProgressListener)
 
 NS_IMETHODIMP
 nsMacShellService::IsDefaultBrowser(bool aStartupCheck,
                                     bool aForAllTypes,
                                     bool* aIsDefaultBrowser)
 {
   *aIsDefaultBrowser = false;
 
--- a/browser/components/shell/src/nsWindowsShellService.cpp
+++ b/browser/components/shell/src/nsWindowsShellService.cpp
@@ -55,17 +55,17 @@
   (val != ERROR_SUCCESS)
 
 #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
 
 using mozilla::IsWin8OrLater;
 using namespace mozilla;
 using namespace mozilla::gfx;
 
-NS_IMPL_ISUPPORTS2(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
+NS_IMPL_ISUPPORTS(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
 
 static nsresult
 OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
 {
   const nsString &flatName = PromiseFlatString(aKeyName);
 
   DWORD res = ::RegOpenKeyExW(aKeyRoot, flatName.get(), 0, KEY_READ, aKey);
   switch (res) {
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -241,16 +241,17 @@ support-files =
 [browser_dbg_variables-view-02.js]
 [browser_dbg_variables-view-03.js]
 [browser_dbg_variables-view-04.js]
 [browser_dbg_variables-view-05.js]
 [browser_dbg_variables-view-accessibility.js]
 [browser_dbg_variables-view-data.js]
 [browser_dbg_variables-view-edit-cancel.js]
 [browser_dbg_variables-view-edit-click.js]
+skip-if = (os == 'mac' || os == 'win') && (debug == false) # Bug 986166
 [browser_dbg_variables-view-edit-getset-01.js]
 [browser_dbg_variables-view-edit-getset-02.js]
 [browser_dbg_variables-view-edit-value.js]
 [browser_dbg_variables-view-edit-watch.js]
 [browser_dbg_variables-view-filter-01.js]
 [browser_dbg_variables-view-filter-02.js]
 [browser_dbg_variables-view-filter-03.js]
 [browser_dbg_variables-view-filter-04.js]
--- a/browser/devtools/eyedropper/eyedropper.js
+++ b/browser/devtools/eyedropper/eyedropper.js
@@ -110,16 +110,18 @@ function Eyedropper(chromeWindow, opts =
   this._onFrameLoaded = this._onFrameLoaded.bind(this);
 
   this._chromeWindow = chromeWindow;
   this._chromeDocument = chromeWindow.document;
 
   this._dragging = true;
   this.loaded = false;
 
+  this._mouseMoveCounter = 0;
+
   this.format = Services.prefs.getCharPref(FORMAT_PREF); // color value format
   this.zoom = Services.prefs.getIntPref(ZOOM_PREF);      // zoom level - integer
 
   this._zoomArea = {
     x: 0,          // the left coordinate of the center of the inspected region
     y: 0,          // the top coordinate of the center of the inspected region
     width: CANVAS_WIDTH,      // width of canvas to draw zoomed area onto
     height: CANVAS_WIDTH      // height of canvas
@@ -373,16 +375,21 @@ Eyedropper.prototype = {
    * @param  {DOMEvent} event
    *         MouseEvent for the mouse moving
    */
   _onMouseMove: function(event) {
     if (!this._dragging || !this._panel || !this._canvas) {
       return;
     }
 
+    if (this._OS == "Linux" && ++this._mouseMoveCounter % 2 == 0) {
+      // skip every other mousemove to preserve performance.
+      return;
+    }
+
     this._setCoordinates(event);
     this._drawWindow();
 
     let { panelX, panelY } = this._getPanelCoordinates(event);
     this._movePanel(panelX, panelY);
   },
 
   /**
--- a/browser/devtools/sourceeditor/editor.js
+++ b/browser/devtools/sourceeditor/editor.js
@@ -1031,39 +1031,42 @@ function detectIndentation(ed) {
       return;
     }
     if (width > 1) {
       total++;
     }
 
     // see how much this line is offset from the line above it
     let indent = Math.abs(width - last);
-    if (indent > 1) {
+    if (indent > 1 && indent <= 8) {
       spaces[indent] = (spaces[indent] || 0) + 1;
     }
     last = width;
   });
 
   // this file is not indented at all
   if (total == 0) {
     return null;
   }
 
   // mark as tabs if they start more than half the lines
   if (tabs >= total / 2) {
     return { tabs: true };
   }
 
   // find most frequent non-zero width difference between adjacent lines
-  let freqIndent = null, max = 0;
+  let freqIndent = null, max = 1;
   for (let width in spaces) {
     width = parseInt(width, 10);
     let tally = spaces[width];
     if (tally > max) {
       max = tally;
       freqIndent = width;
     }
   }
+  if (!freqIndent) {
+    return null;
+  }
 
   return { tabs: false, spaces: freqIndent };
 }
 
 module.exports = Editor;
--- a/browser/devtools/sourceeditor/test/browser_detectindent.js
+++ b/browser/devtools/sourceeditor/test/browser_detectindent.js
@@ -52,26 +52,39 @@ const TABS_CODE = [
 "\tbackground: blue;",
 "}",
 "",
 "span {",
 "\tpadding-left: 10px;",
 "}"
 ].join("\n");
 
+const NONE_CODE = [
+"var x = 0;",
+"           // stray thing",
+"var y = 9;",
+"    ",
+""
+].join("\n");
 
 function test() {
   waitForExplicitFinish();
 
   setup((ed, win) => {
     is(ed.getOption("indentUnit"), 2,
        "2 spaces before code added");
     is(ed.getOption("indentWithTabs"), false,
        "spaces is default");
 
+    ed.setText(NONE_CODE);
+    is(ed.getOption("indentUnit"), 2,
+       "2 spaces after un-detectable code");
+    is(ed.getOption("indentWithTabs"), false,
+       "spaces still set after un-detectable code");
+
     ed.setText(FOUR_SPACES_CODE);
     is(ed.getOption("indentUnit"), 4,
        "4 spaces detected in 4 space code");
     is(ed.getOption("indentWithTabs"), false,
        "spaces detected in 4 space code");
 
     ed.setText(TWO_SPACES_CODE);
     is(ed.getOption("indentUnit"), 2,
--- a/browser/devtools/webconsole/console-output.js
+++ b/browser/devtools/webconsole/console-output.js
@@ -63,19 +63,16 @@ const COMPAT = {
   CATEGORY_CLASS_FRAGMENTS: [ "network", "cssparser", "exception", "console",
                               "input", "output", "security" ],
 
   // The fragment of a CSS class name that identifies each severity.
   SEVERITY_CLASS_FRAGMENTS: [ "error", "warn", "info", "log" ],
 
   // The indent of a console group in pixels.
   GROUP_INDENT: 12,
-
-  // The default indent in pixels, applied even without any groups.
-  GROUP_INDENT_DEFAULT: 6,
 };
 
 // A map from the console API call levels to the Web Console severities.
 const CONSOLE_API_LEVELS_TO_SEVERITIES = {
   error: "error",
   exception: "error",
   assert: "error",
   warn: "warning",
@@ -812,32 +809,34 @@ Messages.Simple.prototype = Heritage.ext
 
     let timestamp = new Widgets.MessageTimestamp(this, this.timestamp).render();
 
     let icon = this.document.createElementNS(XHTML_NS, "span");
     icon.className = "icon";
 
     // Apply the current group by indenting appropriately.
     // TODO: remove this once bug 778766 is fixed.
-    let iconMarginLeft = this._groupDepthCompat * COMPAT.GROUP_INDENT +
-                         COMPAT.GROUP_INDENT_DEFAULT;
-    icon.style.marginLeft = iconMarginLeft + "px";
+    let indent = this._groupDepthCompat * COMPAT.GROUP_INDENT;
+    let indentNode = this.document.createElementNS(XHTML_NS, "span");
+    indentNode.className = "indent";
+    indentNode.style.width = indent + "px";
 
     let body = this._renderBody();
     this._repeatID.textContent += "|" + body.textContent;
 
     let repeatNode = this._renderRepeatNode();
     let location = this._renderLocation();
 
     Messages.BaseMessage.prototype.render.call(this);
     if (this._className) {
       this.element.className += " " + this._className;
     }
 
     this.element.appendChild(timestamp.element);
+    this.element.appendChild(indentNode);
     this.element.appendChild(icon);
     this.element.appendChild(body);
     if (repeatNode) {
       this.element.appendChild(repeatNode);
     }
     if (location) {
       this.element.appendChild(location);
     }
@@ -1105,24 +1104,24 @@ Messages.Extended.prototype = Heritage.e
    *        Value grip from the server.
    * @return string
    *         The class name for the grip.
    */
   getClassNameForValueGrip: function(grip)
   {
     let map = {
       "number": "cm-number",
-      "longstring": "cm-string",
-      "string": "cm-string",
+      "longstring": "console-string",
+      "string": "console-string",
       "regexp": "cm-string-2",
       "boolean": "cm-atom",
       "-infinity": "cm-atom",
       "infinity": "cm-atom",
       "null": "cm-atom",
-      "undefined": "cm-atom",
+      "undefined": "cm-comment",
     };
 
     let className = map[typeof grip];
     if (!className && grip && grip.type) {
       className = map[grip.type.toLowerCase()];
     }
     if (!className && grip && grip.class) {
       className = map[grip.class.toLowerCase()];
@@ -2112,18 +2111,18 @@ Widgets.ObjectRenderers.add({
       }
 
       let keyElem = this.message._renderValueGrip(key, {
         concise: true,
         noStringQuotes: true,
       });
 
       // Strings are property names.
-      if (keyElem.classList && keyElem.classList.contains("cm-string")) {
-        keyElem.classList.remove("cm-string");
+      if (keyElem.classList && keyElem.classList.contains("console-string")) {
+        keyElem.classList.remove("console-string");
         keyElem.classList.add("cm-property");
       }
 
       container.appendChild(keyElem);
 
       this._text(": ");
 
       let valueElem = this.message._renderValueGrip(value, { concise: true });
@@ -2187,17 +2186,17 @@ Widgets.ObjectRenderers.add({
   {
     let {preview} = this.objectActor;
     this.element = this.el("span.kind-" + preview.kind);
 
     this._anchor(this.objectActor.class, { className: "cm-variable" });
 
     if (!this.options.concise) {
       this._text(" ");
-      this.element.appendChild(this.el("span.cm-string",
+      this.element.appendChild(this.el("span.console-string",
                                        VariablesView.getString(preview.text)));
     }
   },
 });
 
 /**
  * The widget used for displaying DOM event previews.
  */
@@ -2331,31 +2330,32 @@ Widgets.ObjectRenderers.add({
     let fragment = this.document.createDocumentFragment();
     if (addLink) {
       this._anchor(nodeName, { className: "cm-attribute", appendTo: fragment });
     } else {
       fragment.appendChild(this.el("span.cm-attribute", nodeName));
     }
 
     this._text("=", fragment);
-    fragment.appendChild(this.el("span.cm-string", '"' + escapeHTML(value) + '"'));
+    fragment.appendChild(this.el("span.console-string",
+                                 '"' + escapeHTML(value) + '"'));
 
     return fragment;
   },
 
   _renderTextNode: function()
   {
     let {preview} = this.objectActor;
     this.element = this.el("span.textNode.kind-" + preview.kind);
 
     this._anchor(preview.nodeName, { className: "cm-variable" });
     this._text(" ");
 
     let text = VariablesView.getString(preview.textContent);
-    this.element.appendChild(this.el("span.cm-string", text));
+    this.element.appendChild(this.el("span.console-string", text));
   },
 
   _renderCommentNode: function()
   {
     let {preview} = this.objectActor;
     let comment = "<!-- " + VariablesView.getString(preview.textContent, {
       noStringQuotes: true,
     }) + " -->";
@@ -2673,17 +2673,17 @@ Widgets.LongString.prototype = Heritage.
 
   render: function()
   {
     if (this.element) {
       return this;
     }
 
     let result = this.element = this.document.createElementNS(XHTML_NS, "span");
-    result.className = "longString cm-string";
+    result.className = "longString console-string";
     this._renderString(this.longStringActor.initial);
     result.appendChild(this._renderEllipsis());
 
     return this;
   },
 
   /**
    * Render the long string in the widget element.
--- a/browser/devtools/webconsole/test/head.js
+++ b/browser/devtools/webconsole/test/head.js
@@ -31,19 +31,16 @@ const CATEGORY_SECURITY = 6;
 const SEVERITY_ERROR = 0;
 const SEVERITY_WARNING = 1;
 const SEVERITY_INFO = 2;
 const SEVERITY_LOG = 3;
 
 // The indent of a console group in pixels.
 const GROUP_INDENT = 12;
 
-// The default indent in pixels, applied even without any groups.
-const GROUP_INDENT_DEFAULT = 6;
-
 const WEBCONSOLE_STRINGS_URI = "chrome://browser/locale/devtools/webconsole.properties";
 let WCU_l10n = new WebConsoleUtils.l10n(WEBCONSOLE_STRINGS_URI);
 
 gDevTools.testing = true;
 SimpleTest.registerCleanupFunction(() => {
   gDevTools.testing = false;
 });
 
@@ -1199,20 +1196,20 @@ function waitForMessages(aOptions)
     if ("repeats" in aRule) {
       let repeats = aElement.querySelector(".message-repeats");
       if (!repeats || repeats.getAttribute("value") != aRule.repeats) {
         return false;
       }
     }
 
     if ("groupDepth" in aRule) {
-      let icon = aElement.querySelector(".icon");
-      let indent = (GROUP_INDENT * aRule.groupDepth + GROUP_INDENT_DEFAULT) + "px";
-      if (!icon || icon.style.marginLeft != indent) {
-        is(icon.style.marginLeft, indent,
+      let indentNode = aElement.querySelector(".indent");
+      let indent = (GROUP_INDENT * aRule.groupDepth)  + "px";
+      if (!indentNode || indentNode.style.width != indent) {
+        is(indentNode.style.width, indent,
            "group depth check failed for message rule: " + displayRule(aRule));
         return false;
       }
     }
 
     if ("longString" in aRule) {
       let longStrings = aElement.querySelectorAll(".longStringEllipsis");
       if (aRule.longString != !!longStrings[0]) {
--- a/browser/devtools/webconsole/webconsole.js
+++ b/browser/devtools/webconsole/webconsole.js
@@ -140,19 +140,16 @@ const MAX_HTTP_ERROR_CODE = 599;
 
 // Constants used for defining the direction of JSTerm input history navigation.
 const HISTORY_BACK = -1;
 const HISTORY_FORWARD = 1;
 
 // The indent of a console group in pixels.
 const GROUP_INDENT = 12;
 
-// The default indent in pixels, applied even without any groups.
-const GROUP_INDENT_DEFAULT = 6;
-
 // The number of messages to display in a single display update. If we display
 // too many messages at once we slow the Firefox UI too much.
 const MESSAGES_IN_INTERVAL = DEFAULT_LOG_LIMIT;
 
 // The delay between display updates - tells how often we should *try* to push
 // new messages to screen. This value is optimistic, updates won't always
 // happen. Keep this low so the Web Console output feels live.
 const OUTPUT_INTERVAL = 50; // milliseconds
@@ -2444,26 +2441,29 @@ WebConsoleFrame.prototype = {
   createMessageNode:
   function WCF_createMessageNode(aCategory, aSeverity, aBody, aSourceURL,
                                  aSourceLine, aClipboardText, aLevel, aTimeStamp)
   {
     if (typeof aBody != "string" && aClipboardText == null && aBody.innerText) {
       aClipboardText = aBody.innerText;
     }
 
+    let indentNode = this.document.createElementNS(XHTML_NS, "span");
+    indentNode.className = "indent";
+
+    // Apply the current group by indenting appropriately.
+    let indent = this.groupDepth * GROUP_INDENT;
+    indentNode.style.width = indent + "px";
+
     // Make the icon container, which is a vertical box. Its purpose is to
     // ensure that the icon stays anchored at the top of the message even for
     // long multi-line messages.
     let iconContainer = this.document.createElementNS(XHTML_NS, "span");
     iconContainer.className = "icon";
 
-    // Apply the current group by indenting appropriately.
-    let iconMarginLeft = this.groupDepth * GROUP_INDENT + GROUP_INDENT_DEFAULT;
-    iconContainer.style.marginLeft = iconMarginLeft + "px";
-
     // Create the message body, which contains the actual text of the message.
     let bodyNode = this.document.createElementNS(XHTML_NS, "span");
     bodyNode.className = "message-body-wrapper message-body devtools-monospace";
 
     // Store the body text, since it is needed later for the variables view.
     let body = aBody;
     // If a string was supplied for the body, turn it into a DOM node and an
     // associated clipboard string now.
@@ -2523,16 +2523,17 @@ WebConsoleFrame.prototype = {
     // Create the source location (e.g. www.example.com:6) that sits on the
     // right side of the message, if applicable.
     let locationNode;
     if (aSourceURL && IGNORED_SOURCE_URLS.indexOf(aSourceURL) == -1) {
       locationNode = this.createLocationNode(aSourceURL, aSourceLine);
     }
 
     node.appendChild(timestampNode);
+    node.appendChild(indentNode);
     node.appendChild(iconContainer);
 
     // Display the variables view after the message node.
     if (aLevel == "dir") {
       bodyNode.style.height = (this.window.innerHeight *
                                CONSOLE_DIR_VIEW_HEIGHT) + "px";
 
       let options = {
--- a/browser/locales/en-US/chrome/browser-region/region.properties
+++ b/browser/locales/en-US/chrome/browser-region/region.properties
@@ -8,17 +8,17 @@ browser.search.defaultenginename=Google
 # Search engine order (order displayed in the search bar dropdown)s
 browser.search.order.1=Google
 browser.search.order.2=Yahoo
 browser.search.order.3=Bing
 
 # This is the default set of web based feed handlers shown in the reader
 # selection UI
 browser.contentHandlers.types.0.title=My Yahoo!
-browser.contentHandlers.types.0.uri=http://add.my.yahoo.com/rss?url=%s
+browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
 
 # increment this number when anything gets changed in the list below.  This will
 # cause Firefox to re-read these prefs and inject any new handlers into the 
 # profile database.  Note that "new" is defined as "has a different URL"; this
 # means that it's not possible to update the name of existing handler, so 
 # don't make any spelling errors here.
 gecko.handlerService.defaultHandlersVersion=4
 
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -254,17 +254,17 @@ These should match what Safari and other
   -  application menu item that opens the browser toolbox UI in the Tools menu. -->
 <!ENTITY browserToolboxMenu.label     "Browser Toolbox">
 <!ENTITY browserToolboxMenu.accesskey "e">
 
 <!ENTITY devToolbarCloseButton.tooltiptext "Close Developer Toolbar">
 <!ENTITY devToolbarMenu.label              "Developer Toolbar">
 <!ENTITY devToolbarMenu.accesskey          "v">
 <!ENTITY devAppMgrMenu.label               "App Manager">
-<!ENTITY devAppMgrMenu.accesskey           "a">
+<!ENTITY devAppMgrMenu.accesskey           "A">
 <!ENTITY devToolbar.keycode                "VK_F2">
 <!ENTITY devToolbar.keytext                "F2">
 <!ENTITY devToolboxMenuItem.label          "Toggle Tools">
 <!ENTITY devToolboxMenuItem.accesskey      "T">
 <!ENTITY devToolboxMenuItem.keytext        "I">
 
 <!ENTITY devToolbarToolsButton.tooltip     "Toggle developer tools">
 <!ENTITY devToolbarOtherToolsButton.label  "More Tools">
--- a/browser/locales/en-US/chrome/browser/devtools/styleeditor.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/styleeditor.properties
@@ -53,17 +53,17 @@ saveStyleSheet.title=Save style sheet
 saveStyleSheet.filter=CSS files
 
 # LOCALIZATION NOTE  (open.commandkey): This the key to use in
 # conjunction with shift to open the style editor
 open.commandkey=VK_F7
 
 # LOCALIZATION NOTE (open.accesskey): The access key used to open the style
 # editor.
-open.accesskey=y
+open.accesskey=l
 
 # LOCALIZATION NOTE  (saveStyleSheet.commandkey): This the key to use in
 # conjunction with accel (Command on Mac or Ctrl on other platforms) to Save
 saveStyleSheet.commandkey=S
 
 # LOCALIZATION NOTE  (showOriginalSources.label): This is the label on the context
 # menu item to toggle showing original sources in the editor.
 showOriginalSources.label=Show original sources
--- a/browser/locales/en-US/chrome/browser/newTab.dtd
+++ b/browser/locales/en-US/chrome/browser/newTab.dtd
@@ -3,10 +3,11 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!-- These strings are used in the about:newtab page -->
 <!ENTITY newtab.pageTitle "New Tab">
 <!ENTITY newtab.undo.removedLabel "Thumbnail removed.">
 <!ENTITY newtab.undo.undoButton "Undo.">
 <!ENTITY newtab.undo.restoreButton "Restore All.">
 <!ENTITY newtab.undo.closeTooltip "Hide">
-<!ENTITY newtab.panel.message "This site is being suggested because it has sponsored Mozilla, helping us promote openness, innovation and opportunity on the Web.">
+<!ENTITY newtab.sponsored.release.message "This Sponsor site was suggested because we hoped you’d find it interesting and because it supports Mozilla’s mission.">
+<!ENTITY newtab.sponsored.trial.message "This Trial Sponsor site was suggested because we hoped you’d find it interesting and because it supports Mozilla’s mission.">
 <!ENTITY newtab.panel.link.text "Learn more…">
--- a/browser/metro/base/content/contenthandlers/FormHelper.js
+++ b/browser/metro/base/content/contenthandlers/FormHelper.js
@@ -445,17 +445,18 @@ FormAssistant.prototype = {
 
   /** Caret is used to input text for this element. */
   _getCaretRect: function _formHelperGetCaretRect() {
     let element = this.currentElement;
     let focusedElement = gFocusManager.getFocusedElementForWindow(content, true, {});
     if (element && (element.mozIsTextField && element.mozIsTextField(false) ||
         element instanceof HTMLTextAreaElement) && focusedElement == element && this._isVisibleElement(element)) {
       let utils = Util.getWindowUtils(element.ownerDocument.defaultView);
-      let rect = utils.sendQueryContentEvent(utils.QUERY_CARET_RECT, element.selectionEnd, 0, 0, 0);
+      let rect = utils.sendQueryContentEvent(utils.QUERY_CARET_RECT, element.selectionEnd, 0, 0, 0,
+                                             utils.QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
       if (rect) {
         let scroll = ContentScroll.getScrollOffset(element.ownerDocument.defaultView);
         return new Rect(scroll.x + rect.left, scroll.y + rect.top, rect.width, rect.height);
       }
     }
 
     return new Rect(0, 0, 0, 0);
   },
--- a/browser/metro/base/content/contenthandlers/SelectionHandler.js
+++ b/browser/metro/base/content/contenthandlers/SelectionHandler.js
@@ -442,19 +442,21 @@ var SelectionHandler = {
     let position = Util.centerElementInView(aNewViewHeight, this._cache.element);
     if (position !== undefined) {
       return position;
     }
 
     // Special case: we are dealing with an input that is taller than the
     // desired height of content. We need to center on the caret location.
     let rect =
-      this._domWinUtils.sendQueryContentEvent(this._domWinUtils.QUERY_CARET_RECT,
-                                              this._targetElement.selectionEnd,
-                                              0, 0, 0);
+      this._domWinUtils.sendQueryContentEvent(
+        this._domWinUtils.QUERY_CARET_RECT,
+        this._targetElement.selectionEnd,
+        0, 0, 0,
+        this._domWinUtils.QUERY_CONTENT_FLAG_USE_XP_LINE_BREAK);
     if (!rect || !rect.succeeded) {
       Util.dumpLn("no caret was present, unexpected.");
       return 0;
     }
 
     // Note sendQueryContentEvent with QUERY_CARET_RECT is really buggy. If it
     // can't find the exact location of the caret position it will "guess".
     // Sometimes this can put the result in unexpected locations.
--- a/browser/metro/profile/metro.js
+++ b/browser/metro/profile/metro.js
@@ -329,18 +329,16 @@ pref("browser.urlbar.search.timeout", 10
 pref("browser.urlbar.restrict.history", "^");
 pref("browser.urlbar.restrict.bookmark", "*");
 pref("browser.urlbar.restrict.tag", "+");
 pref("browser.urlbar.match.title", "#");
 pref("browser.urlbar.match.url", "@");
 pref("browser.history.grouping", "day");
 pref("browser.history.showSessions", false);
 pref("browser.sessionhistory.max_entries", 50);
-pref("browser.history_expire_days", 180);
-pref("browser.history_expire_days_min", 90);
 pref("browser.history_expire_sites", 40000);
 pref("browser.places.migratePostDataAnnotations", true);
 pref("browser.places.updateRecentTagsUri", true);
 pref("places.frecency.numVisits", 10);
 pref("places.frecency.numCalcOnIdle", 50);
 pref("places.frecency.numCalcOnMigrate", 50);
 pref("places.frecency.updateIdleTime", 60000);
 pref("places.frecency.firstBucketCutoff", 4);
--- a/browser/themes/linux/preferences/in-content/preferences.css
+++ b/browser/themes/linux/preferences/in-content/preferences.css
@@ -21,37 +21,33 @@ menulist:not([editable="true"]) > .menul
 
 checkbox {
   -moz-binding: url("chrome://global/content/bindings/checkbox.xml#checkbox");
   -moz-box-align: center;
 }
 
 checkbox:hover::before,
 checkbox[checked]::before {
-  margin-top: 7px;
-  margin-bottom: 6px;
   -moz-margin-end: -19px;
   -moz-margin-start: 4px;
   background-repeat: no-repeat;
 }
 
 radio {
   -moz-binding: url("chrome://global/content/bindings/radio.xml#radio");
   -moz-box-align: center;
-  margin: 7px 0;
+  -moz-margin-start: 0;
 }
 
 .radio-label-box {
   -moz-appearance: none;
 }
 
 radio:hover::before,
 radio[selected]::before {
-  margin-top: 6px;
-  margin-bottom: 6px;
   -moz-margin-end: -17px;
   -moz-margin-start: 6px;
 }
 
 .numberbox-input-box {
   -moz-appearance: none;
   border-width: 0;
 }
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -696,16 +696,20 @@ toolbar .toolbarbutton-1 > .toolbarbutto
   #characterencoding-button@toolbarButtonPressed@ {
     -moz-image-region: rect(18px, 324px, 36px, 306px);
   }
 
   #new-window-button@toolbarButtonPressed@ {
     -moz-image-region: rect(18px, 342px, 36px, 324px);
   }
 
+  #e10s-button@toolbarButtonPressed@ {
+    -moz-image-region: rect(18px, 342px, 36px, 324px);
+  }
+
   #new-tab-button@toolbarButtonPressed@ {
     -moz-image-region: rect(18px, 360px, 36px, 342px);
   }
 
   #privatebrowsing-button@toolbarButtonPressed@ {
     -moz-image-region: rect(18px, 378px, 36px, 360px);
   }
 
@@ -937,16 +941,28 @@ toolbar .toolbarbutton-1 > .toolbarbutto
   #new-window-button[cui-areatype="toolbar"] {
     -moz-image-region: rect(0, 684px, 36px, 648px);
   }
 
   #new-window-button[cui-areatype="toolbar"]:hover:active:not([disabled="true"]) {
     -moz-image-region: rect(36px, 684px, 72px, 648px);
   }
 
+  #e10s-button[cui-areatype="toolbar"] {
+    -moz-image-region: rect(0, 684px, 36px, 648px);
+  }
+
+  #e10s-button[cui-areatype="toolbar"]:hover:active:not([disabled="true"]) {
+    -moz-image-region: rect(36px, 684px, 72px, 648px);
+  }
+
+  #e10s-button > .toolbarbutton-icon {
+    transform: scaleY(-1);
+  }
+
   #new-tab-button[cui-areatype="toolbar"] {
     -moz-image-region: rect(0, 720px, 36px, 684px);
   }
 
   #new-tab-button[cui-areatype="toolbar"]:hover:active:not([disabled="true"]) {
     -moz-image-region: rect(36px, 720px, 72px, 684px);
   }
 
@@ -1185,16 +1201,21 @@ toolbar .toolbarbutton-1 > .toolbarbutto
     -moz-image-region: rect(64px, 960px, 128px, 896px);
   }
 
   #new-window-button[cui-areatype="menu-panel"],
   toolbarpaletteitem[place="palette"] > #new-window-button {
     -moz-image-region: rect(0px, 1024px, 64px, 960px);
   }
 
+  #e10s-button[cui-areatype="menu-panel"],
+  toolbarpaletteitem[place="palette"] > #e10s-button {
+    -moz-image-region: rect(0px, 1024px, 64px, 960px);
+  }
+
   #new-tab-button[cui-areatype="menu-panel"],
   toolbarpaletteitem[place="palette"] > #new-tab-button {
     -moz-image-region: rect(0px, 1088px, 64px, 1024px);
   }
 
   #privatebrowsing-button[cui-areatype="menu-panel"],
   toolbarpaletteitem[place="palette"] > #privatebrowsing-button {
     -moz-image-region: rect(0px, 1152px, 64px, 1088px);
--- a/browser/themes/osx/preferences/in-content/preferences.css
+++ b/browser/themes/osx/preferences/in-content/preferences.css
@@ -7,17 +7,16 @@
 menulist:not([editable="true"]) > .menulist-dropmarker {
   display: -moz-box;
   margin-top: 1px;
   margin-bottom: 1px;
 }
 
 checkbox:hover::before,
 checkbox[checked]::before {
-  margin-bottom: -2px;
   -moz-margin-end: -20px;
   -moz-margin-start: 5px;
 }
 
 radio:hover::before,
 radio[selected]::before {
   -moz-margin-end: -18px;
   -moz-margin-start: 7px;
--- a/browser/themes/shared/browser.inc
+++ b/browser/themes/shared/browser.inc
@@ -1,13 +1,13 @@
 %filter substitution
 
 % Note that zoom-reset-button is a bit different since it doesn't use an image and thus has the image with display: none.
 %define nestedButtons #zoom-out-button, #zoom-reset-button, #zoom-in-button, #cut-button, #copy-button, #paste-button
-%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@
+%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #fullscreen-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #switch-to-metro-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button, #sidebar-button, @nestedButtons@, #e10s-button
 
 %ifdef XP_MACOSX
 % Prior to 10.7 there wasn't a native fullscreen button so we use #restore-button to exit fullscreen
 % and want it to behave like other toolbar buttons.
 %define primaryToolbarButtons @primaryToolbarButtons@, #restore-button
 %endif
 
 %define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]), [overflowedItem=true])
--- a/browser/themes/shared/devtools/webconsole.inc.css
+++ b/browser/themes/shared/devtools/webconsole.inc.css
@@ -13,39 +13,45 @@ a {
 
 /* Workaround for Bug 575675 - FindChildWithRules aRelevantLinkVisited
  * assertion when loading HTML page with links in XUL iframe */
 *:visited { }
 
 .message {
   display: flex;
   flex: 0 0 auto;
-  -moz-margin-start: 6px;
-  -moz-margin-end: 8px;
-  width: calc(100% - 6px - 8px);
+  padding: 0 7px;
+  width: 100%;
+  box-sizing: border-box;
 }
 
 .message > .timestamp {
   flex: 0 0 auto;
   color: GrayText;
-  margin: 4px 0;
+  margin: 4px 6px 0 0;
+}
+
+.message > .indent {
+  flex: 0 0 auto;
 }
 
 .message > .icon {
   background: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 0, 1, 0, 0) no-repeat;
-  background-position: center 0.5em;
+  background-position: center;
   flex: 0 0 auto;
-  margin: 0 6px;
+  margin: 3px 6px 0 0;
   padding: 0 4px;
   width: 8px;
+  height: 1em;
+  align-self: flex-start;
 }
 
 .message > .message-body-wrapper {
   flex: 1 1 100%;
-  margin-top: 4px;
+  margin: 3px;
 }
 
 /* The red bubble that shows the number of times a message is repeated */
 .message-repeats {
   -moz-user-select: none;
   flex: 0 0 auto;
   margin: 2px 6px;
   padding: 0 6px;
@@ -58,23 +64,22 @@ a {
   font-weight: 600;
 }
 
 .message-repeats[value="1"] {
   display: none;
 }
 
 .message-location {
-  -moz-margin-start: 6px;
   display: flex;
   flex: 0 0 auto;
   align-self: flex-start;
   justify-content: flex-end;
   width: 10em;
-  margin: 3px 0;
+  margin-top: 3px;
   color: -moz-nativehyperlinktext;
   text-decoration: none;
   white-space: nowrap;
 }
 
 .message-location:hover,
 .message-location:focus {
   text-decoration: underline;
@@ -97,16 +102,21 @@ a {
 .message-body {
   white-space: pre-wrap;
   word-wrap: break-word;
 }
 
 .message-flex-body > .message-body {
   display: block;
   flex: 1 1 auto;
+  vertical-align: middle;
+}
+
+.message-flex-body > .message-location {
+  margin-top: 0;
 }
 
 .jsterm-input-container {
   border-top-width: 1px;
   border-top-style: solid;
 }
 
 #output-wrapper {
@@ -117,20 +127,34 @@ a {
 #output-container {
   -moz-user-select: text;
   -moz-box-flex: 1;
   display: flex;
   flex-direction: column;
   align-items: flex-start;
 }
 
+#output-container.hideTimestamps > .message {
+  -moz-padding-start: 0;
+  -moz-margin-start: 7px;
+  width: calc(100% - 7px);
+}
+
 #output-container.hideTimestamps > .message > .timestamp {
   display: none;
 }
 
+.theme-dark #output-container.hideTimestamps > .message > .indent {
+  background-color: #14171a; /* .theme-body */
+}
+
+.theme-light #output-container.hideTimestamps > .message > .indent {
+  background-color: #fcfcfc; /* .theme-body */
+}
+
 .filtered-by-type,
 .filtered-by-string {
   display: none;
 }
 
 .hidden-message {
   display: block;
   visibility: hidden;
@@ -165,21 +189,29 @@ a {
   border-color: #777;
 }
 
 .theme-light .message[severity=error] {
   background-color: rgba(255, 150, 150, 0.3);
 }
 
 .theme-dark .message[severity=error] {
-  background-color: rgba(255, 100, 100, 0.3);
+  background-color: rgba(235, 83, 104, 0.17);
+}
+
+.theme-dark .console-string {
+  color: #d99b28;
 }
 
-.message[category=network] > .icon {
-  -moz-border-start: solid #000 6px;
+.theme-light .console-string {
+  color: hsl(24,85%,39%);
+}
+
+.message[category=network] > .indent {
+  -moz-border-end: solid #000 6px;
 }
 
 .message[category=network][severity=error] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 0, 16, 8, 8);
 }
 
 .message[category=network] > .message-body {
   display: flex;
@@ -214,73 +246,73 @@ a {
 }
 
 /* CSS styles */
 .webconsole-filter-button[category="css"] > .toolbarbutton-menubutton-button:before {
   background-image: linear-gradient(#2DC3F3, #00B6F0);
   border-color: #1BA2CC;
 }
 
-.message[category=cssparser] > .icon {
-  -moz-border-start: solid #00b6f0 6px;
+.message[category=cssparser] > .indent {
+  -moz-border-end: solid #00b6f0 6px;
 }
 
 .message[category=cssparser][severity=error] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 8, 16, 16, 8);
 }
 
 .message[category=cssparser][severity=warn] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 8, 24, 16, 16);
 }
 
 /* JS styles */
 .webconsole-filter-button[category="js"] > .toolbarbutton-menubutton-button:before {
   background-image: linear-gradient(#FCB142, #FB9500);
   border-color: #E98A00;
 }
 
-.message[category=exception] > .icon {
-  -moz-border-start: solid #fb9500 6px;
+.message[category=exception] > .indent {
+  -moz-border-end: solid #fb9500 6px;
 }
 
 .message[category=exception][severity=error] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 16, 16, 24, 8);
 }
 
 .message[category=exception][severity=warn] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 16, 24, 24, 16);
 }
 
 /* Web Developer styles */
 .webconsole-filter-button[category="logging"] > .toolbarbutton-menubutton-button:before {
   background-image: linear-gradient(#B9B9B9, #AAAAAA);
   border-color: #929292;
 }
 
-.message[category=console] > .icon {
-  -moz-border-start: solid #cbcbcb 6px;
+.message[category=console] > .indent {
+  -moz-border-end: solid #cbcbcb 6px;
 }
 
 .message[category=console][severity=error] > .icon,
 .message[category=output][severity=error] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 24, 16, 32, 8);
 }
 
 .message[category=console][severity=warn] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 24, 24, 32, 16);
 }
 
 .message[category=console][severity=info] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 24, 32, 32, 24);
 }
 
 /* Input and output styles */
-.message[category=input] > .icon,
-.message[category=output] > .icon {
-  -moz-border-start: solid #808080 6px;
+.message[category=input] > .indent,
+.message[category=output] > .indent {
+  -moz-border-end: solid #808080 6px;
 }
 
 .message[category=input] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 24, 40, 32, 32);
 }
 
 .message[category=output] > .icon {
   background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 24, 48, 32, 40);
@@ -324,18 +356,18 @@ a {
 }
 
 .devtools-side-splitter ~ #webconsole-sidebar[hidden] {
   display: none;
 }
 
 /* Security styles */
 
-.message[category=security] > .icon {
-  -moz-border-start: solid red 6px;
+.message[category=security] > .indent {
+  -moz-border-end: solid red 6px;
 }
 
 .webconsole-filter-button[category="security"] > .toolbarbutton-menubutton-button:before {
   background-image: linear-gradient(#FF3030, #FF7D7D);
   border-color: #D12C2C;
 }
 
 .message[category=security][severity=error] > .icon {
@@ -381,17 +413,17 @@ a {
 
 .message[open] .stacktrace {
   display: block;
 }
 
 .message .theme-twisty {
   display: inline-block;
   vertical-align: middle;
-  margin: 2px 3px 0 0;
+  margin: 0 3px 0 0;
 }
 
 .stacktrace li {
   display: flex;
   margin: 0;
 }
 
 .stacktrace .function {
--- a/browser/themes/shared/incontentprefs/preferences.css
+++ b/browser/themes/shared/incontentprefs/preferences.css
@@ -337,17 +337,18 @@ html|a.inline-link {
 .inline-link:hover:active {
   color: #FF9500;
   text-decoration: none;
 }
 
 /* Checkboxes and radio buttons */
 
 checkbox {
-  margin: 7px 0;
+  -moz-margin-start: 0;
+  position: relative;
 }
 
 .checkbox-check {
   -moz-appearance: none;
   width: 23px;
   height: 23px;
   border-radius: 2px;
   border: 1px solid rgba(23,50,77,0.40);
@@ -410,24 +411,27 @@ checkbox[checked]::before {
 }
 
 .radio-label-box {
   -moz-margin-start: -1px; /* negative margin for the transparent border */
   -moz-margin-end: 10px;
   -moz-padding-start: 0;
 }
 
+radio {
+  position: relative;
+}
+
 radio:hover::before,
 radio[selected]::before {
   position: absolute;
   content: "";
   width: 11px;
   height: 11px;
   border-radius: 50%;
-  margin-bottom: 1px;
   background-image: linear-gradient(rgba(76,177,255,0.25) 0%, rgba(23,146,229,0.25) 100%);
 }
 
 radio[selected]::before {
   background-image: linear-gradient(#4cb1ff 0%, #1792e5 100%);
 }
 
 /* Category List */
@@ -675,21 +679,16 @@ radio[selected]::before {
     -moz-image-region: rect(0, 480px, 80px, 400px);
   }
 
   #header-advanced > .header-icon {
     -moz-image-region: rect(0, 560px, 80px, 480px);
   }
 }
 
-.indent {
-  margin-top: 7px;
-  margin-bottom: 7px;
-}
-
 /* General Pane */
 
 filefield {
   -moz-appearance: none;
   background-color: transparent;
   border: none;
   padding: 0;
 }
--- a/browser/themes/shared/menupanel.inc.css
+++ b/browser/themes/shared/menupanel.inc.css
@@ -78,16 +78,21 @@ toolbarpaletteitem[place="palette"] > #c
   -moz-image-region: rect(32px, 480px, 64px, 448px);
 }
 
 #new-window-button[cui-areatype="menu-panel"],
 toolbarpaletteitem[place="palette"] > #new-window-button {
   -moz-image-region: rect(0px, 512px, 32px, 480px);
 }
 
+#e10s-button[cui-areatype="menu-panel"],
+toolbarpaletteitem[place="palette"] > #e10s-button {
+  -moz-image-region: rect(0px, 512px, 32px, 480px);
+}
+
 #new-tab-button[cui-areatype="menu-panel"],
 toolbarpaletteitem[place="palette"] > #new-tab-button {
   -moz-image-region: rect(0px, 544px, 32px, 512px);
 }
 
 #privatebrowsing-button[cui-areatype="menu-panel"],
 toolbarpaletteitem[place="palette"] > #privatebrowsing-button {
   -moz-image-region: rect(0px, 576px, 32px, 544px);
--- a/browser/themes/shared/toolbarbuttons.inc.css
+++ b/browser/themes/shared/toolbarbuttons.inc.css
@@ -80,16 +80,24 @@
 #characterencoding-button[cui-areatype="toolbar"]{
   -moz-image-region: rect(0, 324px, 18px, 306px);
 }
 
 #new-window-button[cui-areatype="toolbar"] {
   -moz-image-region: rect(0, 342px, 18px, 324px);
 }
 
+#e10s-button[cui-areatype="toolbar"] {
+  -moz-image-region: rect(0, 342px, 18px, 324px);
+}
+
+#e10s-button > .toolbarbutton-icon {
+  transform: scaleY(-1);
+}
+
 #new-tab-button[cui-areatype="toolbar"] {
   -moz-image-region: rect(0, 360px, 18px, 342px);
 }
 
 #privatebrowsing-button[cui-areatype="toolbar"] {
   -moz-image-region: rect(0, 378px, 18px, 360px);
 }
 
--- a/browser/themes/windows/preferences/in-content/preferences.css
+++ b/browser/themes/windows/preferences/in-content/preferences.css
@@ -6,24 +6,23 @@
 
 menulist:not([editable="true"]) > .menulist-dropmarker {
   margin-top: 1px;
   margin-bottom: 1px;
 }
 
 checkbox:hover::before,
 checkbox[checked]::before {
-  margin-bottom: -1px;
   -moz-margin-end: -19px;
   -moz-margin-start: 4px;
 }
 
 radio {
   -moz-binding: url("chrome://global/content/bindings/radio.xml#radio");
-  margin: 7px 0;
+  -moz-margin-start: 0;
 }
 
 radio:hover::before,
 radio[selected]::before {
   -moz-margin-end: -17px;
   -moz-margin-start: 6px;
 }
 
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -3,17 +3,16 @@
  * 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 nsPrincipal_h__
 #define nsPrincipal_h__
 
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
-#include "nsVoidArray.h"
 #include "nsJSPrincipals.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "nsIProtocolHandler.h"
 #include "nsNetUtil.h"
 #include "nsScriptSecurityManager.h"
 
 class nsIObjectInputStream;
--- a/caps/src/DomainPolicy.cpp
+++ b/caps/src/DomainPolicy.cpp
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DomainPolicy.h"
 #include "nsScriptSecurityManager.h"
 
 namespace mozilla {
 
-NS_IMPL_ISUPPORTS1(DomainPolicy, nsIDomainPolicy)
+NS_IMPL_ISUPPORTS(DomainPolicy, nsIDomainPolicy)
 
 DomainPolicy::DomainPolicy() : mBlacklist(new DomainSet())
                              , mSuperBlacklist(new DomainSet())
                              , mWhitelist(new DomainSet())
                              , mSuperWhitelist(new DomainSet())
 {}
 
 DomainPolicy::~DomainPolicy()
@@ -87,17 +87,17 @@ GetCanonicalClone(nsIURI* aURI)
     NS_ENSURE_SUCCESS(rv, nullptr);
     rv = clone->SetUserPass(EmptyCString());
     NS_ENSURE_SUCCESS(rv, nullptr);
     rv = clone->SetPath(EmptyCString());
     NS_ENSURE_SUCCESS(rv, nullptr);
     return clone.forget();
 }
 
-NS_IMPL_ISUPPORTS1(DomainSet, nsIDomainSet)
+NS_IMPL_ISUPPORTS(DomainSet, nsIDomainSet)
 
 NS_IMETHODIMP
 DomainSet::Add(nsIURI* aDomain)
 {
     nsCOMPtr<nsIURI> clone = GetCanonicalClone(aDomain);
     NS_ENSURE_TRUE(clone, NS_ERROR_FAILURE);
     mHashTable.PutEntry(clone);
     return NS_OK;
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -24,22 +24,22 @@
 #include "nsPrincipal.h"
 #include "nsScriptSecurityManager.h"
 #include "pratom.h"
 
 using namespace mozilla;
 
 NS_IMPL_CLASSINFO(nsNullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_NULLPRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(nsNullPrincipal,
+                           nsIPrincipal,
+                           nsISerializable)
+NS_IMPL_CI_INTERFACE_GETTER(nsNullPrincipal,
                             nsIPrincipal,
                             nsISerializable)
-NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
-                             nsIPrincipal,
-                             nsISerializable)
 
 NS_IMETHODIMP_(MozExternalRefCountType)
 nsNullPrincipal::AddRef()
 {
   NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt");
   nsrefcnt count = ++refcount;
   NS_LOG_ADDREF(this, count, "nsNullPrincipal", sizeof(*this));
   return count;
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -111,22 +111,22 @@ void nsPrincipal::dumpImpl()
   nsAutoCString str;
   GetScriptLocation(str);
   fprintf(stderr, "nsPrincipal (%p) = %s\n", static_cast<void*>(this), str.get());
 }
 #endif 
 
 NS_IMPL_CLASSINFO(nsPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_PRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE2_CI(nsPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(nsPrincipal,
+                           nsIPrincipal,
+                           nsISerializable)
+NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
                             nsIPrincipal,
                             nsISerializable)
-NS_IMPL_CI_INTERFACE_GETTER2(nsPrincipal,
-                             nsIPrincipal,
-                             nsISerializable)
 NS_IMPL_ADDREF_INHERITED(nsPrincipal, nsBasePrincipal)
 NS_IMPL_RELEASE_INHERITED(nsPrincipal, nsBasePrincipal)
 
 nsPrincipal::nsPrincipal()
   : mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
   , mInMozBrowser(false)
   , mCodebaseImmutable(false)
   , mDomainImmutable(false)
@@ -622,20 +622,20 @@ nsPrincipal::GetAppStatus()
 }
 
 /************************************************************************************************************************/
 
 static const char EXPANDED_PRINCIPAL_SPEC[] = "[Expanded Principal]";
 
 NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_EXPANDEDPRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE2_CI(nsExpandedPrincipal,
-                            nsIPrincipal,
-                            nsIExpandedPrincipal)
-NS_IMPL_CI_INTERFACE_GETTER2(nsExpandedPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(nsExpandedPrincipal,
+                           nsIPrincipal,
+                           nsIExpandedPrincipal)
+NS_IMPL_CI_INTERFACE_GETTER(nsExpandedPrincipal,
                              nsIPrincipal,
                              nsIExpandedPrincipal)
 NS_IMPL_ADDREF_INHERITED(nsExpandedPrincipal, nsBasePrincipal)
 NS_IMPL_RELEASE_INHERITED(nsExpandedPrincipal, nsBasePrincipal)
 
 nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr <nsIPrincipal> > &aWhiteList)
 {
   mPrincipals.AppendElements(aWhiteList);
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -334,21 +334,21 @@ nsScriptSecurityManager::GetCxSubjectPri
 
 /////////////////////////////
 // nsScriptSecurityManager //
 /////////////////////////////
 
 ////////////////////////////////////
 // Methods implementing ISupports //
 ////////////////////////////////////
-NS_IMPL_ISUPPORTS4(nsScriptSecurityManager,
-                   nsIScriptSecurityManager,
-                   nsIXPCSecurityManager,
-                   nsIChannelEventSink,
-                   nsIObserver)
+NS_IMPL_ISUPPORTS(nsScriptSecurityManager,
+                  nsIScriptSecurityManager,
+                  nsIXPCSecurityManager,
+                  nsIChannelEventSink,
+                  nsIObserver)
 
 ///////////////////////////////////////////////////
 // Methods implementing nsIScriptSecurityManager //
 ///////////////////////////////////////////////////
 
 ///////////////// Security Checks /////////////////
 
 bool
--- a/caps/src/nsSecurityManagerFactory.cpp
+++ b/caps/src/nsSecurityManagerFactory.cpp
@@ -39,17 +39,17 @@ using namespace mozilla;
 nsSecurityNameSet::nsSecurityNameSet()
 {
 }
 
 nsSecurityNameSet::~nsSecurityNameSet()
 {
 }
 
-NS_IMPL_ISUPPORTS1(nsSecurityNameSet, nsIScriptExternalNameSet)
+NS_IMPL_ISUPPORTS(nsSecurityNameSet, nsIScriptExternalNameSet)
 
 static bool
 netscape_security_enablePrivilege(JSContext *cx, unsigned argc, JS::Value *vp)
 {
     Telemetry::Accumulate(Telemetry::ENABLE_PRIVILEGE_EVER_CALLED, true);
     return xpc::EnableUniversalXPConnect(cx);
 }
 
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -17,22 +17,22 @@
 #include "nsString.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIScriptSecurityManager.h"
 #include "pratom.h"
 
 NS_IMPL_CLASSINFO(nsSystemPrincipal, nullptr,
                   nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_SYSTEMPRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE2_CI(nsSystemPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(nsSystemPrincipal,
+                           nsIPrincipal,
+                           nsISerializable)
+NS_IMPL_CI_INTERFACE_GETTER(nsSystemPrincipal,
                             nsIPrincipal,
                             nsISerializable)
-NS_IMPL_CI_INTERFACE_GETTER2(nsSystemPrincipal,
-                             nsIPrincipal,
-                             nsISerializable)
 
 NS_IMETHODIMP_(MozExternalRefCountType)
 nsSystemPrincipal::AddRef()
 {
   NS_PRECONDITION(int32_t(refcount) >= 0, "illegal refcnt");
   nsrefcnt count = ++refcount;
   NS_LOG_ADDREF(this, count, "nsSystemPrincipal", sizeof(*this));
   return count;
--- a/chrome/src/nsChromeProtocolHandler.cpp
+++ b/chrome/src/nsChromeProtocolHandler.cpp
@@ -22,19 +22,19 @@
 #include "nsILoadGroup.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIStandardURL.h"
 #include "nsNetUtil.h"
 #include "nsString.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
-NS_IMPL_ISUPPORTS2(nsChromeProtocolHandler,
-                   nsIProtocolHandler,
-                   nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS(nsChromeProtocolHandler,
+                  nsIProtocolHandler,
+                  nsISupportsWeakReference)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIProtocolHandler methods:
 
 NS_IMETHODIMP
 nsChromeProtocolHandler::GetScheme(nsACString &result)
 {
     result.AssignLiteral("chrome");
--- a/client.mk
+++ b/client.mk
@@ -390,24 +390,24 @@ ifdef MOZ_PREFLIGHT
 	  $(MAKE) -f $(TOPSRCDIR)/$$mkfile preflight TOPSRCDIR=$(TOPSRCDIR) OBJDIR=$(OBJDIR) MOZ_OBJDIR=$(MOZ_OBJDIR); \
 	done
 endif
 
 ####################################
 # Build it
 
 realbuild::  $(OBJDIR)/Makefile $(OBJDIR)/config.status
-	$(MOZ_MAKE)
+	+$(MOZ_MAKE)
 
 ####################################
 # Other targets
 
 # Pass these target onto the real build system
 $(OBJDIR_TARGETS):: $(OBJDIR)/Makefile $(OBJDIR)/config.status
-	$(MOZ_MAKE) $@
+	+$(MOZ_MAKE) $@
 
 ####################################
 # Postflight
 
 realbuild postflight::
 ifdef MOZ_POSTFLIGHT
 	set -e; \
 	for mkfile in $(MOZ_POSTFLIGHT); do \
--- a/content/base/src/Attr.cpp
+++ b/content/base/src/Attr.cpp
@@ -99,18 +99,18 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(Attr)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 // QueryInterface implementation for Attr
 NS_INTERFACE_TABLE_HEAD(Attr)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_TABLE6(Attr, nsINode, nsIDOMAttr, nsIAttribute, nsIDOMNode,
-                      nsIDOMEventTarget, EventTarget)
+  NS_INTERFACE_TABLE(Attr, nsINode, nsIDOMAttr, nsIAttribute, nsIDOMNode,
+                     nsIDOMEventTarget, EventTarget)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(Attr)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
                                  new nsNodeSupportsWeakRefTearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
                                  new nsNode3Tearoff(this))
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Attr)
--- a/content/base/src/Comment.cpp
+++ b/content/base/src/Comment.cpp
@@ -17,18 +17,18 @@ using namespace dom;
 
 namespace mozilla {
 namespace dom {
 
 Comment::~Comment()
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED3(Comment, nsGenericDOMDataNode, nsIDOMNode,
-                             nsIDOMCharacterData, nsIDOMComment)
+NS_IMPL_ISUPPORTS_INHERITED(Comment, nsGenericDOMDataNode, nsIDOMNode,
+                            nsIDOMCharacterData, nsIDOMComment)
 
 bool
 Comment::IsNodeOfType(uint32_t aFlags) const
 {
   return !(aFlags & ~(eCONTENT | eCOMMENT | eDATA_NODE));
 }
 
 nsGenericDOMDataNode*
--- a/content/base/src/DOMQuad.cpp
+++ b/content/base/src/DOMQuad.cpp
@@ -136,17 +136,17 @@ public:
     *aY1 = y1;
     *aY2 = y2;
   }
 
 protected:
   nsRefPtr<DOMQuad> mQuad;
 };
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(DOMQuad::QuadBounds, DOMRectReadOnly, mQuad)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMQuad::QuadBounds, DOMRectReadOnly, mQuad)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMQuad::QuadBounds)
 NS_INTERFACE_MAP_END_INHERITING(DOMRectReadOnly)
 
 NS_IMPL_ADDREF_INHERITED(DOMQuad::QuadBounds, DOMRectReadOnly)
 NS_IMPL_RELEASE_INHERITED(DOMQuad::QuadBounds, DOMRectReadOnly)
 
 DOMRectReadOnly*
--- a/content/base/src/DOMRect.cpp
+++ b/content/base/src/DOMRect.cpp
@@ -24,17 +24,17 @@ JSObject*
 DOMRectReadOnly::WrapObject(JSContext* aCx)
 {
   MOZ_ASSERT(mParent);
   return DOMRectReadOnlyBinding::Wrap(aCx, this);
 }
 
 // -----------------------------------------------------------------------------
 
-NS_IMPL_ISUPPORTS_INHERITED1(DOMRect, DOMRectReadOnly, nsIDOMClientRect)
+NS_IMPL_ISUPPORTS_INHERITED(DOMRect, DOMRectReadOnly, nsIDOMClientRect)
 
 #define FORWARD_GETTER(_name)                                                   \
   NS_IMETHODIMP                                                                 \
   DOMRect::Get ## _name(float* aResult)                                         \
   {                                                                             \
     *aResult = float(_name());                                                  \
     return NS_OK;                                                               \
   }
@@ -71,17 +71,17 @@ DOMRect::Constructor(const GlobalObject&
 }
 
 // -----------------------------------------------------------------------------
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(DOMRectList, mParent, mArray)
 
 NS_INTERFACE_TABLE_HEAD(DOMRectList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_TABLE1(DOMRectList, nsIDOMClientRectList)
+  NS_INTERFACE_TABLE(DOMRectList, nsIDOMClientRectList)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DOMRectList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMRectList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMRectList)
 
 
 NS_IMETHODIMP
--- a/content/base/src/DocumentType.cpp
+++ b/content/base/src/DocumentType.cpp
@@ -77,18 +77,18 @@ DocumentType::DocumentType(already_AddRe
   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
                     "Bad NodeType in aNodeInfo");
 }
 
 DocumentType::~DocumentType()
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED2(DocumentType, nsGenericDOMDataNode, nsIDOMNode,
-                             nsIDOMDocumentType)
+NS_IMPL_ISUPPORTS_INHERITED(DocumentType, nsGenericDOMDataNode, nsIDOMNode,
+                            nsIDOMDocumentType)
 
 bool
 DocumentType::IsNodeOfType(uint32_t aFlags) const
 {
   // Don't claim to be eDATA_NODE since we're just inheriting
   // nsGenericDOMDataNode for convinience. Doctypes aren't really
   // data nodes (they have a null .nodeValue and don't implement
   // nsIDOMCharacterData)
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -516,17 +516,17 @@ public:
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<EventSource> mEventSource;
 };
 
-NS_IMPL_CYCLE_COLLECTION_1(AsyncVerifyRedirectCallbackFwr, mEventSource)
+NS_IMPL_CYCLE_COLLECTION(AsyncVerifyRedirectCallbackFwr, mEventSource)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AsyncVerifyRedirectCallbackFwr)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(AsyncVerifyRedirectCallbackFwr)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(AsyncVerifyRedirectCallbackFwr)
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -370,17 +370,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
 // CanSkipThis returns false to avoid problems with incomplete unlinking.
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsChildContentList)
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 NS_INTERFACE_TABLE_HEAD(nsChildContentList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_TABLE2(nsChildContentList, nsINodeList, nsIDOMNodeList)
+  NS_INTERFACE_TABLE(nsChildContentList, nsINodeList, nsIDOMNodeList)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsChildContentList)
 NS_INTERFACE_MAP_END
 
 JSObject*
 nsChildContentList::WrapObject(JSContext *cx)
 {
   return NodeListBinding::Wrap(cx, this);
 }
@@ -423,17 +423,17 @@ nsChildContentList::IndexOf(nsIContent* 
     return mNode->IndexOf(aContent);
   }
 
   return -1;
 }
 
 //----------------------------------------------------------------------
 
-NS_IMPL_CYCLE_COLLECTION_1(nsNode3Tearoff, mNode)
+NS_IMPL_CYCLE_COLLECTION(nsNode3Tearoff, mNode)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNode3Tearoff)
   NS_INTERFACE_MAP_ENTRY(nsIDOMXPathNSResolver)
 NS_INTERFACE_MAP_END_AGGREGATED(mNode)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNode3Tearoff)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNode3Tearoff)
 
@@ -458,18 +458,18 @@ FragmentOrElement::Children()
 
   return slots->mChildrenList;
 }
 
 
 //----------------------------------------------------------------------
 
 
-NS_IMPL_ISUPPORTS1(nsNodeWeakReference,
-                   nsIWeakReference)
+NS_IMPL_ISUPPORTS(nsNodeWeakReference,
+                  nsIWeakReference)
 
 nsNodeWeakReference::~nsNodeWeakReference()
 {
   if (mNode) {
     NS_ASSERTION(mNode->Slots()->mWeakReference == this,
                  "Weak reference has wrong value");
     mNode->Slots()->mWeakReference = nullptr;
   }
@@ -478,17 +478,17 @@ nsNodeWeakReference::~nsNodeWeakReferenc
 NS_IMETHODIMP
 nsNodeWeakReference::QueryReferent(const nsIID& aIID, void** aInstancePtr)
 {
   return mNode ? mNode->QueryInterface(aIID, aInstancePtr) :
                  NS_ERROR_NULL_POINTER;
 }
 
 
-NS_IMPL_CYCLE_COLLECTION_1(nsNodeSupportsWeakRefTearoff, mNode)
+NS_IMPL_CYCLE_COLLECTION(nsNodeSupportsWeakRefTearoff, mNode)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsNodeSupportsWeakRefTearoff)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END_AGGREGATED(mNode)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeSupportsWeakRefTearoff)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsNodeSupportsWeakRefTearoff)
 
--- a/content/base/src/ShadowRoot.cpp
+++ b/content/base/src/ShadowRoot.cpp
@@ -650,18 +650,18 @@ ShadowRoot::ContentRemoved(nsIDocument* 
 
   // Watch for node that is removed from the pool because
   // it may need to be removed from an insertion point.
   if (IsPooledNode(aChild, aContainer, mPoolHost)) {
     RemoveDistributedNode(aChild);
   }
 }
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ShadowRootStyleSheetList, StyleSheetList,
-                                     mShadowRoot)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList, StyleSheetList,
+                                   mShadowRoot)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList)
 NS_INTERFACE_MAP_END_INHERITING(StyleSheetList)
 
 NS_IMPL_ADDREF_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
 NS_IMPL_RELEASE_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
 
 ShadowRootStyleSheetList::ShadowRootStyleSheetList(ShadowRoot* aShadowRoot)
--- a/content/base/src/ThirdPartyUtil.cpp
+++ b/content/base/src/ThirdPartyUtil.cpp
@@ -7,17 +7,17 @@
 #include "nsIServiceManager.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsIDOMWindow.h"
 #include "nsILoadContext.h"
 #include "nsIPrincipal.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsThreadUtils.h"
 
-NS_IMPL_ISUPPORTS1(ThirdPartyUtil, mozIThirdPartyUtil)
+NS_IMPL_ISUPPORTS(ThirdPartyUtil, mozIThirdPartyUtil)
 
 nsresult
 ThirdPartyUtil::Init()
 {
   NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_AVAILABLE);
 
   nsresult rv;
   mTLDService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv);
--- a/content/base/src/TreeWalker.cpp
+++ b/content/base/src/TreeWalker.cpp
@@ -36,17 +36,17 @@ TreeWalker::~TreeWalker()
 {
     /* destructor code */
 }
 
 /*
  * nsISupports and cycle collection stuff
  */
 
-NS_IMPL_CYCLE_COLLECTION_3(TreeWalker, mFilter, mCurrentNode, mRoot)
+NS_IMPL_CYCLE_COLLECTION(TreeWalker, mFilter, mCurrentNode, mRoot)
 
 // QueryInterface implementation for TreeWalker
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TreeWalker)
     NS_INTERFACE_MAP_ENTRY(nsIDOMTreeWalker)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMTreeWalker)
 NS_INTERFACE_MAP_END
 
 // Have to pass in dom::TreeWalker because a11y has an a11y::TreeWalker that
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -36,17 +36,17 @@ using namespace mozilla;
 using namespace mozilla::dom;
 
 static bool sInited = 0;
 uint32_t nsCCUncollectableMarker::sGeneration = 0;
 #ifdef MOZ_XUL
 #include "nsXULPrototypeCache.h"
 #endif
 
-NS_IMPL_ISUPPORTS1(nsCCUncollectableMarker, nsIObserver)
+NS_IMPL_ISUPPORTS(nsCCUncollectableMarker, nsIObserver)
 
 /* static */
 nsresult
 nsCCUncollectableMarker::Init()
 {
   if (sInited) {
     return NS_OK;
   }
--- a/content/base/src/nsCSPService.cpp
+++ b/content/base/src/nsCSPService.cpp
@@ -43,17 +43,17 @@ CSPService::CSPService()
 #endif
 }
 
 CSPService::~CSPService()
 {
   mAppStatusCache.Clear();
 }
 
-NS_IMPL_ISUPPORTS2(CSPService, nsIContentPolicy, nsIChannelEventSink)
+NS_IMPL_ISUPPORTS(CSPService, nsIContentPolicy, nsIChannelEventSink)
 
 /* nsIContentPolicy implementation */
 NS_IMETHODIMP
 CSPService::ShouldLoad(uint32_t aContentType,
                        nsIURI *aContentLocation,
                        nsIURI *aRequestOrigin,
                        nsISupports *aRequestContext,
                        const nsACString &aMimeTypeGuess,
--- a/content/base/src/nsChannelPolicy.cpp
+++ b/content/base/src/nsChannelPolicy.cpp
@@ -9,17 +9,17 @@ nsChannelPolicy::nsChannelPolicy()
   : mLoadType(0)
 {
 }
 
 nsChannelPolicy::~nsChannelPolicy()
 {
 }
 
-NS_IMPL_ISUPPORTS1(nsChannelPolicy, nsIChannelPolicy)
+NS_IMPL_ISUPPORTS(nsChannelPolicy, nsIChannelPolicy)
 
 NS_IMETHODIMP
 nsChannelPolicy::GetLoadType(uint32_t *aLoadType)
 {
     *aLoadType = mLoadType;
     return NS_OK;
 }
 
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -122,17 +122,17 @@ nsContentAreaDragDrop::GetDragData(nsPID
   *aCanDrag = true;
 
   DragDataProducer
     provider(aWindow, aTarget, aSelectionTargetNode, aIsAltKeyPressed);
   return provider.Produce(aDataTransfer, aCanDrag, aSelection, aDragNode);
 }
 
 
-NS_IMPL_ISUPPORTS1(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
+NS_IMPL_ISUPPORTS(nsContentAreaDragDropDataProvider, nsIFlavorDataProvider)
 
 // SaveURIToFile
 // used on platforms where it's possible to drag items (e.g. images)
 // into the file system
 nsresult
 nsContentAreaDragDropDataProvider::SaveURIToFile(nsAString& inSourceURIString,
                                                  nsIFile* inDestFile,
                                                  bool isPrivate)
--- a/content/base/src/nsContentIterator.cpp
+++ b/content/base/src/nsContentIterator.cpp
@@ -206,21 +206,21 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LA
                                                    LastRelease())
 
 NS_INTERFACE_MAP_BEGIN(nsContentIterator)
   NS_INTERFACE_MAP_ENTRY(nsIContentIterator)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentIterator)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsContentIterator)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_4(nsContentIterator,
-                           mCurNode,
-                           mFirst,
-                           mLast,
-                           mCommonParent)
+NS_IMPL_CYCLE_COLLECTION(nsContentIterator,
+                         mCurNode,
+                         mFirst,
+                         mLast,
+                         mCommonParent)
 
 void
 nsContentIterator::LastRelease()
 {
   mCurNode = nullptr;
   mFirst = nullptr;
   mLast = nullptr;
   mCommonParent = nullptr;
@@ -1153,18 +1153,18 @@ protected:
 };
 
 NS_IMPL_ADDREF_INHERITED(nsContentSubtreeIterator, nsContentIterator)
 NS_IMPL_RELEASE_INHERITED(nsContentSubtreeIterator, nsContentIterator)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsContentSubtreeIterator)
 NS_INTERFACE_MAP_END_INHERITING(nsContentIterator)
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(nsContentSubtreeIterator, nsContentIterator,
-                                     mRange)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(nsContentSubtreeIterator, nsContentIterator,
+                                   mRange)
 
 void
 nsContentSubtreeIterator::LastRelease()
 {
   mRange = nullptr;
   nsContentIterator::LastRelease();
 }
 
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -80,17 +80,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_E
 
 #define NS_CONTENT_LIST_INTERFACES(_class)                                    \
     NS_INTERFACE_TABLE_ENTRY(_class, nsINodeList)                             \
     NS_INTERFACE_TABLE_ENTRY(_class, nsIDOMNodeList)
 
 // QueryInterface implementation for nsBaseContentList
 NS_INTERFACE_TABLE_HEAD(nsBaseContentList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_TABLE2(nsBaseContentList, nsINodeList, nsIDOMNodeList)
+  NS_INTERFACE_TABLE(nsBaseContentList, nsINodeList, nsIDOMNodeList)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsBaseContentList)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBaseContentList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBaseContentList)
 
 
@@ -130,18 +130,18 @@ nsBaseContentList::IndexOf(nsIContent *a
 }
 
 int32_t
 nsBaseContentList::IndexOf(nsIContent* aContent)
 {
   return IndexOf(aContent, true);
 }
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_1(nsSimpleContentList, nsBaseContentList,
-                                     mRoot)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(nsSimpleContentList, nsBaseContentList,
+                                   mRoot)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsSimpleContentList)
 NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList)
 
 
 NS_IMPL_ADDREF_INHERITED(nsSimpleContentList, nsBaseContentList)
 NS_IMPL_RELEASE_INHERITED(nsSimpleContentList, nsBaseContentList)
 
@@ -488,19 +488,19 @@ nsContentList::~nsContentList()
 }
 
 JSObject*
 nsContentList::WrapObject(JSContext *cx)
 {
   return HTMLCollectionBinding::Wrap(cx, this);
 }
 
-NS_IMPL_ISUPPORTS_INHERITED3(nsContentList, nsBaseContentList,
-                             nsIHTMLCollection, nsIDOMHTMLCollection,
-                             nsIMutationObserver)
+NS_IMPL_ISUPPORTS_INHERITED(nsContentList, nsBaseContentList,
+                            nsIHTMLCollection, nsIDOMHTMLCollection,
+                            nsIMutationObserver)
 
 uint32_t
 nsContentList::Length(bool aDoFlush)
 {
   BringSelfUpToDate(aDoFlush);
     
   return mElements.Length();
 }
--- a/content/base/src/nsContentPolicy.cpp
+++ b/content/base/src/nsContentPolicy.cpp
@@ -15,17 +15,17 @@
 #include "nsContentPolicyUtils.h"
 #include "nsContentPolicy.h"
 #include "nsIURI.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMWindow.h"
 #include "nsIContent.h"
 #include "nsCOMArray.h"
 
-NS_IMPL_ISUPPORTS1(nsContentPolicy, nsIContentPolicy)
+NS_IMPL_ISUPPORTS(nsContentPolicy, nsIContentPolicy)
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gConPolLog;
 #endif
 
 nsresult
 NS_NewContentPolicy(nsIContentPolicy **aResult)
 {
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -273,17 +273,17 @@ public:
 
     return MOZ_COLLECT_REPORT(
       "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
       amount,
       "Memory used by the event listener manager's hash table.");
   }
 };
 
-NS_IMPL_ISUPPORTS1(DOMEventListenerManagersHashReporter, nsIMemoryReporter)
+NS_IMPL_ISUPPORTS(DOMEventListenerManagersHashReporter, nsIMemoryReporter)
 
 class EventListenerManagerMapEntry : public PLDHashEntryHdr
 {
 public:
   EventListenerManagerMapEntry(const void *aKey)
     : mKey(aKey)
   {
   }
@@ -5385,19 +5385,19 @@ nsContentUtils::CheckSameOrigin(nsIChann
   nsresult rv = oldPrincipal->CheckMayLoad(newURI, false, false);
   if (NS_SUCCEEDED(rv) && newOriginalURI != newURI) {
     rv = oldPrincipal->CheckMayLoad(newOriginalURI, false, false);
   }
 
   return rv;
 }
 
-NS_IMPL_ISUPPORTS2(SameOriginChecker,
-                   nsIChannelEventSink,
-                   nsIInterfaceRequestor)
+NS_IMPL_ISUPPORTS(SameOriginChecker,
+                  nsIChannelEventSink,
+                  nsIInterfaceRequestor)
 
 NS_IMETHODIMP
 SameOriginChecker::AsyncOnChannelRedirect(nsIChannel *aOldChannel,
                                           nsIChannel *aNewChannel,
                                           uint32_t aFlags,
                                           nsIAsyncVerifyRedirectCallback *cb)
 {
   NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -392,19 +392,19 @@ nsPreflightCache::GetCacheKey(nsIURI* aU
                  spec);
 
   return true;
 }
 
 //////////////////////////////////////////////////////////////////////////
 // nsCORSListenerProxy
 
-NS_IMPL_ISUPPORTS5(nsCORSListenerProxy, nsIStreamListener,
-                   nsIRequestObserver, nsIChannelEventSink,
-                   nsIInterfaceRequestor, nsIAsyncVerifyRedirectCallback)
+NS_IMPL_ISUPPORTS(nsCORSListenerProxy, nsIStreamListener,
+                  nsIRequestObserver, nsIChannelEventSink,
+                  nsIInterfaceRequestor, nsIAsyncVerifyRedirectCallback)
 
 /* static */
 void
 nsCORSListenerProxy::Startup()
 {
   Preferences::AddBoolVarCache(&gDisableCORS,
                                "content.cors.disable");
   Preferences::AddBoolVarCache(&gDisableCORSPrivateData,
@@ -926,19 +926,19 @@ private:
   nsCOMPtr<nsIChannel> mOuterChannel;
   nsCOMPtr<nsIStreamListener> mOuterListener;
   nsCOMPtr<nsISupports> mOuterContext;
   nsCOMPtr<nsIPrincipal> mReferrerPrincipal;
   nsCString mRequestMethod;
   bool mWithCredentials;
 };
 
-NS_IMPL_ISUPPORTS4(nsCORSPreflightListener, nsIStreamListener,
-                   nsIRequestObserver, nsIInterfaceRequestor,
-                   nsIChannelEventSink)
+NS_IMPL_ISUPPORTS(nsCORSPreflightListener, nsIStreamListener,
+                  nsIRequestObserver, nsIInterfaceRequestor,
+                  nsIChannelEventSink)
 
 void
 nsCORSPreflightListener::AddResultToCache(nsIRequest *aRequest)
 {
   nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aRequest);
   NS_ASSERTION(http, "Request was not http");
 
   // The "Access-Control-Max-Age" header should return an age in seconds.
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -109,17 +109,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDOMAttributeMap)
   return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 // QueryInterface implementation for nsDOMAttributeMap
 NS_INTERFACE_TABLE_HEAD(nsDOMAttributeMap)
-  NS_INTERFACE_TABLE1(nsDOMAttributeMap, nsIDOMMozNamedAttrMap)
+  NS_INTERFACE_TABLE(nsDOMAttributeMap, nsIDOMMozNamedAttrMap)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMAttributeMap)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMAttributeMap)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMAttributeMap)
 
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -16,18 +16,18 @@
 #include "nsContentUtils.h"
 #include "nsIScriptError.h"
 #include "nsIXPConnect.h"
 #include <algorithm>
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsDOMMultipartFile, nsDOMFile,
-                             nsIJSNativeInitializer)
+NS_IMPL_ISUPPORTS_INHERITED(nsDOMMultipartFile, nsDOMFile,
+                            nsIJSNativeInitializer)
 
 NS_IMETHODIMP
 nsDOMMultipartFile::GetSize(uint64_t* aLength)
 {
   if (mLength == UINT64_MAX) {
     CheckedUint64 length = 0;
   
     uint32_t i;
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -705,17 +705,17 @@ public:
         aClosure);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     return NS_OK;
   }
 };
 
-NS_IMPL_ISUPPORTS1(nsDOMMemoryFileDataOwnerMemoryReporter, nsIMemoryReporter)
+NS_IMPL_ISUPPORTS(nsDOMMemoryFileDataOwnerMemoryReporter, nsIMemoryReporter)
 
 /* static */ void
 nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered()
 {
   sDataOwnerMutex.AssertCurrentThreadOwns();
   if (sMemoryReporterRegistered) {
     return;
   }
--- a/content/base/src/nsDataDocumentContentPolicy.cpp
+++ b/content/base/src/nsDataDocumentContentPolicy.cpp
@@ -11,17 +11,17 @@
 
 #include "nsDataDocumentContentPolicy.h"
 #include "nsNetUtil.h"
 #include "nsScriptSecurityManager.h"
 #include "nsIDocument.h"
 #include "nsINode.h"
 #include "nsIDOMWindow.h"
 
-NS_IMPL_ISUPPORTS1(nsDataDocumentContentPolicy, nsIContentPolicy)
+NS_IMPL_ISUPPORTS(nsDataDocumentContentPolicy, nsIContentPolicy)
 
 // Helper method for ShouldLoad()
 // Checks a URI for the given flags.  Returns true if the URI has the flags,
 // and false if not (or if we weren't able to tell).
 static bool
 HasFlags(nsIURI* aURI, uint32_t aURIFlags)
 {
   bool hasFlags;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -718,19 +718,19 @@ nsDOMStyleSheetList::nsDOMStyleSheetList
 
 nsDOMStyleSheetList::~nsDOMStyleSheetList()
 {
   if (mDocument) {
     mDocument->RemoveObserver(this);
   }
 }
 
-NS_IMPL_ISUPPORTS_INHERITED2(nsDOMStyleSheetList, StyleSheetList,
-                             nsIDocumentObserver,
-                             nsIMutationObserver)
+NS_IMPL_ISUPPORTS_INHERITED(nsDOMStyleSheetList, StyleSheetList,
+                            nsIDocumentObserver,
+                            nsIMutationObserver)
 
 uint32_t
 nsDOMStyleSheetList::Length()
 {
   if (!mDocument) {
     return 0;
   }
 
@@ -795,17 +795,17 @@ nsDOMStyleSheetList::StyleSheetRemoved(n
     nsCOMPtr<nsIDOMStyleSheet> domss(do_QueryInterface(aStyleSheet));
     if (domss) {
       mLength--;
     }
   }
 }
 
 // nsOnloadBlocker implementation
-NS_IMPL_ISUPPORTS1(nsOnloadBlocker, nsIRequest)
+NS_IMPL_ISUPPORTS(nsOnloadBlocker, nsIRequest)
 
 NS_IMETHODIMP
 nsOnloadBlocker::GetName(nsACString &aResult)
 {
   aResult.AssignLiteral("about:document-onload-blocker");
   return NS_OK;
 }
 
@@ -1115,19 +1115,19 @@ nsExternalResourceMap::AddExternalResour
   const nsTArray< nsCOMPtr<nsIObserver> > & obs = load->Observers();
   for (uint32_t i = 0; i < obs.Length(); ++i) {
     obs[i]->Observe(doc, "external-resource-document-created", nullptr);
   }
 
   return rv;
 }
 
-NS_IMPL_ISUPPORTS2(nsExternalResourceMap::PendingLoad,
-                   nsIStreamListener,
-                   nsIRequestObserver)
+NS_IMPL_ISUPPORTS(nsExternalResourceMap::PendingLoad,
+                  nsIStreamListener,
+                  nsIRequestObserver)
 
 NS_IMETHODIMP
 nsExternalResourceMap::PendingLoad::OnStartRequest(nsIRequest *aRequest,
                                                    nsISupports *aContext)
 {
   nsExternalResourceMap& map = mDisplayDocument->ExternalResourceMap();
   if (map.HaveShutDown()) {
     return NS_BINDING_ABORTED;
@@ -1312,21 +1312,21 @@ nsExternalResourceMap::PendingLoad::Star
   rv = NS_NewChannel(getter_AddRefs(channel), aURI, nullptr, loadGroup, req);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mURI = aURI;
 
   return channel->AsyncOpen(this, nullptr);
 }
 
-NS_IMPL_ISUPPORTS1(nsExternalResourceMap::LoadgroupCallbacks,
-                   nsIInterfaceRequestor)
+NS_IMPL_ISUPPORTS(nsExternalResourceMap::LoadgroupCallbacks,
+                  nsIInterfaceRequestor)
 
 #define IMPL_SHIM(_i) \
-  NS_IMPL_ISUPPORTS1(nsExternalResourceMap::LoadgroupCallbacks::_i##Shim, _i)
+  NS_IMPL_ISUPPORTS(nsExternalResourceMap::LoadgroupCallbacks::_i##Shim, _i)
 
 IMPL_SHIM(nsILoadContext)
 IMPL_SHIM(nsIProgressEventSink)
 IMPL_SHIM(nsIChannelEventSink)
 IMPL_SHIM(nsISecurityEventSink)
 IMPL_SHIM(nsIApplicationCacheContainer)
 
 #undef IMPL_SHIM
@@ -5560,17 +5560,17 @@ class ProcessStackRunner MOZ_FINAL : pub
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
     nsDocument::ProcessTopElementQueue(mIsBaseQueue);
     return NS_OK;
   }
   bool mIsBaseQueue;
 };
 
-NS_IMPL_ISUPPORTS1(ProcessStackRunner, nsIRunnable);
+NS_IMPL_ISUPPORTS(ProcessStackRunner, nsIRunnable);
 
 } // anonymous namespace
 
 void
 nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
                                      Element* aCustomElement,
                                      LifecycleCallbackArgs* aArgs,
                                      CustomElementDefinition* aDefinition)
@@ -5845,17 +5845,17 @@ nsDocument::RegisterElement(JSContext* a
     const js::Class* clasp = js::GetObjectClass(protoObject);
     if (IsDOMIfaceAndProtoClass(clasp)) {
       rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return nullptr;
     }
 
     JS::Rooted<JSPropertyDescriptor> descRoot(aCx);
     JS::MutableHandle<JSPropertyDescriptor> desc(&descRoot);
-    if(!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", 0, desc)) {
+    if (!JS_GetPropertyDescriptor(aCx, protoObject, "constructor", desc)) {
       rv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
 
     // Check if non-configurable
     if (desc.isPermanent()) {
       rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
       return nullptr;
@@ -9321,17 +9321,17 @@ class StubCSSLoaderObserver MOZ_FINAL : 
 public:
   NS_IMETHOD
   StyleSheetLoaded(nsCSSStyleSheet*, bool, nsresult)
   {
     return NS_OK;
   }
   NS_DECL_ISUPPORTS
 };
-NS_IMPL_ISUPPORTS1(StubCSSLoaderObserver, nsICSSLoaderObserver)
+NS_IMPL_ISUPPORTS(StubCSSLoaderObserver, nsICSSLoaderObserver)
 
 }
 
 void
 nsDocument::PreloadStyle(nsIURI* uri, const nsAString& charset,
                          const nsAString& aCrossOriginAttr)
 {
   // The CSSLoader will retain this object after we return.
@@ -11432,19 +11432,19 @@ public:
     }
   }
 
   nsWeakPtr mElement;
   nsWeakPtr mDocument;
   bool mUserInputOrChromeCaller;
 };
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsPointerLockPermissionRequest,
-                             nsRunnable,
-                             nsIContentPermissionRequest)
+NS_IMPL_ISUPPORTS_INHERITED(nsPointerLockPermissionRequest,
+                            nsRunnable,
+                            nsIContentPermissionRequest)
 
 NS_IMETHODIMP
 nsPointerLockPermissionRequest::GetTypes(nsIArray** aTypes)
 {
   nsTArray<nsString> emptyOptions;
   return CreatePermissionArray(NS_LITERAL_CSTRING("pointerLock"),
                                NS_LITERAL_CSTRING("unused"),
                                emptyOptions,
--- a/content/base/src/nsDocumentEncoder.cpp
+++ b/content/base/src/nsDocumentEncoder.cpp
@@ -177,18 +177,18 @@ protected:
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDocumentEncoder)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDocumentEncoder)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDocumentEncoder)
    NS_INTERFACE_MAP_ENTRY(nsIDocumentEncoder)
    NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_5(nsDocumentEncoder,
-                           mDocument, mSelection, mRange, mNode, mCommonParent)
+NS_IMPL_CYCLE_COLLECTION(nsDocumentEncoder,
+                         mDocument, mSelection, mRange, mNode, mCommonParent)
 
 nsDocumentEncoder::nsDocumentEncoder() : mCachedBuffer(nullptr)
 {
   Initialize();
   mMimeType.AssignLiteral("text/plain");
 }
 
 void nsDocumentEncoder::Initialize(bool aClearCachedSerializer)
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -117,17 +117,17 @@ public:
     if (base_win) {
       base_win->Destroy();
     }
     return NS_OK;
   }
   nsRefPtr<nsIDocShell> mDocShell;
 };
 
-NS_IMPL_ISUPPORTS1(nsContentView, nsIContentView)
+NS_IMPL_ISUPPORTS(nsContentView, nsIContentView)
 
 nsresult
 nsContentView::Update(const ViewConfig& aConfig)
 {
   if (aConfig == mConfig) {
     return NS_OK;
   }
   mConfig = aConfig;
@@ -245,17 +245,17 @@ nsContentView::GetId(nsContentViewId* aI
 // does not count chrome frames when determining depth, nor does it
 // prevent chrome recursion.  Number is fairly arbitrary, but meant to
 // keep number of shells to a reasonable number on accidental recursion with a
 // small (but not 1) branching factor.  With large branching factors the number
 // of shells can rapidly become huge and run us out of memory.  To solve that,
 // we'd need to re-institute a fixed version of bug 98158.
 #define MAX_DEPTH_CONTENT_FRAMES 10
 
-NS_IMPL_CYCLE_COLLECTION_3(nsFrameLoader, mDocShell, mMessageManager, mChildMessageManager)
+NS_IMPL_CYCLE_COLLECTION(nsFrameLoader, mDocShell, mMessageManager, mChildMessageManager)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
   NS_INTERFACE_MAP_ENTRY(nsIContentViewManager)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFrameLoader)
 NS_INTERFACE_MAP_END
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -1205,17 +1205,17 @@ public:
   NS_DECL_NSIMEMORYREPORTER
 
   static const size_t kSuspectReferentCount = 300;
 protected:
   void CountReferents(nsFrameMessageManager* aMessageManager,
                       MessageManagerReferentCount* aReferentCount);
 };
 
-NS_IMPL_ISUPPORTS1(MessageManagerReporter, nsIMemoryReporter)
+NS_IMPL_ISUPPORTS(MessageManagerReporter, nsIMemoryReporter)
 
 static PLDHashOperator
 CollectMessageListenerData(const nsAString& aKey,
                            nsAutoTObserverArray<nsMessageListenerInfo, 1>* aListeners,
                            void* aData)
 {
   MessageManagerReferentCount* referentCount =
     static_cast<MessageManagerReferentCount*>(aData);
@@ -1606,17 +1606,17 @@ nsFrameScriptExecutor::InitTabChildGloba
   // Set the location information for the new global, so that tools like
   // about:memory may use that information.
   xpc::SetLocationForGlobal(global, aID);
 
   DidCreateGlobal();
   return true;
 }
 
-NS_IMPL_ISUPPORTS1(nsScriptCacheCleaner, nsIObserver)
+NS_IMPL_ISUPPORTS(nsScriptCacheCleaner, nsIObserver)
 
 nsFrameMessageManager* nsFrameMessageManager::sChildProcessManager = nullptr;
 nsFrameMessageManager* nsFrameMessageManager::sParentProcessManager = nullptr;
 nsFrameMessageManager* nsFrameMessageManager::sSameProcessParentManager = nullptr;
 nsTArray<nsCOMPtr<nsIRunnable> >* nsFrameMessageManager::sPendingSameProcessAsyncMessages = nullptr;
 
 class nsAsyncMessageToSameProcessChild : public nsSameProcessAsyncMessageBase,
                                          public nsRunnable
--- a/content/base/src/nsGenConImageContent.cpp
+++ b/content/base/src/nsGenConImageContent.cpp
@@ -58,21 +58,21 @@ public:
   
 private:
   virtual ~nsGenConImageContent();
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
 };
 
-NS_IMPL_ISUPPORTS_INHERITED3(nsGenConImageContent,
-                             nsXMLElement,
-                             nsIImageLoadingContent,
-                             imgINotificationObserver,
-                             imgIOnloadBlocker)
+NS_IMPL_ISUPPORTS_INHERITED(nsGenConImageContent,
+                            nsXMLElement,
+                            nsIImageLoadingContent,
+                            imgINotificationObserver,
+                            imgIOnloadBlocker)
 
 nsresult
 NS_NewGenConImageContent(nsIContent** aResult, already_AddRefed<nsINodeInfo>&& aNodeInfo,
                          imgRequestProxy* aImageRequest)
 {
   NS_PRECONDITION(aImageRequest, "Must have request!");
   nsGenConImageContent *it = new nsGenConImageContent(aNodeInfo);
   if (!it)
--- a/content/base/src/nsHostObjectProtocolHandler.cpp
+++ b/content/base/src/nsHostObjectProtocolHandler.cpp
@@ -42,17 +42,17 @@ class HostObjectURLsReporter MOZ_FINAL :
     return MOZ_COLLECT_REPORT(
       "host-object-urls", KIND_OTHER, UNITS_COUNT,
       gDataTable ? gDataTable->Count() : 0,
       "The number of host objects stored for access via URLs "
       "(e.g. blobs passed to URL.createObjectURL).");
   }
 };
 
-NS_IMPL_ISUPPORTS1(HostObjectURLsReporter, nsIMemoryReporter)
+NS_IMPL_ISUPPORTS(HostObjectURLsReporter, nsIMemoryReporter)
 
 class BlobURLsReporter MOZ_FINAL : public nsIMemoryReporter
 {
  public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD CollectReports(nsIHandleReportCallback* aCallback,
                             nsISupports* aData)
@@ -245,17 +245,17 @@ class BlobURLsReporter MOZ_FINAL : publi
             descString,
             envp->mData);
       }
     }
     return PL_DHASH_NEXT;
   }
 };
 
-NS_IMPL_ISUPPORTS1(BlobURLsReporter, nsIMemoryReporter)
+NS_IMPL_ISUPPORTS(BlobURLsReporter, nsIMemoryReporter)
 
 }
 
 void
 nsHostObjectProtocolHandler::Init(void)
 {
   static bool initialized = false;
 
@@ -402,17 +402,17 @@ GetDataObject(nsIURI* aURI)
 
   DataInfo* info = GetDataInfo(spec);
   return info ? info->mObject : nullptr;
 }
 
 // -----------------------------------------------------------------------
 // Protocol handler
 
-NS_IMPL_ISUPPORTS1(nsHostObjectProtocolHandler, nsIProtocolHandler)
+NS_IMPL_ISUPPORTS(nsHostObjectProtocolHandler, nsIProtocolHandler)
 
 NS_IMETHODIMP
 nsHostObjectProtocolHandler::GetDefaultPort(int32_t *result)
 {
   *result = -1;
   return NS_OK;
 }
 
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -138,20 +138,20 @@ nsInProcessTabChildGlobal::Init()
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                    "Couldn't initialize nsInProcessTabChildGlobal");
   mMessageManager = new nsFrameMessageManager(this,
                                               nullptr,
                                               dom::ipc::MM_CHILD);
   return NS_OK;
 }
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED_2(nsInProcessTabChildGlobal,
-                                     DOMEventTargetHelper,
-                                     mMessageManager,
-                                     mGlobal)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal,
+                                   DOMEventTargetHelper,
+                                   mMessageManager,
+                                   mGlobal)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsInProcessTabChildGlobal)
   NS_INTERFACE_MAP_ENTRY(nsIMessageListenerManager)
   NS_INTERFACE_MAP_ENTRY(nsIMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsISyncMessageSender)
   NS_INTERFACE_MAP_ENTRY(nsIContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIInProcessContentFrameMessageManager)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
--- a/content/base/src/nsMappedAttributes.cpp
+++ b/content/base/src/nsMappedAttributes.cpp
@@ -69,18 +69,18 @@ void* nsMappedAttributes::operator new(s
 
 #ifdef DEBUG
   static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
 #endif
 
   return newAttrs;
 }
 
-NS_IMPL_ISUPPORTS1(nsMappedAttributes,
-                   nsIStyleRule)
+NS_IMPL_ISUPPORTS(nsMappedAttributes,
+                  nsIStyleRule)
 
 void
 nsMappedAttributes::SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue)
 {
   NS_PRECONDITION(aAttrName, "null name");
 
   uint32_t i;
   for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) {
--- a/content/base/src/nsMixedContentBlocker.cpp
+++ b/content/base/src/nsMixedContentBlocker.cpp
@@ -145,17 +145,17 @@ nsMixedContentBlocker::nsMixedContentBlo
   Preferences::AddBoolVarCache(&sBlockMixedDisplay,
                                "security.mixed_content.block_display_content");
 }
 
 nsMixedContentBlocker::~nsMixedContentBlocker()
 {
 }
 
-NS_IMPL_ISUPPORTS1(nsMixedContentBlocker, nsIContentPolicy)
+NS_IMPL_ISUPPORTS(nsMixedContentBlocker, nsIContentPolicy)
 
 static void
 LogMixedContentMessage(MixedContentTypes aClassification,
                        nsIURI* aContentLocation,
                        nsIDocument* aRootDoc,
                        nsMixedContentBlockerMessageType aMessageType)
 {
   nsAutoCString messageCategory;
--- a/content/base/src/nsNoDataProtocolContentPolicy.cpp
+++ b/content/base/src/nsNoDataProtocolContentPolicy.cpp
@@ -12,17 +12,17 @@
 #include "nsNoDataProtocolContentPolicy.h"
 #include "nsIDOMWindow.h"
 #include "nsString.h"
 #include "nsIProtocolHandler.h"
 #include "nsIIOService.h"
 #include "nsIExternalProtocolHandler.h"
 #include "nsNetUtil.h"
 
-NS_IMPL_ISUPPORTS1(nsNoDataProtocolContentPolicy, nsIContentPolicy)
+NS_IMPL_ISUPPORTS(nsNoDataProtocolContentPolicy, nsIContentPolicy)
 
 NS_IMETHODIMP
 nsNoDataProtocolContentPolicy::ShouldLoad(uint32_t aContentType,
                                           nsIURI *aContentLocation,
                                           nsIURI *aRequestingLocation,
                                           nsISupports *aRequestingContext,
                                           const nsACString &aMimeGuess,
                                           nsISupports *aExtra,
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -160,17 +160,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsNodeInfo)
   return nsCCUncollectableMarker::sGeneration && tmp->CanSkip();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsNodeInfo)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsNodeInfo, LastRelease())
 NS_INTERFACE_TABLE_HEAD(nsNodeInfo)
-  NS_INTERFACE_TABLE1(nsNodeInfo, nsINodeInfo)
+  NS_INTERFACE_TABLE(nsNodeInfo, nsINodeInfo)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsNodeInfo)
 NS_INTERFACE_MAP_END
 
 // nsINodeInfo
 
 void
 nsNodeInfo::GetNamespaceURI(nsAString& aNameSpaceURI) const
 {
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -390,17 +390,17 @@ public:
   NS_IMETHOD Notify(nsITimer *timer);
 
 private:
   nsCOMPtr<nsITimer> mTimer;
   nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
   nsCOMPtr<nsIObjectLoadingContent> mContent;
 };
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
+NS_IMPL_ISUPPORTS_INHERITED(nsStopPluginRunnable, nsRunnable, nsITimerCallback)
 
 NS_IMETHODIMP
 nsStopPluginRunnable::Notify(nsITimer *aTimer)
 {
   return Run();
 }
 
 NS_IMETHODIMP
@@ -1152,17 +1152,17 @@ public:
   ObjectInterfaceRequestorShim(nsIObjectLoadingContent* aContent)
     : mContent(aContent)
   {}
 
 protected:
   nsCOMPtr<nsIObjectLoadingContent> mContent;
 };
 
-NS_IMPL_CYCLE_COLLECTION_1(ObjectInterfaceRequestorShim, mContent)
+NS_IMPL_CYCLE_COLLECTION(ObjectInterfaceRequestorShim, mContent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ObjectInterfaceRequestorShim)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInterfaceRequestor)
 NS_INTERFACE_MAP_END
@@ -3509,10 +3509,10 @@ nsObjectLoadingContent::SetupProtoChainR
     return NS_OK;
   }
   nsObjectLoadingContent* objectLoadingContent =
     static_cast<nsObjectLoadingContent*>(mContent.get());
   objectLoadingContent->SetupProtoChain(cx, obj);
   return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS1(nsObjectLoadingContent::SetupProtoChainRunner, nsIRunnable)
-
+NS_IMPL_ISUPPORTS(nsObjectLoadingContent::SetupProtoChainRunner, nsIRunnable)
+
--- a/content/base/src/nsPlainTextSerializer.cpp
+++ b/content/base/src/nsPlainTextSerializer.cpp
@@ -107,18 +107,18 @@ nsPlainTextSerializer::nsPlainTextSerial
 
 nsPlainTextSerializer::~nsPlainTextSerializer()
 {
   delete[] mTagStack;
   delete[] mOLStack;
   NS_WARN_IF_FALSE(mHeadLevel == 0, "Wrong head level!");
 }
 
-NS_IMPL_ISUPPORTS1(nsPlainTextSerializer,
-                   nsIContentSerializer)
+NS_IMPL_ISUPPORTS(nsPlainTextSerializer,
+                  nsIContentSerializer)
 
 
 NS_IMETHODIMP 
 nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn,
                             const char* aCharSet, bool aIsCopying,
                             bool aIsWholeDocument)
 {
 #ifdef DEBUG
--- a/content/base/src/nsReferencedElement.cpp
+++ b/content/base/src/nsReferencedElement.cpp
@@ -212,18 +212,18 @@ nsReferencedElement::Observe(Element* aO
     p->mWatchID = nullptr;
   }
   return keepTracking;
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsReferencedElement::ChangeNotification,
                              nsRunnable)
 
-NS_IMPL_ISUPPORTS1(nsReferencedElement::DocumentLoadNotification,
-                   nsIObserver)
+NS_IMPL_ISUPPORTS(nsReferencedElement::DocumentLoadNotification,
+                  nsIObserver)
 
 NS_IMETHODIMP
 nsReferencedElement::DocumentLoadNotification::Observe(nsISupports* aSubject,
                                                        const char* aTopic,
                                                        const char16_t* aData)
 {
   NS_ASSERTION(PL_strcmp(aTopic, "external-resource-document-created") == 0,
                "Unexpected topic");
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -172,17 +172,17 @@ nsScriptLoader::~nsScriptLoader()
 
   // Unblock the kids, in case any of them moved to a different document
   // subtree in the meantime and therefore aren't actually going away.
   for (uint32_t j = 0; j < mPendingChildLoaders.Length(); ++j) {
     mPendingChildLoaders[j]->RemoveExecuteBlocker();
   }  
 }
 
-NS_IMPL_ISUPPORTS1(nsScriptLoader, nsIStreamLoaderObserver)
+NS_IMPL_ISUPPORTS(nsScriptLoader, nsIStreamLoaderObserver)
 
 // Helper method for checking if the script element is an event-handler
 // This means that it has both a for-attribute and a event-attribute.
 // Also, if the for-attribute has a value that matches "\s*window\s*",
 // and the event-attribute matches "\s*onload([ \(].*)?" then it isn't an
 // eventhandler. (both matches are case insensitive).
 // This is how IE seems to filter out a window's onload handler from a
 // <script for=... event=...> element.
--- a/content/base/src/nsSyncLoadService.cpp
+++ b/content/base/src/nsSyncLoadService.cpp
@@ -80,19 +80,19 @@ nsForceXMLListener::nsForceXMLListener(n
     : mListener(aListener)
 {
 }
 
 nsForceXMLListener::~nsForceXMLListener()
 {
 }
 
-NS_IMPL_ISUPPORTS2(nsForceXMLListener,
-                   nsIStreamListener,
-                   nsIRequestObserver)
+NS_IMPL_ISUPPORTS(nsForceXMLListener,
+                  nsIStreamListener,
+                  nsIRequestObserver)
 
 NS_IMETHODIMP
 nsForceXMLListener::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext)
 {
     nsresult status;
     aRequest->GetStatus(&status);
     nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
     if (channel && NS_SUCCEEDED(status)) {
@@ -111,22 +111,22 @@ nsForceXMLListener::OnStopRequest(nsIReq
 
 nsSyncLoader::~nsSyncLoader()
 {
     if (mLoading && mChannel) {
         mChannel->Cancel(NS_BINDING_ABORTED);
     }
 }
 
-NS_IMPL_ISUPPORTS5(nsSyncLoader,
-                   nsIStreamListener,
-                   nsIRequestObserver,
-                   nsIChannelEventSink,
-                   nsIInterfaceRequestor,
-                   nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS(nsSyncLoader,
+                  nsIStreamListener,
+                  nsIRequestObserver,
+                  nsIChannelEventSink,
+                  nsIInterfaceRequestor,
+                  nsISupportsWeakReference)
 
 nsresult
 nsSyncLoader::LoadDocument(nsIChannel* aChannel,
                            nsIPrincipal *aLoaderPrincipal,
                            bool aChannelIsSync,
                            bool aForceToXML,
                            nsIDOMDocument **aResult)
 {
--- a/content/base/src/nsTextNode.cpp
+++ b/content/base/src/nsTextNode.cpp
@@ -91,18 +91,18 @@ private:
   int32_t mNameSpaceID;
   nsCOMPtr<nsIAtom> mAttrName;
 };
 
 nsTextNode::~nsTextNode()
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED3(nsTextNode, nsGenericDOMDataNode, nsIDOMNode,
-                             nsIDOMText, nsIDOMCharacterData)
+NS_IMPL_ISUPPORTS_INHERITED(nsTextNode, nsGenericDOMDataNode, nsIDOMNode,
+                            nsIDOMText, nsIDOMCharacterData)
 
 JSObject*
 nsTextNode::WrapNode(JSContext *aCx)
 {
   return TextBinding::Wrap(aCx, this);
 }
 
 bool
@@ -217,18 +217,18 @@ NS_NewAttributeContent(nsNodeInfoManager
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aResult = textNode);
 
   return NS_OK;
 }
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsAttributeTextNode, nsTextNode,
-                             nsIMutationObserver)
+NS_IMPL_ISUPPORTS_INHERITED(nsAttributeTextNode, nsTextNode,
+                            nsIMutationObserver)
 
 nsresult
 nsAttributeTextNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 bool aCompileEventHandlers)
 {
   NS_PRECONDITION(aParent && aParent->GetParent(),
                   "This node can't be a child of the document or of the document root");
--- a/content/base/src/nsXMLContentSerializer.cpp
+++ b/content/base/src/nsXMLContentSerializer.cpp
@@ -66,17 +66,17 @@ nsXMLContentSerializer::nsXMLContentSeri
     mInBody(0)
 {
 }
 
 nsXMLContentSerializer::~nsXMLContentSerializer()
 {
 }
 
-NS_IMPL_ISUPPORTS1(nsXMLContentSerializer, nsIContentSerializer)
+NS_IMPL_ISUPPORTS(nsXMLContentSerializer, nsIContentSerializer)
 
 NS_IMETHODIMP 
 nsXMLContentSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn,
                              const char* aCharSet, bool aIsCopying,
                              bool aRewriteEncodingDeclaration)
 {
   mPrefixIndex = 0;
   mColPos = 0;
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -133,17 +133,17 @@ using namespace mozilla::dom;
   nsXMLHttpRequest::_name(nsACString& aOut)                                     \
   {                                                                             \
     nsCString tmp;                                                              \
     _name(tmp);                                                                 \
     aOut = tmp;                                                                 \
     return NS_OK;                                                               \
   }
 
-NS_IMPL_ISUPPORTS1(nsXHRParseEndListener, nsIDOMEventListener)
+NS_IMPL_ISUPPORTS(nsXHRParseEndListener, nsIDOMEventListener)
 
 class nsResumeTimeoutsEvent : public nsRunnable
 {
 public:
   nsResumeTimeoutsEvent(nsPIDOMWindow* aWindow) : mWindow(aWindow) {}
 
   NS_IMETHOD Run()
   {
@@ -175,17 +175,17 @@ class XMLHttpRequestAuthPrompt : public 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIAUTHPROMPT
 
   XMLHttpRequestAuthPrompt();
   virtual ~XMLHttpRequestAuthPrompt();
 };
 
-NS_IMPL_ISUPPORTS1(XMLHttpRequestAuthPrompt, nsIAuthPrompt)
+NS_IMPL_ISUPPORTS(XMLHttpRequestAuthPrompt, nsIAuthPrompt)
 
 XMLHttpRequestAuthPrompt::XMLHttpRequestAuthPrompt()
 {
   MOZ_COUNT_CTOR(XMLHttpRequestAuthPrompt);
 }
 
 XMLHttpRequestAuthPrompt::~XMLHttpRequestAuthPrompt()
 {
@@ -3336,17 +3336,17 @@ public:
 
     return NS_OK;
   }
 
 private:
   nsRefPtr<nsXMLHttpRequest> mXHR;
 };
 
-NS_IMPL_CYCLE_COLLECTION_1(AsyncVerifyRedirectCallbackForwarder, mXHR)
+NS_IMPL_CYCLE_COLLECTION(AsyncVerifyRedirectCallbackForwarder, mXHR)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AsyncVerifyRedirectCallbackForwarder)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(AsyncVerifyRedirectCallbackForwarder)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(AsyncVerifyRedirectCallbackForwarder)
@@ -3776,17 +3776,17 @@ nsXMLHttpRequest::EnsureXPCOMifier()
 {
   if (!mXPCOMifier) {
     mXPCOMifier = new nsXMLHttpRequestXPCOMifier(this);
   }
   nsRefPtr<nsXMLHttpRequestXPCOMifier> newRef(mXPCOMifier);
   return newRef.forget();
 }
 
-NS_IMPL_ISUPPORTS1(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
+NS_IMPL_ISUPPORTS(nsXMLHttpRequest::nsHeaderVisitor, nsIHttpHeaderVisitor)
 
 NS_IMETHODIMP nsXMLHttpRequest::
 nsHeaderVisitor::VisitHeader(const nsACString &header, const nsACString &value)
 {
   if (mXHR->IsSafeHeader(header, mHttpChannel)) {
     mHeaders.Append(header);
     mHeaders.Append(": ");
     mHeaders.Append(value);
@@ -3804,17 +3804,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXMLHttpRequestXPCOMifier)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXMLHttpRequestXPCOMifier)
 
-// Can't NS_IMPL_CYCLE_COLLECTION_1 because mXHR has ambiguous
+// Can't NS_IMPL_CYCLE_COLLECTION( because mXHR has ambiguous
 // inheritance from nsISupports.
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequestXPCOMifier)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequestXPCOMifier)
 if (tmp->mXHR) {
   tmp->mXHR->mXPCOMifier = nullptr;
 }
 NS_IMPL_CYCLE_COLLECTION_UNLINK(mXHR)
@@ -3925,23 +3925,22 @@ ArrayBufferBuilder::getArrayBuffer(JSCon
   // added
   if (mCapacity > mLength || mLength == 0) {
     if (!setCapacity(mLength)) {
       return nullptr;
     }
   }
 
   JSObject* obj = JS_NewArrayBufferWithContents(aCx, mLength, mDataPtr);
+  mDataPtr = nullptr;
+  mLength = mCapacity = 0;
   if (!obj) {
+    js_free(mDataPtr);
     return nullptr;
   }
-
-  mDataPtr = nullptr;
-  mLength = mCapacity = 0;
-
   return obj;
 }
 
 /* static */ bool
 ArrayBufferBuilder::areOverlappingRegions(const uint8_t* aStart1,
                                           uint32_t aLength1,
                                           const uint8_t* aStart2,
                                           uint32_t aLength2)
--- a/content/canvas/src/CanvasGradient.h
+++ b/content/canvas/src/CanvasGradient.h
@@ -18,28 +18,26 @@ namespace mozilla {
 namespace dom {
 
 class CanvasGradient : public nsWrapperCache
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasGradient)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasGradient)
 
-  enum Type
-  {
+  MOZ_BEGIN_NESTED_ENUM_CLASS(Type, uint8_t)
     LINEAR = 0,
     RADIAL
-  };
+  MOZ_END_NESTED_ENUM_CLASS(Type)
 
   Type GetType()
   {
     return mType;
   }
 
-
   mozilla::gfx::GradientStops *
   GetGradientStopsForTarget(mozilla::gfx::DrawTarget *aRT)
   {
     if (mStops && mStops->GetBackendType() == aRT->GetType()) {
       return mStops;
     }
 
     mStops =
@@ -73,12 +71,14 @@ protected:
 
   nsRefPtr<CanvasRenderingContext2D> mContext;
   nsTArray<mozilla::gfx::GradientStop> mRawStops;
   mozilla::RefPtr<mozilla::gfx::GradientStops> mStops;
   Type mType;
   virtual ~CanvasGradient() {}
 };
 
+MOZ_FINISH_NESTED_ENUM_CLASS(CanvasGradient::Type)
+
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_CanvasGradient_h
--- a/content/canvas/src/CanvasImageCache.cpp
+++ b/content/canvas/src/CanvasImageCache.cpp
@@ -182,17 +182,17 @@ CanvasImageCache::Lookup(Element* aImage
     return nullptr;
 
   gImageCache->MarkUsed(entry->mData);
 
   *aSize = entry->mData->mSize;
   return entry->mData->mSourceSurface;
 }
 
-NS_IMPL_ISUPPORTS1(CanvasImageCacheShutdownObserver, nsIObserver)
+NS_IMPL_ISUPPORTS(CanvasImageCacheShutdownObserver, nsIObserver)
 
 NS_IMETHODIMP
 CanvasImageCacheShutdownObserver::Observe(nsISupports *aSubject,
                                           const char *aTopic,
                                           const char16_t *aData)
 {
   if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
     delete gImageCache;
--- a/content/canvas/src/CanvasPattern.h
+++ b/content/canvas/src/CanvasPattern.h
@@ -22,54 +22,55 @@ class SourceSurface;
 namespace dom {
 
 class CanvasPattern MOZ_FINAL : public nsWrapperCache
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPattern)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPattern)
 
-  enum RepeatMode
-  {
+  MOZ_BEGIN_NESTED_ENUM_CLASS(RepeatMode, uint8_t)
     REPEAT,
     REPEATX,
     REPEATY,
     NOREPEAT
-  };
+  MOZ_END_NESTED_ENUM_CLASS(RepeatMode)
 
   CanvasPattern(CanvasRenderingContext2D* aContext,
                 gfx::SourceSurface* aSurface,
                 RepeatMode aRepeat,
                 nsIPrincipal* principalForSecurityCheck,
                 bool forceWriteOnly,
                 bool CORSUsed)
     : mContext(aContext)
     , mSurface(aSurface)
-    , mRepeat(aRepeat)
     , mPrincipal(principalForSecurityCheck)
     , mForceWriteOnly(forceWriteOnly)
     , mCORSUsed(CORSUsed)
+    , mRepeat(aRepeat)
   {
     SetIsDOMBinding();
   }
 
   JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE
   {
     return CanvasPatternBinding::Wrap(aCx, this);
   }
 
   CanvasRenderingContext2D* GetParentObject()
   {
     return mContext;
   }
 
   nsRefPtr<CanvasRenderingContext2D> mContext;
   RefPtr<gfx::SourceSurface> mSurface;
-  const RepeatMode mRepeat;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   const bool mForceWriteOnly;
   const bool mCORSUsed;
+  const RepeatMode mRepeat;
 };
 
+MOZ_FINISH_NESTED_ENUM_CLASS(CanvasPattern::RepeatMode)
+
 }
 }
 
 #endif // mozilla_dom_CanvasPattern_h
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -153,25 +153,25 @@ public:
     return MOZ_COLLECT_REPORT(
       "canvas-2d-pixels", KIND_OTHER, UNITS_BYTES,
       gCanvasAzureMemoryUsed,
       "Memory used by 2D canvases. Each canvas requires "
       "(width * height * 4) bytes.");
   }
 };
 
-NS_IMPL_ISUPPORTS1(Canvas2dPixelsReporter, nsIMemoryReporter)
+NS_IMPL_ISUPPORTS(Canvas2dPixelsReporter, nsIMemoryReporter)
 
 class CanvasRadialGradient : public CanvasGradient
 {
 public:
   CanvasRadialGradient(CanvasRenderingContext2D* aContext,
                        const Point &aBeginOrigin, Float aBeginRadius,
                        const Point &aEndOrigin, Float aEndRadius)
-    : CanvasGradient(aContext, RADIAL)
+    : CanvasGradient(aContext, Type::RADIAL)
     , mCenter1(aBeginOrigin)
     , mCenter2(aEndOrigin)
     , mRadius1(aBeginRadius)
     , mRadius2(aEndRadius)
   {
   }
 
   Point mCenter1;
@@ -180,17 +180,17 @@ public:
   Float mRadius2;
 };
 
 class CanvasLinearGradient : public CanvasGradient
 {
 public:
   CanvasLinearGradient(CanvasRenderingContext2D* aContext,
                        const Point &aBegin, const Point &aEnd)
-    : CanvasGradient(aContext, LINEAR)
+    : CanvasGradient(aContext, Type::LINEAR)
     , mBegin(aBegin)
     , mEnd(aEnd)
   {
   }
 
 protected:
   friend class CanvasGeneralPattern;
 
@@ -226,41 +226,41 @@ public:
     // not be executed.
     NS_ASSERTION(!mPattern, "ForStyle() should only be called once on CanvasGeneralPattern!");
 
     const ContextState &state = aCtx->CurrentState();
 
     if (state.StyleIsColor(aStyle)) {
       mPattern = new (mColorPattern.addr()) ColorPattern(Color::FromABGR(state.colorStyles[aStyle]));
     } else if (state.gradientStyles[aStyle] &&
-               state.gradientStyles[aStyle]->GetType() == CanvasGradient::LINEAR) {
+               state.gradientStyles[aStyle]->GetType() == CanvasGradient::Type::LINEAR) {
       CanvasLinearGradient *gradient =
         static_cast<CanvasLinearGradient*>(state.gradientStyles[aStyle].get());
 
       mPattern = new (mLinearGradientPattern.addr())
         LinearGradientPattern(gradient->mBegin, gradient->mEnd,
                               gradient->GetGradientStopsForTarget(aRT));
     } else if (state.gradientStyles[aStyle] &&
-               state.gradientStyles[aStyle]->GetType() == CanvasGradient::RADIAL) {
+               state.gradientStyles[aStyle]->GetType() == CanvasGradient::Type::RADIAL) {
       CanvasRadialGradient *gradient =
         static_cast<CanvasRadialGradient*>(state.gradientStyles[aStyle].get());
 
       mPattern = new (mRadialGradientPattern.addr())
         RadialGradientPattern(gradient->mCenter1, gradient->mCenter2, gradient->mRadius1,
                               gradient->mRadius2, gradient->GetGradientStopsForTarget(aRT));
     } else if (state.patternStyles[aStyle]) {
       if (aCtx->mCanvasElement) {
         CanvasUtils::DoDrawImageSecurityCheck(aCtx->mCanvasElement,
                                               state.patternStyles[aStyle]->mPrincipal,
                                               state.patternStyles[aStyle]->mForceWriteOnly,
                                               state.patternStyles[aStyle]->mCORSUsed);
       }
 
       ExtendMode mode;
-      if (state.patternStyles[aStyle]->mRepeat == CanvasPattern::NOREPEAT) {
+      if (state.patternStyles[aStyle]->mRepeat == CanvasPattern::RepeatMode::NOREPEAT) {
         mode = ExtendMode::CLAMP;
       } else {
         mode = ExtendMode::REPEAT;
       }
       mPattern = new (mSurfacePattern.addr())
         SurfacePattern(state.patternStyles[aStyle]->mSurface, mode);
     }
 
@@ -473,31 +473,31 @@ private:
 NS_IMPL_CYCLE_COLLECTING_ADDREF(CanvasRenderingContext2D)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasRenderingContext2D)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(CanvasRenderingContext2D)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CanvasRenderingContext2D)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCanvasElement)
   for (uint32_t i = 0; i < tmp->mStyleStack.Length(); i++) {
-    ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[STYLE_STROKE]);
-    ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[STYLE_FILL]);
-    ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[STYLE_STROKE]);
-    ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[STYLE_FILL]);
+    ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[Style::STROKE]);
+    ImplCycleCollectionUnlink(tmp->mStyleStack[i].patternStyles[Style::FILL]);
+    ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[Style::STROKE]);
+    ImplCycleCollectionUnlink(tmp->mStyleStack[i].gradientStyles[Style::FILL]);
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CanvasRenderingContext2D)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCanvasElement)
   for (uint32_t i = 0; i < tmp->mStyleStack.Length(); i++) {
-    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].patternStyles[STYLE_STROKE], "Stroke CanvasPattern");
-    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].patternStyles[STYLE_FILL], "Fill CanvasPattern");
-    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].gradientStyles[STYLE_STROKE], "Stroke CanvasGradient");
-    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].gradientStyles[STYLE_FILL], "Fill CanvasGradient");
+    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].patternStyles[Style::STROKE], "Stroke CanvasPattern");
+    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].patternStyles[Style::FILL], "Fill CanvasPattern");
+    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].gradientStyles[Style::STROKE], "Stroke CanvasGradient");
+    ImplCycleCollectionTraverse(cb, tmp->mStyleStack[i].gradientStyles[Style::FILL], "Fill CanvasGradient");
   }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(CanvasRenderingContext2D)
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(CanvasRenderingContext2D)
  if (nsCCUncollectableMarker::sGeneration && tmp->IsBlack()) {
@@ -997,18 +997,18 @@ CanvasRenderingContext2D::ClearTarget()
   mStyleStack.Clear();
   mPathBuilder = nullptr;
   mPath = nullptr;
   mDSPathBuilder = nullptr;
 
   ContextState *state = mStyleStack.AppendElement();
   state->globalAlpha = 1.0;
 
-  state->colorStyles[STYLE_FILL] = NS_RGB(0,0,0);
-  state->colorStyles[STYLE_STROKE] = NS_RGB(0,0,0);
+  state->colorStyles[Style::FILL] = NS_RGB(0,0,0);
+  state->colorStyles[Style::STROKE] = NS_RGB(0,0,0);
   state->shadowColor = NS_RGBA(0,0,0,0);
 }
 
 NS_IMETHODIMP
 CanvasRenderingContext2D::InitializeWithSurface(nsIDocShell *shell,
                                                 gfxASurface *surface,
                                                 int32_t width,
                                                 int32_t height)
@@ -1422,26 +1422,26 @@ CanvasRenderingContext2D::CreateRadialGr
 }
 
 already_AddRefed<CanvasPattern>
 CanvasRenderingContext2D::CreatePattern(const HTMLImageOrCanvasOrVideoElement& element,
                                         const nsAString& repeat,
                                         ErrorResult& error)
 {
   CanvasPattern::RepeatMode repeatMode =
-    CanvasPattern::NOREPEAT;
+    CanvasPattern::RepeatMode::NOREPEAT;
 
   if (repeat.IsEmpty() || repeat.EqualsLiteral("repeat")) {
-    repeatMode = CanvasPattern::REPEAT;
+    repeatMode = CanvasPattern::RepeatMode::REPEAT;
   } else if (repeat.EqualsLiteral("repeat-x")) {
-    repeatMode = CanvasPattern::REPEATX;
+    repeatMode = CanvasPattern::RepeatMode::REPEATX;
   } else if (repeat.EqualsLiteral("repeat-y")) {
-    repeatMode = CanvasPattern::REPEATY;
+    repeatMode = CanvasPattern::RepeatMode::REPEATY;
   } else if (repeat.EqualsLiteral("no-repeat")) {
-    repeatMode = CanvasPattern::NOREPEAT;
+    repeatMode = CanvasPattern::RepeatMode::NOREPEAT;
   } else {
     error.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     return nullptr;
   }
 
   Element* htmlElement;
   if (element.IsHTMLCanvasElement()) {
     HTMLCanvasElement* canvas = &element.GetAsHTMLCanvasElement();
@@ -1522,25 +1522,25 @@ CanvasRenderingContext2D::ClearRect(doub
 }
 
 void
 CanvasRenderingContext2D::FillRect(double x, double y, double w,
                                    double h)
 {
   const ContextState &state = CurrentState();
 
-  if (state.patternStyles[STYLE_FILL]) {
+  if (state.patternStyles[Style::FILL]) {
     CanvasPattern::RepeatMode repeat =
-      state.patternStyles[STYLE_FILL]->mRepeat;
+      state.patternStyles[Style::FILL]->mRepeat;
     // In the FillRect case repeat modes are easy to deal with.
-    bool limitx = repeat == CanvasPattern::NOREPEAT || repeat == CanvasPattern::REPEATY;
-    bool limity = repeat == CanvasPattern::NOREPEAT || repeat == CanvasPattern::REPEATX;
+    bool limitx = repeat == CanvasPattern::RepeatMode::NOREPEAT || repeat == CanvasPattern::RepeatMode::REPEATY;
+    bool limity = repeat == CanvasPattern::RepeatMode::NOREPEAT || repeat == CanvasPattern::RepeatMode::REPEATX;
 
     IntSize patternSize =
-      state.patternStyles[STYLE_FILL]->mSurface->GetSize();
+      state.patternStyles[Style::FILL]->mSurface->GetSize();
 
     // We always need to execute painting for non-over operators, even if
     // we end up with w/h = 0.
     if (limitx) {
       if (x < 0) {
         w += x;
         if (w < 0) {
           w = 0;
@@ -1578,17 +1578,17 @@ CanvasRenderingContext2D::FillRect(doubl
   EnsureTarget();
   if (NeedToDrawShadow()) {
     bounds = mgfx::Rect(x, y, w, h);
     bounds = mTarget->GetTransform().TransformBounds(bounds);
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     FillRect(mgfx::Rect(x, y, w, h),
-             CanvasGeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
+             CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
              DrawOptions(state.globalAlpha, UsedOperation()));
 
   RedrawUser(gfxRect(x, y, w, h));
 }
 
 void
 CanvasRenderingContext2D::StrokeRect(double x, double y, double w,
                                      double h)
@@ -1614,46 +1614,46 @@ CanvasRenderingContext2D::StrokeRect(dou
 
   if (!h) {
     CapStyle cap = CapStyle::BUTT;
     if (state.lineJoin == JoinStyle::ROUND) {
       cap = CapStyle::ROUND;
     }
     AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
       StrokeLine(Point(x, y), Point(x + w, y),
-                  CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
+                  CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
                   StrokeOptions(state.lineWidth, state.lineJoin,
                                 cap, state.miterLimit,
                                 state.dash.Length(),
                                 state.dash.Elements(),
                                 state.dashOffset),
                   DrawOptions(state.globalAlpha, UsedOperation()));
     return;
   }
 
   if (!w) {
     CapStyle cap = CapStyle::BUTT;
     if (state.lineJoin == JoinStyle::ROUND) {
       cap = CapStyle::ROUND;
     }
     AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
       StrokeLine(Point(x, y), Point(x, y + h),
-                  CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
+                  CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
                   StrokeOptions(state.lineWidth, state.lineJoin,
                                 cap, state.miterLimit,
                                 state.dash.Length(),
                                 state.dash.Elements(),
                                 state.dashOffset),
                   DrawOptions(state.globalAlpha, UsedOperation()));
     return;
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
     StrokeRect(mgfx::Rect(x, y, w, h),
-                CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
+                CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
                 StrokeOptions(state.lineWidth, state.lineJoin,
                               state.lineCap, state.miterLimit,
                               state.dash.Length(),
                               state.dash.Elements(),
                               state.dashOffset),
                 DrawOptions(state.globalAlpha, UsedOperation()));
 
   Redraw();
@@ -1683,17 +1683,17 @@ CanvasRenderingContext2D::Fill(const Can
 
   mgfx::Rect bounds;
 
   if (NeedToDrawShadow()) {
     bounds = mPath->GetBounds(mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
-    Fill(mPath, CanvasGeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
+    Fill(mPath, CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
          DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
 void CanvasRenderingContext2D::Fill(const CanvasPath& path, const CanvasWindingRule& winding)
 {
   EnsureTarget();
@@ -1706,17 +1706,17 @@ void CanvasRenderingContext2D::Fill(cons
 
   mgfx::Rect bounds;
 
   if (NeedToDrawShadow()) {
     bounds = gfxpath->GetBounds(mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
-    Fill(gfxpath, CanvasGeneralPattern().ForStyle(this, STYLE_FILL, mTarget),
+    Fill(gfxpath, CanvasGeneralPattern().ForStyle(this, Style::FILL, mTarget),
          DrawOptions(CurrentState().globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
 void
 CanvasRenderingContext2D::Stroke()
 {
@@ -1735,17 +1735,17 @@ CanvasRenderingContext2D::Stroke()
 
   mgfx::Rect bounds;
   if (NeedToDrawShadow()) {
     bounds =
       mPath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
-    Stroke(mPath, CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
+    Stroke(mPath, CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
            strokeOptions, DrawOptions(state.globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
 void
 CanvasRenderingContext2D::Stroke(const CanvasPath& path)
 {
@@ -1766,17 +1766,17 @@ CanvasRenderingContext2D::Stroke(const C
 
   mgfx::Rect bounds;
   if (NeedToDrawShadow()) {
     bounds =
       gfxpath->GetStrokedBounds(strokeOptions, mTarget->GetTransform());
   }
 
   AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
-    Stroke(gfxpath, CanvasGeneralPattern().ForStyle(this, STYLE_STROKE, mTarget),
+    Stroke(gfxpath, CanvasGeneralPattern().ForStyle(this, Style::STROKE, mTarget),
            strokeOptions, DrawOptions(state.globalAlpha, UsedOperation()));
 
   Redraw();
 }
 
 void CanvasRenderingContext2D::DrawFocusIfNeeded(mozilla::dom::Element& aElement)
 {
   EnsureUserSpacePath();
@@ -1798,27 +1798,27 @@ void CanvasRenderingContext2D::DrawFocus
 
     state.lineCap = CapStyle::BUTT;
     state.lineJoin = mozilla::gfx::JoinStyle::MITER_OR_BEVEL;
     state.lineWidth = 1;
     CurrentState().dash.Clear();
 
     // color and style of the rings is the same as for image maps
     // set the background focus color
-    CurrentState().SetColorStyle(STYLE_STROKE, NS_RGBA(255, 255, 255, 255));
+    CurrentState().SetColorStyle(Style::STROKE, NS_RGBA(255, 255, 255, 255));
     // draw the focus ring
     Stroke();
 
     // set dashing for foreground
     FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
     dash.AppendElement(1);
     dash.AppendElement(1);
 
     // set the foreground focus color
-    CurrentState().SetColorStyle(STYLE_STROKE, NS_RGBA(0,0,0, 255));
+    CurrentState().SetColorStyle(Style::STROKE, NS_RGBA(0,0,0, 255));
     // draw the focus ring
     Stroke();
 
     Restore();
   }
 }
 
 bool CanvasRenderingContext2D::DrawCustomFocusRing(mozilla::dom::Element& aElement)
@@ -2286,88 +2286,88 @@ CanvasRenderingContext2D::SetFont(const 
   // longer seems to be required.)
   declaration->GetValue(eCSSProperty_font, CurrentState().font);
 }
 
 void
 CanvasRenderingContext2D::SetTextAlign(const nsAString& ta)
 {
   if (ta.EqualsLiteral("start"))
-    CurrentState().textAlign = TEXT_ALIGN_START;
+    CurrentState().textAlign = TextAlign::START;
   else if (ta.EqualsLiteral("end"))
-    CurrentState().textAlign = TEXT_ALIGN_END;
+    CurrentState().textAlign = TextAlign::END;
   else if (ta.EqualsLiteral("left"))
-    CurrentState().textAlign = TEXT_ALIGN_LEFT;
+    CurrentState().textAlign = TextAlign::LEFT;
   else if (ta.EqualsLiteral("right"))
-    CurrentState().textAlign = TEXT_ALIGN_RIGHT;
+    CurrentState().textAlign = TextAlign::RIGHT;
   else if (ta.EqualsLiteral("center"))
-    CurrentState().textAlign = TEXT_ALIGN_CENTER;
+    CurrentState().textAlign = TextAlign::CENTER;
 }
 
 void
 CanvasRenderingContext2D::GetTextAlign(nsAString& ta)
 {
   switch (CurrentState().textAlign)
   {
-  case TEXT_ALIGN_START:
+  case TextAlign::START:
     ta.AssignLiteral("start");
     break;
-  case TEXT_ALIGN_END:
+  case TextAlign::END:
     ta.AssignLiteral("end");
     break;
-  case TEXT_ALIGN_LEFT:
+  case TextAlign::LEFT:
     ta.AssignLiteral("left");
     break;
-  case TEXT_ALIGN_RIGHT:
+  case TextAlign::RIGHT:
     ta.AssignLiteral("right");
     break;
-  case TEXT_ALIGN_CENTER:
+  case TextAlign::CENTER:
     ta.AssignLiteral("center");
     break;
   }
 }
 
 void
 CanvasRenderingContext2D::SetTextBaseline(const nsAString& tb)
 {
   if (tb.EqualsLiteral("top"))
-    CurrentState().textBaseline = TEXT_BASELINE_TOP;
+    CurrentState().textBaseline = TextBaseline::TOP;
   else if (tb.EqualsLiteral("hanging"))
-    CurrentState().textBaseline = TEXT_BASELINE_HANGING;
+    CurrentState().textBaseline = TextBaseline::HANGING;
   else if (tb.EqualsLiteral("middle"))
-    CurrentState().textBaseline = TEXT_BASELINE_MIDDLE;
+    CurrentState().textBaseline = TextBaseline::MIDDLE;
   else if (tb.EqualsLiteral("alphabetic"))
-    CurrentState().textBaseline = TEXT_BASELINE_ALPHABETIC;
+    CurrentState().textBaseline = TextBaseline::ALPHABETIC;
   else if (tb.EqualsLiteral("ideographic"))
-    CurrentState().textBaseline = TEXT_BASELINE_IDEOGRAPHIC;
+    CurrentState().textBaseline = TextBaseline::IDEOGRAPHIC;
   else if (tb.EqualsLiteral("bottom"))
-    CurrentState().textBaseline = TEXT_BASELINE_BOTTOM;
+    CurrentState().textBaseline = TextBaseline::BOTTOM;
 }
 
 void
 CanvasRenderingContext2D::GetTextBaseline(nsAString& tb)
 {
   switch (CurrentState().textBaseline)
   {
-  case TEXT_BASELINE_TOP:
+  case TextBaseline::TOP:
     tb.AssignLiteral("top");
     break;
-  case TEXT_BASELINE_HANGING:
+  case TextBaseline::HANGING:
     tb.AssignLiteral("hanging");
     break;
-  case TEXT_BASELINE_MIDDLE:
+  case TextBaseline::MIDDLE:
     tb.AssignLiteral("middle");
     break;
-  case TEXT_BASELINE_ALPHABETIC:
+  case TextBaseline::ALPHABETIC:
     tb.AssignLiteral("alphabetic");
     break;
-  case TEXT_BASELINE_IDEOGRAPHIC:
+  case TextBaseline::IDEOGRAPHIC:
     tb.AssignLiteral("ideographic");
     break;
-  case TEXT_BASELINE_BOTTOM:
+  case TextBaseline::BOTTOM:
     tb.AssignLiteral("bottom");
     break;
   }
 }
 
 /*
  * Helper function that replaces the whitespace characters in a string
  * with U+0020 SPACE. The whitespace characters are defined as U+0020 SPACE,
@@ -2382,35 +2382,35 @@ TextReplaceWhitespaceCharacters(nsAutoSt
 }
 
 void
 CanvasRenderingContext2D::FillText(const nsAString& text, double x,
                                    double y,
                                    const Optional<double>& maxWidth,
                                    ErrorResult& error)
 {
-  error = DrawOrMeasureText(text, x, y, maxWidth, TEXT_DRAW_OPERATION_FILL, nullptr);
+  error = DrawOrMeasureText(text, x, y, maxWidth, TextDrawOperation::FILL, nullptr);
 }
 
 void
 CanvasRenderingContext2D::StrokeText(const nsAString& text, double x,
                                      double y,
                                      const Optional<double>& maxWidth,
                                      ErrorResult& error)
 {
-  error = DrawOrMeasureText(text, x, y, maxWidth, TEXT_DRAW_OPERATION_STROKE, nullptr);
+  error = DrawOrMeasureText(text, x, y, maxWidth, TextDrawOperation::STROKE, nullptr);
 }
 
 TextMetrics*
 CanvasRenderingContext2D::MeasureText(const nsAString& rawText,
                                       ErrorResult& error)
 {
   float width;
   Optional<double> maxWidth;
-  error = DrawOrMeasureText(rawText, 0, 0, maxWidth, TEXT_DRAW_OPERATION_MEASURE, &width);
+  error = DrawOrMeasureText(rawText, 0, 0, maxWidth, TextDrawOperation::MEASURE, &width);
   if (error.Failed()) {
     return nullptr;
   }
 
   return new TextMetrics(width);
 }
 
 void
@@ -2634,38 +2634,38 @@ struct MOZ_STACK_CLASS CanvasBidiProcess
       }
 
       buffer.mGlyphs = &glyphBuf.front();
       buffer.mNumGlyphs = glyphBuf.size();
 
       Rect bounds = mCtx->mTarget->GetTransform().
         TransformBounds(Rect(mBoundingBox.x, mBoundingBox.y,
                              mBoundingBox.width, mBoundingBox.height));
-      if (mOp == CanvasRenderingContext2D::TEXT_DRAW_OPERATION_FILL) {
+      if (mOp == CanvasRenderingContext2D::TextDrawOperation::FILL) {
         AdjustedTarget(mCtx, &bounds)->
           FillGlyphs(scaledFont, buffer,
                      CanvasGeneralPattern().
-                       ForStyle(mCtx, CanvasRenderingContext2D::STYLE_FILL, mCtx->mTarget),
+                       ForStyle(mCtx, CanvasRenderingContext2D::Style::FILL, mCtx->mTarget),
                      DrawOptions(mState->globalAlpha, mCtx->UsedOperation()),
                      renderingOptions);
-      } else if (mOp == CanvasRenderingContext2D::TEXT_DRAW_OPERATION_STROKE) {
+      } else if (mOp == CanvasRenderingContext2D::TextDrawOperation::STROKE) {
         // stroke glyphs one at a time to avoid poor CoreGraphics performance
         // when stroking a path with a very large number of points
         buffer.mGlyphs = &glyphBuf.front();
         buffer.mNumGlyphs = 1;
         const ContextState& state = *mState;
         AdjustedTarget target(mCtx, &bounds);
         const StrokeOptions strokeOpts(state.lineWidth, state.lineJoin,
                                        state.lineCap, state.miterLimit,
                                        state.dash.Length(),
                                        state.dash.Elements(),
                                        state.dashOffset);
         CanvasGeneralPattern cgp;
         const Pattern& patForStyle
-          (cgp.ForStyle(mCtx, CanvasRenderingContext2D::STYLE_STROKE, mCtx->mTarget));
+          (cgp.ForStyle(mCtx, CanvasRenderingContext2D::Style::STROKE, mCtx->mTarget));
         const DrawOptions drawOpts(state.globalAlpha, mCtx->UsedOperation());
 
         for (unsigned i = glyphBuf.size(); i > 0; --i) {
           RefPtr<Path> path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget);
           target->Stroke(path, patForStyle, strokeOpts, drawOpts);
           buffer.mGlyphs++;
         }
       }
@@ -2814,58 +2814,58 @@ CanvasRenderingContext2D::DrawOrMeasureT
   }
 
   float totalWidth = float(totalWidthCoord) / processor.mAppUnitsPerDevPixel;
   if (aWidth) {
     *aWidth = totalWidth;
   }
 
   // if only measuring, don't need to do any more work
-  if (aOp==TEXT_DRAW_OPERATION_MEASURE) {
+  if (aOp==TextDrawOperation::MEASURE) {
     return NS_OK;
   }
 
   // offset pt.x based on text align
   gfxFloat anchorX;
 
-  if (state.textAlign == TEXT_ALIGN_CENTER) {
+  if (state.textAlign == TextAlign::CENTER) {
     anchorX = .5;
-  } else if (state.textAlign == TEXT_ALIGN_LEFT ||
-            (!isRTL && state.textAlign == TEXT_ALIGN_START) ||
-            (isRTL && state.textAlign == TEXT_ALIGN_END)) {
+  } else if (state.textAlign == TextAlign::LEFT ||
+            (!isRTL && state.textAlign == TextAlign::START) ||
+            (isRTL && state.textAlign == TextAlign::END)) {
     anchorX = 0;
   } else {
     anchorX = 1;
   }
 
   processor.mPt.x -= anchorX * totalWidth;
 
   // offset pt.y based on text baseline
   processor.mFontgrp->UpdateFontList(); // ensure user font generation is current
   NS_ASSERTION(processor.mFontgrp->FontListLength()>0, "font group contains no fonts");
   const gfxFont::Metrics& fontMetrics = processor.mFontgrp->GetFontAt(0)->GetMetrics();
 
   gfxFloat anchorY;
 
   switch (state.textBaseline)
   {
-  case TEXT_BASELINE_HANGING:
+  case TextBaseline::HANGING:
       // fall through; best we can do with the information available
-  case TEXT_BASELINE_TOP:
+  case TextBaseline::TOP:
     anchorY = fontMetrics.emAscent;
     break;
-  case TEXT_BASELINE_MIDDLE:
+  case TextBaseline::MIDDLE:
     anchorY = (fontMetrics.emAscent - fontMetrics.emDescent) * .5f;
     break;
-  case TEXT_BASELINE_IDEOGRAPHIC:
+  case TextBaseline::IDEOGRAPHIC:
     // fall through; best we can do with the information available
-  case TEXT_BASELINE_ALPHABETIC:
+  case TextBaseline::ALPHABETIC:
     anchorY = 0;
     break;
-  case TEXT_BASELINE_BOTTOM:
+  case TextBaseline::BOTTOM:
     anchorY = -fontMetrics.emDescent;
     break;
   default:
     MOZ_CRASH("unexpected TextBaseline");
   }
 
   processor.mPt.y += anchorY;
 
@@ -2909,17 +2909,17 @@ CanvasRenderingContext2D::DrawOrMeasureT
                                     nullptr,
                                     0,
                                     nullptr,
                                     &bidiEngine);
 
 
   mTarget->SetTransform(oldTransform);
 
-  if (aOp == CanvasRenderingContext2D::TEXT_DRAW_OPERATION_FILL &&
+  if (aOp == CanvasRenderingContext2D::TextDrawOperation::FILL &&
       !doDrawShadow) {
     RedrawUser(boundingBox);
     return NS_OK;
   }
 
   Redraw();
   return NS_OK;
 }
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -19,16 +19,17 @@
 #include "mozilla/dom/CanvasGradient.h"
 #include "mozilla/dom/CanvasRenderingContext2DBinding.h"
 #include "mozilla/dom/CanvasPattern.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/gfx/2D.h"
 #include "gfx2DGlue.h"
 #include "imgIEncoder.h"
 #include "nsLayoutUtils.h"
+#include "mozilla/EnumeratedArray.h"
 
 class nsGlobalWindow;
 class nsXULElement;
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 class SurfaceStream;
@@ -153,32 +154,32 @@ public:
   }
 
   void GetGlobalCompositeOperation(nsAString& op, mozilla::ErrorResult& error);
   void SetGlobalCompositeOperation(const nsAString& op,
                                    mozilla::ErrorResult& error);
 
   void GetStrokeStyle(OwningStringOrCanvasGradientOrCanvasPattern& value)
   {
-    GetStyleAsUnion(value, STYLE_STROKE);
+    GetStyleAsUnion(value, Style::STROKE);
   }
 
   void SetStrokeStyle(const StringOrCanvasGradientOrCanvasPattern& value)
   {
-    SetStyleFromUnion(value, STYLE_STROKE);
+    SetStyleFromUnion(value, Style::STROKE);
   }
 
   void GetFillStyle(OwningStringOrCanvasGradientOrCanvasPattern& value)
   {
-    GetStyleAsUnion(value, STYLE_FILL);
+    GetStyleAsUnion(value, Style::FILL);
   }
 
   void SetFillStyle(const StringOrCanvasGradientOrCanvasPattern& value)
   {
-    SetStyleFromUnion(value, STYLE_FILL);
+    SetStyleFromUnion(value, Style::FILL);
   }
 
   already_AddRefed<CanvasGradient>
     CreateLinearGradient(double x0, double y0, double x1, double y1);
   already_AddRefed<CanvasGradient>
     CreateRadialGradient(double x0, double y0, double r0, double x1, double y1,
                          double r1, ErrorResult& aError);
   already_AddRefed<CanvasPattern>
@@ -487,27 +488,27 @@ public:
   // this rect is in mTarget's current user space
   void RedrawUser(const gfxRect &r);
 
   // nsISupports interface + CC
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(CanvasRenderingContext2D)
 
-  enum CanvasMultiGetterType {
-    CMG_STYLE_STRING = 0,
-    CMG_STYLE_PATTERN = 1,
-    CMG_STYLE_GRADIENT = 2
-  };
+  MOZ_BEGIN_NESTED_ENUM_CLASS(CanvasMultiGetterType, uint8_t)
+    STRING = 0,
+    PATTERN = 1,
+    GRADIENT = 2
+  MOZ_END_NESTED_ENUM_CLASS(CanvasMultiGetterType)
 
-  enum Style {
-    STYLE_STROKE = 0,
-    STYLE_FILL,
-    STYLE_MAX
-  };
+  MOZ_BEGIN_NESTED_ENUM_CLASS(Style, uint8_t)
+    STROKE = 0,
+    FILL,
+    MAX
+  MOZ_END_NESTED_ENUM_CLASS(Style)
 
   nsINode* GetParentObject()
   {
     return mCanvasElement;
   }
 
   void LineTo(const mozilla::gfx::Point& aPoint)
   {
@@ -805,71 +806,79 @@ protected:
     }
     if (mDocShell) {
       return mDocShell->GetPresShell();
     }
     return nullptr;
   }
 
   // text
-  enum TextAlign {
-    TEXT_ALIGN_START,
-    TEXT_ALIGN_END,
-    TEXT_ALIGN_LEFT,
-    TEXT_ALIGN_RIGHT,
-    TEXT_ALIGN_CENTER
-  };
+
+public: // These enums are public only to accomodate non-C++11 legacy path of
+        // MOZ_FINISH_NESTED_ENUM_CLASS. Can move back to protected as soon
+        // as that legacy path is dropped.
+  MOZ_BEGIN_NESTED_ENUM_CLASS(TextAlign, uint8_t)
+    START,
+    END,
+    LEFT,
+    RIGHT,
+    CENTER
+  MOZ_END_NESTED_ENUM_CLASS(TextAlign)
 
-  enum TextBaseline {
-    TEXT_BASELINE_TOP,
-    TEXT_BASELINE_HANGING,
-    TEXT_BASELINE_MIDDLE,
-    TEXT_BASELINE_ALPHABETIC,
-    TEXT_BASELINE_IDEOGRAPHIC,
-    TEXT_BASELINE_BOTTOM
-  };
+  MOZ_BEGIN_NESTED_ENUM_CLASS(TextBaseline, uint8_t)
+    TOP,
+    HANGING,
+    MIDDLE,
+    ALPHABETIC,
+    IDEOGRAPHIC,
+    BOTTOM
+  MOZ_END_NESTED_ENUM_CLASS(TextBaseline)
 
-  gfxFontGroup *GetCurrentFontStyle();
+  MOZ_BEGIN_NESTED_ENUM_CLASS(TextDrawOperation, uint8_t)
+    FILL,
+    STROKE,
+    MEASURE
+  MOZ_END_NESTED_ENUM_CLASS(TextDrawOperation)
 
-  enum TextDrawOperation {
-    TEXT_DRAW_OPERATION_FILL,
-    TEXT_DRAW_OPERATION_STROKE,
-    TEXT_DRAW_OPERATION_MEASURE
-  };
+protected:
+  gfxFontGroup *GetCurrentFontStyle();
 
   /*
     * Implementation of the fillText, strokeText, and measure functions with
     * the operation abstracted to a flag.
     */
   nsresult DrawOrMeasureText(const nsAString& text,
                              float x,
                              float y,
                              const Optional<double>& maxWidth,
                              TextDrawOperation op,
                              float* aWidth);
 
   // state stack handling
   class ContextState {
   public:
-    ContextState() : textAlign(TEXT_ALIGN_START),
-                     textBaseline(TEXT_BASELINE_ALPHABETIC),
+    ContextState() : textAlign(TextAlign::START),
+                     textBaseline(TextBaseline::ALPHABETIC),
                      lineWidth(1.0f),
                      miterLimit(10.0f),
                      globalAlpha(1.0f),
                      shadowBlur(0.0),
                      dashOffset(0.0f),
                      op(mozilla::gfx::CompositionOp::OP_OVER),
                      fillRule(mozilla::gfx::FillRule::FILL_WINDING),
                      lineCap(mozilla::gfx::CapStyle::BUTT),
                      lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
                      imageSmoothingEnabled(true)
     { }
 
     ContextState(const ContextState& other)
         : fontGroup(other.fontGroup),
+          gradientStyles(other.gradientStyles),
+          patternStyles(other.patternStyles),
+          colorStyles(other.colorStyles),
           font(other.font),
           textAlign(other.textAlign),
           textBaseline(other.textBaseline),
           shadowColor(other.shadowColor),
           transform(other.transform),
           shadowOffset(other.shadowOffset),
           lineWidth(other.lineWidth),
           miterLimit(other.miterLimit),
@@ -877,23 +886,17 @@ protected:
           shadowBlur(other.shadowBlur),
           dash(other.dash),
           dashOffset(other.dashOffset),
           op(other.op),
           fillRule(other.fillRule),
           lineCap(other.lineCap),
           lineJoin(other.lineJoin),
           imageSmoothingEnabled(other.imageSmoothingEnabled)
-    {
-      for (int i = 0; i < STYLE_MAX; i++) {
-        colorStyles[i] = other.colorStyles[i];
-        gradientStyles[i] = other.gradientStyles[i];
-        patternStyles[i] = other.patternStyles[i];
-      }
-    }
+    { }
 
     void SetColorStyle(Style whichStyle, nscolor color)
     {
       colorStyles[whichStyle] = color;
       gradientStyles[whichStyle] = nullptr;
       patternStyles[whichStyle] = nullptr;
     }
 
@@ -916,24 +919,24 @@ protected:
     {
       return !(patternStyles[whichStyle] || gradientStyles[whichStyle]);
     }
 
 
     std::vector<mozilla::RefPtr<mozilla::gfx::Path> > clipsPushed;
 
     nsRefPtr<gfxFontGroup> fontGroup;
-    nsRefPtr<CanvasGradient> gradientStyles[STYLE_MAX];
-    nsRefPtr<CanvasPattern> patternStyles[STYLE_MAX];
+    EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasGradient>> gradientStyles;
+    EnumeratedArray<Style, Style::MAX, nsRefPtr<CanvasPattern>> patternStyles;
+    EnumeratedArray<Style, Style::MAX, nscolor> colorStyles;
 
     nsString font;
     TextAlign textAlign;
     TextBaseline textBaseline;
 
-    nscolor colorStyles[STYLE_MAX];
     nscolor shadowColor;
 
     mozilla::gfx::Matrix transform;
     mozilla::gfx::Point shadowOffset;
     mozilla::gfx::Float lineWidth;
     mozilla::gfx::Float miterLimit;
     mozilla::gfx::Float globalAlpha;
     mozilla::gfx::Float shadowBlur;
@@ -982,12 +985,18 @@ protected:
       *perDevPixel = devPixel;
     if (perCSSPixel)
       *perCSSPixel = cssPixel;
   }
 
   friend struct CanvasBidiProcessor;
 };
 
+MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::CanvasMultiGetterType)
+MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::Style)
+MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextAlign)
+MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextBaseline)
+MOZ_FINISH_NESTED_ENUM_CLASS(CanvasRenderingContext2D::TextDrawOperation)
+
 }
 }
 
 #endif /* CanvasRenderingContext2D_h */
--- a/content/canvas/src/ImageEncoder.cpp
+++ b/content/canvas/src/ImageEncoder.cpp
@@ -76,17 +76,17 @@ private:
   nsAutoString mType;
   void* mImgData;
   nsCOMPtr<nsIScriptContext> mScriptContext;
   nsCOMPtr<nsIThread> mEncoderThread;
   nsRefPtr<FileCallback> mCallback;
   bool mFailed;
 };
 
-NS_IMPL_ISUPPORTS1(EncodingCompleteEvent, nsIRunnable);
+NS_IMPL_ISUPPORTS(EncodingCompleteEvent, nsIRunnable);
 
 class EncodingRunnable : public nsRunnable
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   EncodingRunnable(const nsAString& aType,
                    const nsAString& aOptions,
@@ -170,17 +170,17 @@ private:
   nsAutoArrayPtr<uint8_t> mImageBuffer;
   nsCOMPtr<imgIEncoder> mEncoder;
   nsRefPtr<EncodingCompleteEvent> mEncodingCompleteEvent;
   int32_t mFormat;
   const nsIntSize mSize;
   bool mUsingCustomOptions;
 };
 
-NS_IMPL_ISUPPORTS1(EncodingRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS(EncodingRunnable, nsIRunnable)
 
 /* static */
 nsresult
 ImageEncoder::ExtractData(nsAString& aType,
                           const nsAString& aOptions,
                           const nsIntSize aSize,
                           nsICanvasRenderingContextInternal* aContext,
                           nsIInputStream** aStream)
--- a/content/canvas/src/WebGL2Context.cpp
+++ b/content/canvas/src/WebGL2Context.cpp
@@ -58,24 +58,24 @@ WebGL2Context::WrapObject(JSContext *cx)
 // WebGL 2 initialisation
 
 bool
 WebGLContext::InitWebGL2()
 {
     MOZ_ASSERT(IsWebGL2(), "WebGLContext is not a WebGL 2 context!");
 
     const WebGLExtensionID sExtensionNativelySupportedArr[] = {
-        ANGLE_instanced_arrays,
-        OES_element_index_uint,
-        OES_standard_derivatives,
-        OES_texture_float,
-        OES_texture_float_linear,
-        OES_vertex_array_object,
-        WEBGL_depth_texture,
-        WEBGL_draw_buffers
+        WebGLExtensionID::ANGLE_instanced_arrays,
+        WebGLExtensionID::OES_element_index_uint,
+        WebGLExtensionID::OES_standard_derivatives,
+        WebGLExtensionID::OES_texture_float,
+        WebGLExtensionID::OES_texture_float_linear,
+        WebGLExtensionID::OES_vertex_array_object,
+        WebGLExtensionID::WEBGL_depth_texture,
+        WebGLExtensionID::WEBGL_draw_buffers
     };
     const GLFeature sFeatureRequiredArr[] = {
         GLFeature::blend_minmax,
         GLFeature::instanced_non_arrays,
         GLFeature::transform_feedback
     };
 
     // check WebGL extensions that are supposed to be natively supported
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -52,16 +52,17 @@
 #include "mozilla/Telemetry.h"
 
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/ProcessPriorityManager.h"
+#include "mozilla/EnumeratedArrayCycleCollection.h"
 
 #include "Layers.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include "mozilla/layers/ShadowLayers.h"
 #endif
 
 using namespace mozilla;
@@ -257,20 +258,20 @@ WebGLContext::DestroyResourcesAndContext
     mBlackTransparentTextureCubeMap = nullptr;
 
     if (mFakeVertexAttrib0BufferObject) {
         gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
     }
 
     // disable all extensions except "WEBGL_lose_context". see bug #927969
     // spec: http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
-    for (size_t i = 0; i < size_t(WebGLExtensionID_max); ++i) {
+    for (size_t i = 0; i < size_t(WebGLExtensionID::Max); ++i) {
         WebGLExtensionID extension = WebGLExtensionID(i);
 
-        if (!IsExtensionEnabled(extension) || (extension == WEBGL_lose_context))
+        if (!IsExtensionEnabled(extension) || (extension == WebGLExtensionID::WEBGL_lose_context))
             continue;
 
         mExtensions[extension]->MarkLost();
         mExtensions[extension] = nullptr;
     }
 
     // We just got rid of everything, so the context had better
     // have been going away.
@@ -987,17 +988,17 @@ static bool IsShadowCorrect(float shadow
 void
 WebGLContext::ForceClearFramebufferWithDefaultValues(GLbitfield mask, const bool colorAttachmentsMask[sMaxColorAttachments])
 {
     MakeContextCurrent();
 
     bool initializeColorBuffer = 0 != (mask & LOCAL_GL_COLOR_BUFFER_BIT);
     bool initializeDepthBuffer = 0 != (mask & LOCAL_GL_DEPTH_BUFFER_BIT);
     bool initializeStencilBuffer = 0 != (mask & LOCAL_GL_STENCIL_BUFFER_BIT);
-    bool drawBuffersIsEnabled = IsExtensionEnabled(WEBGL_draw_buffers);
+    bool drawBuffersIsEnabled = IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers);
 
     GLenum currentDrawBuffers[WebGLContext::sMaxColorAttachments];
 
     // Fun GL fact: No need to worry about the viewport here, glViewport is just
     // setting up a coordinates transformation, it doesn't affect glClear at all.
 
 #ifdef DEBUG
     // Scope to hide our variables.
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -19,16 +19,17 @@
 #include "nsICanvasRenderingContextInternal.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
 #include "nsWrapperCache.h"
 #include "nsIObserver.h"
 #include "nsLayoutUtils.h"
 
 #include "GLContextProvider.h"
 
+#include "mozilla/EnumeratedArray.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/gfx/2D.h"
 
 #ifdef XP_MACOSX
 #include "ForceDiscreteGPUHelperCGL.h"
 #endif
@@ -887,43 +888,21 @@ protected:
         // The context is lost, an event has been sent to the script, and the
         // script correctly handled the event. We are waiting for the context to
         // be restored.
         ContextLostAwaitingRestore
     };
 
     // -------------------------------------------------------------------------
     // WebGL extensions (implemented in WebGLContextExtensions.cpp)
-    enum WebGLExtensionID {
-        EXT_color_buffer_half_float,
-        EXT_frag_depth,
-        EXT_sRGB,
-        EXT_texture_filter_anisotropic,
-        OES_element_index_uint,
-        OES_standard_derivatives,
-        OES_texture_float,
-        OES_texture_float_linear,
-        OES_texture_half_float,
-        OES_texture_half_float_linear,
-        OES_vertex_array_object,
-        WEBGL_color_buffer_float,
-        WEBGL_compressed_texture_atc,
-        WEBGL_compressed_texture_etc1,
-        WEBGL_compressed_texture_pvrtc,
-        WEBGL_compressed_texture_s3tc,
-        WEBGL_debug_renderer_info,
-        WEBGL_debug_shaders,
-        WEBGL_depth_texture,
-        WEBGL_lose_context,
-        WEBGL_draw_buffers,
-        ANGLE_instanced_arrays,
-        WebGLExtensionID_max,
-        WebGLExtensionID_unknown_extension
-    };
-    nsTArray<nsRefPtr<WebGLExtensionBase> > mExtensions;
+    typedef EnumeratedArray<WebGLExtensionID,
+                            WebGLExtensionID::Max,
+                            nsRefPtr<WebGLExtensionBase>> ExtensionsArrayType;
+
+    ExtensionsArrayType mExtensions;
 
     // enable an extension. the extension should not be enabled before.
     void EnableExtension(WebGLExtensionID ext);
 
     // returns true if the extension has been enabled by calling getExtension.
     bool IsExtensionEnabled(WebGLExtensionID ext) const;
 
     // returns true if the extension is supported for this JSContext (this decides what getSupportedExtensions exposes)
--- a/content/canvas/src/WebGLContextDraw.cpp
+++ b/content/canvas/src/WebGLContextDraw.cpp
@@ -24,17 +24,17 @@ using namespace mozilla::gl;
 // For a Tegra workaround.
 static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
 
 bool
 WebGLContext::DrawInstanced_check(const char* info)
 {
     // This restriction was removed in GLES3, so WebGL2 shouldn't have it.
     if (!IsWebGL2() &&
-        IsExtensionEnabled(ANGLE_instanced_arrays) &&
+        IsExtensionEnabled(WebGLExtensionID::ANGLE_instanced_arrays) &&
         !mBufferFetchingHasPerVertex)
     {
         /* http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_instanced_arrays.txt
          *  If all of the enabled vertex attribute arrays that are bound to active
          *  generic attributes in the program have a non-zero divisor, the draw
          *  call should return INVALID_OPERATION.
          *
          * NB: This also appears to apply to NV_instanced_arrays, though the
@@ -189,17 +189,17 @@ WebGLContext::DrawElements_check(GLsizei
             return false;
         }
         first = byteOffset / 2;
     }
     else if (type == LOCAL_GL_UNSIGNED_BYTE) {
         checked_byteCount = count;
         first = byteOffset;
     }
-    else if (type == LOCAL_GL_UNSIGNED_INT && IsExtensionEnabled(OES_element_index_uint)) {
+    else if (type == LOCAL_GL_UNSIGNED_INT && IsExtensionEnabled(WebGLExtensionID::OES_element_index_uint)) {
         checked_byteCount = 4 * CheckedUint32(count);
         if (byteOffset % 4 != 0) {
             ErrorInvalidOperation("%s: invalid byteOffset for UNSIGNED_INT (must be a multiple of 4)", info);
             return false;
         }
         first = byteOffset / 4;
     }
     else {
--- a/content/canvas/src/WebGLContextExtensions.cpp
+++ b/content/canvas/src/WebGLContextExtensions.cpp
@@ -10,56 +10,57 @@
 
 #include "nsString.h"
 #include "mozilla/Preferences.h"
 #include "AccessCheck.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 
-// must match WebGLContext::WebGLExtensionID
-static const char *sExtensionNames[] = {
-    "EXT_color_buffer_half_float",
-    "EXT_frag_depth",
-    "EXT_sRGB",
-    "EXT_texture_filter_anisotropic",
-    "OES_element_index_uint",
-    "OES_standard_derivatives",
-    "OES_texture_float",
-    "OES_texture_float_linear",
-    "OES_texture_half_float",
-    "OES_texture_half_float_linear",
-    "OES_vertex_array_object",
-    "WEBGL_color_buffer_float",
-    "WEBGL_compressed_texture_atc",
-    "WEBGL_compressed_texture_etc1",
-    "WEBGL_compressed_texture_pvrtc",
-    "WEBGL_compressed_texture_s3tc",
-    "WEBGL_debug_renderer_info",
-    "WEBGL_debug_shaders",
-    "WEBGL_depth_texture",
-    "WEBGL_lose_context",
-    "WEBGL_draw_buffers",
-    "ANGLE_instanced_arrays"
-};
-
 /* static */ const char*
 WebGLContext::GetExtensionString(WebGLExtensionID ext)
 {
-    static_assert(MOZ_ARRAY_LENGTH(sExtensionNames) == size_t(WebGLExtensionID_max),
-                  "Mismatched lengths for sFeatureInfoInfos and GLFeature enums");
+    // must match WebGLExtensionID.
+    // Once we can use variadic templates, EnumeratedArray should get a constructor
+    // allowing to initialize it directly without using this auxiliary plain array.
+    static const char *kExtensionNames[] = {
+        "ANGLE_instanced_arrays",
+        "EXT_color_buffer_half_float",
+        "EXT_frag_depth",
+        "EXT_sRGB",
+        "EXT_texture_filter_anisotropic",
+        "OES_element_index_uint",
+        "OES_standard_derivatives",
+        "OES_texture_float",
+        "OES_texture_float_linear",
+        "OES_texture_half_float",
+        "OES_texture_half_float_linear",
+        "OES_vertex_array_object",
+        "WEBGL_color_buffer_float",
+        "WEBGL_compressed_texture_atc",
+        "WEBGL_compressed_texture_etc1",
+        "WEBGL_compressed_texture_pvrtc",
+        "WEBGL_compressed_texture_s3tc",
+        "WEBGL_debug_renderer_info",
+        "WEBGL_debug_shaders",
+        "WEBGL_depth_texture",
+        "WEBGL_draw_buffers",
+        "WEBGL_lose_context"
+    };
 
-    MOZ_ASSERT(ext < WebGLExtensionID_max, "unknown extension!");
+    typedef EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max, const char*>
+            names_array_t;
+    static const names_array_t kExtensionNamesEnumeratedArray(kExtensionNames);
 
-    return sExtensionNames[ext];
+    return kExtensionNamesEnumeratedArray[ext];
 }
 
 bool
 WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const {
-    return mExtensions.SafeElementAt(ext);
+    return mExtensions[ext];
 }
 
 bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
 {
     bool allowPrivilegedExts = false;
 
     // Chrome contexts need access to debug information even when
     // webgl.disable-extensions is set. This is used in the graphics
@@ -67,19 +68,19 @@ bool WebGLContext::IsExtensionSupported(
     if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx)))
         allowPrivilegedExts = true;
 
     if (Preferences::GetBool("webgl.enable-privileged-extensions", false))
         allowPrivilegedExts = true;
 
     if (allowPrivilegedExts) {
         switch (ext) {
-            case WEBGL_debug_renderer_info:
+            case WebGLExtensionID::WEBGL_debug_renderer_info:
                 return true;
-            case WEBGL_debug_shaders:
+            case WebGLExtensionID::WEBGL_debug_shaders:
                 return true;
             default:
                 // For warnings-as-errors.
                 break;
         }
     }
 
     return IsExtensionSupported(ext);
@@ -87,74 +88,74 @@ bool WebGLContext::IsExtensionSupported(
 
 bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
 {
     if (mDisableExtensions) {
         return false;
     }
 
     switch (ext) {
-        case OES_element_index_uint:
+        case WebGLExtensionID::OES_element_index_uint:
             return gl->IsSupported(GLFeature::element_index_uint);
-        case OES_standard_derivatives:
+        case WebGLExtensionID::OES_standard_derivatives:
             return gl->IsSupported(GLFeature::standard_derivatives);
-        case WEBGL_lose_context:
+        case WebGLExtensionID::WEBGL_lose_context:
             // We always support this extension.
             return true;
-        case OES_texture_float:
+        case WebGLExtensionID::OES_texture_float:
             return gl->IsSupported(GLFeature::texture_float);
-        case OES_texture_float_linear:
+        case WebGLExtensionID::OES_texture_float_linear:
             return gl->IsSupported(GLFeature::texture_float_linear);
-        case OES_texture_half_float:
+        case WebGLExtensionID::OES_texture_half_float:
             // If we have Feature::texture_half_float, we must not be on ES2
             // and need to translate HALF_FLOAT_OES -> HALF_FLOAT.  We do that
             // right before making the relevant calls.
             return gl->IsExtensionSupported(GLContext::OES_texture_half_float) ||
                    gl->IsSupported(GLFeature::texture_half_float);
-        case OES_texture_half_float_linear:
+        case WebGLExtensionID::OES_texture_half_float_linear:
             return gl->IsSupported(GLFeature::texture_half_float_linear);
-        case WEBGL_color_buffer_float:
+        case WebGLExtensionID::WEBGL_color_buffer_float:
             return WebGLExtensionColorBufferFloat::IsSupported(this);
-        case EXT_color_buffer_half_float:
+        case WebGLExtensionID::EXT_color_buffer_half_float:
             return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
-        case OES_vertex_array_object:
+        case WebGLExtensionID::OES_vertex_array_object:
             return WebGLExtensionVertexArray::IsSupported(this);
-        case EXT_texture_filter_anisotropic:
+        case WebGLExtensionID::EXT_texture_filter_anisotropic:
             return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
-        case WEBGL_compressed_texture_s3tc:
+        case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
             if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc)) {
                 return true;
             }
             else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
                      gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
                      gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
             {
                 return true;
             }
             return false;
-        case WEBGL_compressed_texture_atc:
+        case WebGLExtensionID::WEBGL_compressed_texture_atc:
             return gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture);
-        case WEBGL_compressed_texture_etc1:
+        case WebGLExtensionID::WEBGL_compressed_texture_etc1:
             return gl->IsExtensionSupported(GLContext::OES_compressed_ETC1_RGB8_texture);
-        case WEBGL_compressed_texture_pvrtc:
+        case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
             return gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc);
-        case WEBGL_depth_texture:
+        case WebGLExtensionID::WEBGL_depth_texture:
             // WEBGL_depth_texture supports DEPTH_STENCIL textures
             if (!gl->IsSupported(GLFeature::packed_depth_stencil)) {
                 return false;
             }
             return gl->IsSupported(GLFeature::depth_texture) ||
                    gl->IsExtensionSupported(GLContext::ANGLE_depth_texture);
-        case ANGLE_instanced_arrays:
+        case WebGLExtensionID::ANGLE_instanced_arrays:
             return WebGLExtensionInstancedArrays::IsSupported(this);
-        case EXT_sRGB:
+        case WebGLExtensionID::EXT_sRGB:
             return WebGLExtensionSRGB::IsSupported(this);
-        case WEBGL_draw_buffers:
+        case WebGLExtensionID::WEBGL_draw_buffers:
             return WebGLExtensionDrawBuffers::IsSupported(this);
-        case EXT_frag_depth:
+        case WebGLExtensionID::EXT_frag_depth:
             return WebGLExtensionFragDepth::IsSupported(this);
         default:
             // For warnings-as-errors.
             break;
     }
 // Uncomment this switch for any new extensions
 #if 0
     if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
@@ -178,61 +179,61 @@ CompareWebGLExtensionName(const nsACStri
 JSObject*
 WebGLContext::GetExtension(JSContext *cx, const nsAString& aName, ErrorResult& rv)
 {
     if (IsContextLost())
         return nullptr;
 
     NS_LossyConvertUTF16toASCII name(aName);
 
-    WebGLExtensionID ext = WebGLExtensionID_unknown_extension;
+    WebGLExtensionID ext = WebGLExtensionID::Unknown;
 
     // step 1: figure what extension is wanted
-    for (size_t i = 0; i < size_t(WebGLExtensionID_max); i++)
+    for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++)
     {
         WebGLExtensionID extension = WebGLExtensionID(i);
 
         if (CompareWebGLExtensionName(name, GetExtensionString(extension))) {
             ext = extension;
             break;
         }
     }
 
-    if (ext == WebGLExtensionID_unknown_extension)
+    if (ext == WebGLExtensionID::Unknown)
     {
         /**
          * We keep backward compatibility for these deprecated vendor-prefixed
          * alias. Do not add new ones anymore. Hide it behind the
          * webgl.enable-draft-extensions flag instead.
          */
         if (CompareWebGLExtensionName(name, "MOZ_WEBGL_lose_context")) {
-            ext = WEBGL_lose_context;
+            ext = WebGLExtensionID::WEBGL_lose_context;
         }
         else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc")) {
-            ext = WEBGL_compressed_texture_s3tc;
+            ext = WebGLExtensionID::WEBGL_compressed_texture_s3tc;
         }
         else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc")) {
-            ext = WEBGL_compressed_texture_atc;
+            ext = WebGLExtensionID::WEBGL_compressed_texture_atc;
         }
         else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
-            ext = WEBGL_compressed_texture_pvrtc;
+            ext = WebGLExtensionID::WEBGL_compressed_texture_pvrtc;
         }
         else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
-            ext = WEBGL_depth_texture;
+            ext = WebGLExtensionID::WEBGL_depth_texture;
         }
 
-        if (ext != WebGLExtensionID_unknown_extension) {
+        if (ext != WebGLExtensionID::Unknown) {
             GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension strings are deprecated. "
                             "Support for them will be removed in the future. Use unprefixed extension strings. "
                             "To get draft extensions, set the webgl.enable-draft-extensions preference.",
                             name.get());
         }
     }
 
-    if (ext == WebGLExtensionID_unknown_extension) {
+    if (ext == WebGLExtensionID::Unknown) {
         return nullptr;
     }
 
     // step 2: check if the extension is supported
     if (!IsExtensionSupported(cx, ext)) {
         return nullptr;
     }
 
@@ -242,86 +243,84 @@ WebGLContext::GetExtension(JSContext *cx
     }
 
     return WebGLObjectAsJSObject(cx, mExtensions[ext].get(), rv);
 }
 
 void
 WebGLContext::EnableExtension(WebGLExtensionID ext)
 {
-    mExtensions.EnsureLengthAtLeast(ext + 1);
-
     MOZ_ASSERT(IsExtensionEnabled(ext) == false);
 
     WebGLExtensionBase* obj = nullptr;
     switch (ext) {
-        case OES_element_index_uint:
+        case WebGLExtensionID::OES_element_index_uint:
             obj = new WebGLExtensionElementIndexUint(this);
             break;
-        case OES_standard_derivatives:
+        case WebGLExtensionID::OES_standard_derivatives:
             obj = new WebGLExtensionStandardDerivatives(this);
             break;
-        case EXT_texture_filter_anisotropic:
+        case WebGLExtensionID::EXT_texture_filter_anisotropic:
             obj = new WebGLExtensionTextureFilterAnisotropic(this);
             break;
-        case WEBGL_lose_context:
+        case WebGLExtensionID::WEBGL_lose_context:
             obj = new WebGLExtensionLoseContext(this);
             break;
-        case WEBGL_compressed_texture_s3tc:
+        case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
             obj = new WebGLExtensionCompressedTextureS3TC(this);
             break;
-        case WEBGL_compressed_texture_atc:
+        case WebGLExtensionID::WEBGL_compressed_texture_atc:
             obj = new WebGLExtensionCompressedTextureATC(this);
             break;
-        case WEBGL_compressed_texture_etc1:
+        case WebGLExtensionID::WEBGL_compressed_texture_etc1:
             obj = new WebGLExtensionCompressedTextureETC1(this);
             break;
-        case WEBGL_compressed_texture_pvrtc:
+        case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
             obj = new WebGLExtensionCompressedTexturePVRTC(this);
             break;
-        case WEBGL_debug_renderer_info:
+        case WebGLExtensionID::WEBGL_debug_renderer_info:
             obj = new WebGLExtensionDebugRendererInfo(this);
             break;
-        case WEBGL_debug_shaders:
+        case WebGLExtensionID::WEBGL_debug_shaders:
             obj = new WebGLExtensionDebugShaders(this);
             break;
-        case WEBGL_depth_texture:
+        case WebGLExtensionID::WEBGL_depth_texture:
             obj = new WebGLExtensionDepthTexture(this);
             break;
-        case OES_texture_float:
+        case WebGLExtensionID::OES_texture_float:
             obj = new WebGLExtensionTextureFloat(this);
             break;
-        case OES_texture_float_linear:
+        case WebGLExtensionID::OES_texture_float_linear:
             obj = new WebGLExtensionTextureFloatLinear(this);
             break;
-        case OES_texture_half_float:
+        case WebGLExtensionID::OES_texture_half_float:
             obj = new WebGLExtensionTextureHalfFloat(this);
             break;
-        case OES_texture_half_float_linear:
+        case WebGLExtensionID::OES_texture_half_float_linear:
             obj = new WebGLExtensionTextureHalfFloatLinear(this);
             break;
-        case WEBGL_color_buffer_float:
+        case WebGLExtensionID::WEBGL_color_buffer_float:
             obj = new WebGLExtensionColorBufferFloat(this);
             break;
-        case EXT_color_buffer_half_float:
+        case WebGLExtensionID::EXT_color_buffer_half_float:
             obj = new WebGLExtensionColorBufferHalfFloat(this);
             break;
-        case WEBGL_draw_buffers:
+        case WebGLExtensionID::WEBGL_draw_buffers:
             obj = new WebGLExtensionDrawBuffers(this);
             break;
-        case OES_vertex_array_object:
+        case WebGLExtensionID::OES_vertex_array_object:
             obj = new WebGLExtensionVertexArray(this);
             break;
-        case ANGLE_instanced_arrays:
+        case WebGLExtensionID::ANGLE_instanced_arrays:
             obj = new WebGLExtensionInstancedArrays(this);
             break;
-        case EXT_sRGB:
+        case WebGLExtensionID::EXT_sRGB:
             obj = new WebGLExtensionSRGB(this);
             break;
-        case EXT_frag_depth:
+        case WebGLExtensionID::EXT_frag_depth:
             obj = new WebGLExtensionFragDepth(this);
             break;
         default:
             MOZ_ASSERT(false, "should not get there.");
     }
 
     mExtensions[ext] = obj;
 }
@@ -330,34 +329,34 @@ void
 WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString> > &retval)
 {
     retval.SetNull();
     if (IsContextLost())
         return;
 
     nsTArray<nsString>& arr = retval.SetValue();
 
-    for (size_t i = 0; i < size_t(WebGLExtensionID_max); i++)
+    for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++)
     {
         WebGLExtensionID extension = WebGLExtensionID(i);
 
         if (IsExtensionSupported(cx, extension)) {
             arr.AppendElement(NS_ConvertUTF8toUTF16(GetExtensionString(extension)));
         }
     }
 
     /**
      * We keep backward compatibility for these deprecated vendor-prefixed
      * alias. Do not add new ones anymore. Hide it behind the
      * webgl.enable-draft-extensions flag instead.
      */
-    if (IsExtensionSupported(cx, WEBGL_lose_context))
+    if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_lose_context))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
-    if (IsExtensionSupported(cx, WEBGL_compressed_texture_s3tc))
+    if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_s3tc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
-    if (IsExtensionSupported(cx, WEBGL_compressed_texture_atc))
+    if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_atc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
-    if (IsExtensionSupported(cx, WEBGL_compressed_texture_pvrtc))
+    if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_pvrtc))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
-    if (IsExtensionSupported(cx, WEBGL_depth_texture))
+    if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_depth_texture))
         arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
 }
 
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -899,17 +899,17 @@ WebGLContext::GenerateMipmap(GLenum targ
 
     if (!tex->IsFirstImagePowerOfTwo())
         return ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
 
     GLenum internalFormat = tex->ImageInfoAt(imageTarget, 0).InternalFormat();
     if (IsTextureFormatCompressed(internalFormat))
         return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
 
-    if (IsExtensionEnabled(WEBGL_depth_texture) &&
+    if (IsExtensionEnabled(WebGLExtensionID::WEBGL_depth_texture) &&
         (IsGLDepthFormat(internalFormat) || IsGLDepthStencilFormat(internalFormat)))
     {
         return ErrorInvalidOperation("generateMipmap: "
                                      "A texture that has a base internal format of "
                                      "DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
     }
 
     if (!tex->AreAllLevel0ImageInfosEqual())
@@ -1083,17 +1083,17 @@ WebGLContext::GetFramebufferAttachmentPa
         ErrorInvalidOperation("getFramebufferAttachmentParameter: cannot query framebuffer 0");
         return JS::NullValue();
     }
 
     if (attachment != LOCAL_GL_DEPTH_ATTACHMENT &&
         attachment != LOCAL_GL_STENCIL_ATTACHMENT &&
         attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
     {
-        if (IsExtensionEnabled(WEBGL_draw_buffers))
+        if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
         {
             if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
                 attachment >= GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mGLMaxColorAttachments))
             {
                 ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: attachment", attachment);
                 return JS::NullValue();
             }
 
@@ -1108,35 +1108,35 @@ WebGLContext::GetFramebufferAttachmentPa
 
     MakeContextCurrent();
 
     const WebGLFramebuffer::Attachment& fba = mBoundFramebuffer->GetAttachment(attachment);
 
     if (fba.Renderbuffer()) {
         switch (pname) {
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
-                if (IsExtensionEnabled(EXT_sRGB)) {
+                if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB)) {
                     const GLenum internalFormat = fba.Renderbuffer()->InternalFormat();
                     return (internalFormat == LOCAL_GL_SRGB_EXT ||
                             internalFormat == LOCAL_GL_SRGB_ALPHA_EXT ||
                             internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT) ?
                         JS::NumberValue(uint32_t(LOCAL_GL_SRGB_EXT)) :
                         JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
                 }
                 break;
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                 return JS::NumberValue(uint32_t(LOCAL_GL_RENDERBUFFER));
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
                 return WebGLObjectAsJSValue(cx, fba.Renderbuffer(), rv);
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: {
-                if (!IsExtensionEnabled(EXT_color_buffer_half_float) &&
-                    !IsExtensionEnabled(WEBGL_color_buffer_float))
+                if (!IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float) &&
+                    !IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float))
                 {
                     break;
                 }
 
                 if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
                     ErrorInvalidOperation("getFramebufferAttachmentParameter: Cannot get component"
                                           " type of a depth-stencil attachment.");
                     return JS::NullValue();
@@ -1171,17 +1171,17 @@ WebGLContext::GetFramebufferAttachmentPa
             }
         }
 
         ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
         return JS::NullValue();
     } else if (fba.Texture()) {
         switch (pname) {
              case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT:
-                if (IsExtensionEnabled(EXT_sRGB)) {
+                if (IsExtensionEnabled(WebGLExtensionID::EXT_sRGB)) {
                     const GLenum internalFormat =
                         fba.Texture()->ImageInfoBase().InternalFormat();
                     return (internalFormat == LOCAL_GL_SRGB_EXT ||
                             internalFormat == LOCAL_GL_SRGB_ALPHA_EXT) ?
                         JS::NumberValue(uint32_t(LOCAL_GL_SRGB_EXT)) :
                         JS::NumberValue(uint32_t(LOCAL_GL_LINEAR));
                 }
                 break;
@@ -1198,18 +1198,18 @@ WebGLContext::GetFramebufferAttachmentPa
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: {
                 GLenum face = fba.TexImageTarget();
                 if (face == LOCAL_GL_TEXTURE_2D)
                     face = 0;
                 return JS::Int32Value(face);
             }
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: {
-                if (!IsExtensionEnabled(EXT_color_buffer_half_float) &&
-                    !IsExtensionEnabled(WEBGL_color_buffer_float))
+                if (!IsExtensionEnabled(WebGLExtensionID::EXT_color_buffer_half_float) &&
+                    !IsExtensionEnabled(WebGLExtensionID::WEBGL_color_buffer_float))
                 {
                     break;
                 }
 
                 if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
                     ErrorInvalidOperation("getFramebufferAttachmentParameter: cannot component"
                                           " type of depth-stencil attachments.");
                     return JS::NullValue();
@@ -1530,17 +1530,17 @@ void WebGLContext::TexParameter_base(GLe
                 case LOCAL_GL_REPEAT:
                     tex->SetWrapT(intParam);
                     break;
                 default:
                     pnameAndParamAreIncompatible = true;
             }
             break;
         case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
-            if (IsExtensionEnabled(EXT_texture_filter_anisotropic)) {
+            if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
                 if (floatParamPtr && floatParam < 1.f)
                     paramValueInvalid = true;
                 else if (intParamPtr && intParam < 1)
                     paramValueInvalid = true;
             }
             else
                 pnameAndParamAreIncompatible = true;
             break;
@@ -1593,17 +1593,17 @@ WebGLContext::GetTexParameter(GLenum tar
         case LOCAL_GL_TEXTURE_WRAP_S:
         case LOCAL_GL_TEXTURE_WRAP_T:
         {
             GLint i = 0;
             gl->fGetTexParameteriv(target, pname, &i);
             return JS::NumberValue(uint32_t(i));
         }
         case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
-            if (IsExtensionEnabled(EXT_texture_filter_anisotropic)) {
+            if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
                 GLfloat f = 0.f;
                 gl->fGetTexParameterfv(target, pname, &f);
                 return JS::DoubleValue(f);
             }
 
             ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
             break;
 
@@ -1790,17 +1790,17 @@ WebGLContext::Hint(GLenum target, GLenum
 
     bool isValid = false;
 
     switch (target) {
         case LOCAL_GL_GENERATE_MIPMAP_HINT:
             isValid = true;
             break;
         case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
-            if (IsExtensionEnabled(OES_standard_derivatives))
+            if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
                 isValid = true;
             break;
     }
 
     if (!isValid)
         return ErrorInvalidEnum("hint: invalid hint");
 
     MakeContextCurrent();
@@ -2113,18 +2113,18 @@ WebGLContext::ReadPixels(GLint x, GLint 
         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
             isReadTypeValid = true;
             bytesPerPixel = 2;
             requiredDataType = js::ArrayBufferView::TYPE_UINT16;
             break;
         case LOCAL_GL_FLOAT: